当XML没有命名空间时,如何反序列化用XmlRoot命名空间修饰的类?

时间:2012-03-29 17:38:47

标签: .net xml xml-serialization

以前曾问过这个问题,但答案对我不起作用:所以这里再次提出问题:)

我在尝试反序列化某些XML时遇到了麻烦,希望有人可以提供一些帮助。我已经阅读了很多类似的帖子,但我无法解决这个问题。

这是XML

<register-account success="false">
  <user-name>xxxxx</user-name>
  <password>fghgh</password>
  <email>test@example.com</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)中存在错误。 ---&GT;   System.InvalidOperationException:不期望。在   Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderData.Read5_data()

内部异常如下:

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

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

2 个答案:

答案 0 :(得分: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-serialization属性。在你的情况下,这不是必要的。

More information.

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

答案 1 :(得分:-2)

如果您不能或不想更改代码,那么您必须使用xslt转换xml以在需要时添加一些命名空间。这将有助于反序列化程序反序列化文档。

问候。