Как десериализовать класс, украшенный пространством имен XmlRoot, когда у XML нет пространства имен? - PullRequest
2 голосов
/ 29 марта 2012

Этот вопрос задавался ранее, но ответ не работает для меня: так что вот еще раз вопрос:)

У меня есть реальная проблема при попытке десериализации некоторого 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).---> System.InvalidOperationException: не ожидалось.в Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderData.Read5_data ()

Внутреннее исключение следующим образом:

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

Ответ на вопрос былудалить пространство имен из класса (удалить Namespace = "MyNamespace").Класс, однако, является частью очень большой библиотеки, которая создается автоматически с помощью xsd.exe.Я не хочу ничего менять в сгенерированном классе.Есть ли еще, чтобы решить эту проблему, не изменяя класс?

Ответы [ 2 ]

5 голосов
/ 05 апреля 2012

Есть ли еще возможность исправить эту проблему без изменения класса?

Да.

.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-сериализации в любой части класса для десериализации.Это не было необходимо в вашем случае.

Дополнительная информация.

ps: Атрибут [Serializable], который вы используете для украшения своего класса,не нужно.Это распространенная ошибка - применять ее к классам, которые будут сериализованы и десериализованы.Но это постороннее, а потому и неправильное.

0 голосов
/ 29 марта 2012

Ну, если вы не можете или не хотите изменять код, тогда вам нужно xslt, чтобы преобразовать ваш xml и добавить несколько пространств имен, где это необходимо.это поможет десериализатору десериализовать документ.

С уважением.

...