反序列化XML命名空间没有,但一类期待命名空间

问题描述:

重复:
Omitting all xml namespaces when serializing an object? 不一样的。我想在其他的方式:反序列化!反序列化XML命名空间没有,但一类期待命名空间


我有波纹管作为一个C#类:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.portalfiscal.inf.br/nfe")] 
[System.Xml.Serialization.XmlRootAttribute("NFe", Namespace = "http://www.portalfiscal.inf.br/nfe", IsNullable = false)] 
public partial class TNFe 
{ 

    private TNFeInfNFe infNFeField; 

    private SignatureType signatureField; 

    /// <remarks/> 
    public TNFeInfNFe infNFe 
    { ... 

我使用这个类的用户请求序列化/反序列化的XML文件。 但是我遇到了一个问题:在这个软件的新版本中添加了命名空间定义。 XML仍然是相同的,只添加名称空间定义。

例如,去年的版本...

<?xml version="1.0" encoding="utf-8" ?> 
    <NFe> 
    <infNFe version="1.10"> 
     ... 

和新版本...

<?xml version="1.0" encoding="utf-8" ?> 
    <NFe xmlns="http://www.portalfiscal.inf.br/nfe"> 
    <infNFe version="2.10"> 
     ... 

我需要加载使用和不使用这些命名空间的XML文件。 我有很多嵌套类,每个都有自己的名称空间定义。

我想使用相同的类都为XML,有和没有命名空间。

我试着创建一个XmlTextReader并覆盖NamespaceURI方法,但我仍然收到一个没有太多信息的异常。我认为.NET引擎正试图强制对XML的类名称空间定义。

+0

嗨,是你的查询解决? – 2014-08-13 10:03:13

+0

Arijit,我用不同的方法解决了它。不幸的是,没有办法按我想要的方式做我想做的事(尽可能少使用代码)。所以我使用XmlTextReader来处理一些Web服务,而其他人则使用字符串对整个Xml进行序列化,并使用String.Replace删除未使用的名称空间。不是有史以来最好的事情,但事实证明它也很好。 – rodrigogq 2014-08-14 16:38:10

+0

感谢您的回复,实际上我的问题看起来与您类似,下面给出的答案是行不通的,我猜。 你能证明你是如何做到的吗? 为什么微软没有想到这是4年? – 2014-08-15 12:40:15

我遇到了类似的代理类挑战。由于我不会涉及的原因,我需要使用Web服务器上的XmlSerializer手动序列化类,并在客户端上反序列化。我无法在网上找到一个优雅的解决方案,所以我通过在Visual Studio中自动生成XmlTypeAttribute后,手动从代理类中手动删除XmlTypeAttribute,从而避免了这个问题。

我不停地回头看看是否有办法让命名空间锻炼。以下是我如何在无需修改自动生成的类的情况下工作。我最终使用XmlTextReader在与属性名称匹配的节点上返回所需的名称空间。有改进的空间,但我希望它可以帮助别人。

class Program 
{ 
    static void Main(string[] args) 
    { 
     //create list to serialize 
     Person personA = new Person() { Name = "Bob", Age = 10, StartDate = DateTime.Parse("1/1/1960"), Money = 123456m }; 
     List<Person> listA = new List<Person>(); 
     for (int i = 0; i < 10; i++) 
     { 
      listA.Add(personA); 
     } 

     //serialize list to file 
     XmlSerializer serializer = new XmlSerializer(typeof(List<Person>)); 
     XmlTextWriter writer = new XmlTextWriter("Test.xml", Encoding.UTF8); 
     serializer.Serialize(writer, listA); 
     writer.Close(); 

     //deserialize list from file 
     serializer = new XmlSerializer(typeof(List<ProxysNamespace.Person>)); 
     List<ProxysNamespace.Person> listB; 
     using (FileStream file = new FileStream("Test.xml", FileMode.Open)) 
     { 
      //configure proxy reader 
      XmlSoapProxyReader reader = new XmlSoapProxyReader(file); 
      reader.ProxyNamespace = "http://myappns.com/";  //the namespace of the XmlTypeAttribute 
      reader.ProxyType = typeof(ProxysNamespace.Person); //the type with the XmlTypeAttribute 

      //deserialize 
      listB = (List<ProxysNamespace.Person>)serializer.Deserialize(reader); 
     } 

     //display list 
     foreach (ProxysNamespace.Person p in listB) 
     { 
      Console.WriteLine(p.ToString()); 
     } 

     Console.ReadLine(); 
    } 
} 

public class Person 
{ 
    public string Name { get; set; } 
    public int Age { get; set; } 
    public DateTime StartDate { get; set; } 
    public decimal Money { get; set; } 
} 

namespace ProxysNamespace 
{ 
    [XmlTypeAttribute(Namespace = "http://myappns.com/")] 
    public class Person 
    { 
     public string Name { get; set; } 
     public int Age { get; set; } 
     public DateTime Birthday { get; set; } 
     public decimal Money { get; set; } 

     public override string ToString() 
     { 
      return string.Format("{0}:{1},{2:d}:{3:c2}", Name, Age, Birthday, Money); 
     } 
    } 
} 

public class XmlSoapProxyReader : XmlTextReader 
{ 
    List<object> propNames; 
    public XmlSoapProxyReader(Stream input) 
     : base(input) 
    { 
     propNames = new List<object>(); 
    } 

    public string ProxyNamespace { get; set; } 

    private Type proxyType; 
    public Type ProxyType 
    { 
     get { return proxyType; } 
     set 
     { 
      proxyType = value; 
      PropertyInfo[] properties = proxyType.GetProperties(); 
      foreach (PropertyInfo p in properties) 
      { 
       propNames.Add(p.Name); 
      } 
     } 
    } 

    public override string NamespaceURI 
    { 
     get 
     { 
      object localname = LocalName; 
      if (propNames.Contains(localname)) 
       return ProxyNamespace; 
      else 
       return string.Empty; 
     } 
    } 
} 
+0

嗨GLass,我几乎陷入类似的问题,需要一些帮助 – 2014-08-13 10:03:41

+0

辉煌的肥皂代理阅读器 - >非常感谢你。 – Titwan 2014-11-27 17:49:18

您需要实现IXmlSerializable以改善您的自定义序列化。

+1

我有很多嵌套类。在每个类上实现它只是为了删除命名空间! 我将不得不为每个类添加一个XmlSchemaProvider,根据版本返回不同的模式。 是否有更简单的方法来执行反序列化?就像添加一个空的名称空间字符串到序列化函数? – rodrigogq 2010-02-19 14:34:19

您可以以文本形式读取文件,删除违规的命名空间文本,然后对其进行反序列化。

您可能需要将“good”文本写回到[memory/string/etc]流中,以便可以调用XmlSerializer的Deserialize。

+0

是的...这似乎是“最好”的方式。 TKS! – rodrigogq 2010-02-25 18:18:32

为了反序列化XML没有命名空间添加XmlRoot属性来代表您的层次结构的顶层类:

[XmlRoot(ElementName="plugins", Namespace="")] 

在我的例子中,XML已经没有命名空间,并开始像

<plugins><... 

它反序列化到的类:

[XmlRoot(ElementName="plugins", Namespace="")] 
public class Plugins 
{ 
    //... 
} 

显然,你的情况可能会略有不同,但此代码的工作对我来说:

using (FileStream stream = File.Open(filePath, FileMode.Open)) 
{ 
    XmlReader reader = new XmlTextReader(stream);     
    XmlSerializer serializer = new XmlSerializer(typeof(Plugins)); 
    var plugins = (Plugins)serializer.Deserialize(reader); 
} 

-Stan