2012-03-29 106 views
2

这个问题以前被问过,但答案不适用于我:所以这里是问题再次:)当XML没有命名空间时,如何反序列化装有XmlRoot命名空间的类?

我真的有麻烦试图反序列化一些XML,并希望有人可以提供一些援助。我读过很多类似的帖子,但我无法解决这个问题。

这里是XML

<register-account success="false"> 
    <user-name>xxxxx</user-name> 
    <password>fghgh</password> 
    <email>[email protected]</email> 
</register-account> 

类我试图反序列化到:

[Serializable, XmlRoot(ElementName = "register-account", Namespace = "MyNamespace")] 
[XmlType("register-account")] 
public class RegisterAccountResponse 
{ 
    [XmlAttribute("success")] 
    public bool Success { get; set; } 

    /// <summary> 
    /// Gets or sets the Tennant email address 
    /// </summary> 
    [XmlElement("email")] 
    public string Email { get; set; } 

    /// <summary> 
    /// Gets or sets the tennant password 
    /// </summary> 
    [XmlElement("password")] 
    public string Password { get; set; } 

    /// <summary> 
    /// Gets or sets the Tennant username 
    /// </summary> 
    [XmlElement("user-name")] 
    public string Username { get; set; } 
} 

反序列化方法

public static T Deserialize<T>(string data) where T : class 
{ 

    var ser = new XmlSerializer(typeof(T)); 

    using (var sr = new StringReader(data)) 
    { 
     return (T)ser.Deserialize(sr); 
    } 
} 

反序列化方法调用

var data = Helper.Deserialize<RegisterAccountResponse>(xml); 

例外:

有XML文档中的误差(1,2)。 ---> System.InvalidOperationException:不是预期的。在 Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderData.Read5_data()

内部异常如下:

<register-account xmlns=''> was not expected. 

的问题的答案是从类中删除的命名空间(除去Namespace =“MyNamespace”)。然而,该类是使用xsd.exe自动生成的非常大的库的一部分。我不想在生成的类中更改任何内容。是否仍然可以解决这个问题而不必修改类?

+0

假设这是整个XML,那么您显示的XML没有名称空间(没有xmlns声明)。因此,将它从类的序列化参数中移除是有意义的......否则,请通过XSD重新生成类,以使其不需要名称空间即可生成。 – Reddog 2012-03-29 18:14:12

+0

我不认为XSD.exe支持生成没有名称空间属性的类。 – 2012-03-29 18:34:14

回答

-2

那么,如果你不能或不想改变代码,那么你必须xslt转换你的xml以在需要的地方添加一些命名空间。这将有助于解串器反序列化文档。

问候。

+0

我无法更改反序列化代码吗?或者更改传入的xml以注入命名空间?我怎么能这样做 – 2012-03-29 18:21:57

+0

我不这么认为你可以避免已经写入属性类的名称空间声明。但您可以使用XSLT更改包含的xml。它可能需要对XSLT进行一些研究,因为它是一种标记语言,用于设置xml.http://support.microsoft.com/kb/307322/en-us/或http://stackoverflow.com/questions/144713/add- a-namespace-to-elements-using-xslt – 2012-03-30 05:01:01

+0

这个答案是不正确的。 xslt是不需要的。 @Amine - 你可以做你想做的。看到我的答案。 http://stackoverflow.com/a/10020010/48082 – Cheeso 2012-04-04 22:23:51

5

有没有需要修改这个问题而无需修改类?

是的。

.NET有一个名为XmlAttributeOverrides的类,它是专门为此目的而设计的。 您可以在运行时覆盖代码中存在的属性。

以下修改的Deserialize实用程序方法将使用您提供的XML正确反序列化您提供的类的实例,而无需对其进行修改。没有XSLT。

public static T DeserializeWithNoRootNamespace<T>(string data) 
     where T : class 
    { 

     /* Each overridden field, property, or type requires 
      an XmlAttributes object. We are overriding the serialization 
      of the XmlRoot on the type, so we need one XmlAttributes collection. */ 
     var attrs = new XmlAttributes(); 

     /* Create an XmlRootAttribute to override the XmlRoot in-line attr. 
      The override will use no namespace. */ 
     var root = new XmlRootAttribute("register-account"); 

     // set the XmlRoot on the XmlAttributes collection. 
     attrs.XmlRoot= root; 

     // Create the XmlAttributeOverrides object. 
     var o = new XmlAttributeOverrides(); 

     /* Map the attributes collection to the thing being 
      overriden (the class). */ 
     o.Add(typeof(T), attrs); 

     // create the serializer, specifying the overrides to use 
     var ser = new XmlSerializer(typeof(T), o); 

     using (var sr = new StringReader(data)) 
     { 
      return (T)ser.Deserialize(sr); 
     } 
    } 

上面的代码覆盖了XmlRoot属性。 XmlAttributeOverrides通用性足以允许覆盖任何要反序列化的类的xml序列化属性。你的情况没有必要。

More information.

PS:[Serializable]属性你装饰你的类,则不需要。这是一个常见的错误,将其应用于将被XML序列化和反序列化的类。但它是无关的,因此是错误的。

+0

这是一个interresting,有了这段代码,我设法覆盖了我的XML命名空间,也就是说,我的模式有一个名称空间,但由于某种原因,我必须读取的XML文件具有不同的供应商名称空间。 但是,我可以从文件中读取命名空间,然后在我的反序列化中覆盖它,并从文件中按元素反序列化元素。 但是..很多运行时代码正在进行: 'test.vshost.exe'(CLR v4.0.30319:test.vshost.exe):Loaded'Microsoft.GeneratedCode'。 而且速度很慢..有没有其他方法可以做到这一点? – neslekkiM 2015-06-09 13:51:50