C # проблема десериализации - PullRequest
4 голосов
/ 12 ноября 2010

У меня есть следующий класс:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:eu.emsa.ssn")]
public partial class SSN_ReceiptType {

    private Header1Type headerField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order=0)]
    public Header1Type Header {
        get {
            return this.headerField;
        }
        set {
            this.headerField = value;
        }
    }
}

И следующий XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <SSN_Receipt xmlns="urn:eu.emsa.ssn">
        <Header StatusMessage="SomethingSomething" StatusCode="Blabla" SSNRefId="N/A" MSRefId="2674762" Version="2.0" To="NCANOHAU1" SentAt="2010-11-12T14:48:44Z" From="SSN"/>
    </SSN_Receipt>

И я использую этот типизированный метод для десериализации (вызывая Deserialize (xmlGoesHere)):

    /// <summary>
    /// Deserialize xml string to object of type T
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="xml"></param>
    /// <returns></returns>
    public static T Deserialize<T>(string xml)
    {
        try
        {

            // Create serializer
            var xs = new XmlSerializer(typeof(T));

            // Deserialize
            T t = (T)xs.Deserialize(new StringReader(xml));

            return t;
        }
        catch (Exception e)
        {
            log.Error(string.Format("Unable to deserialize XML: {0}", xml), e);

            return default(T);
        }
    }

Теперь вот кикер. Это раньше работало. Но недавно мы получили новую версию XSD, используемую для генерации классов, и после генерации нового кода (который не изменился для этого класса и показан выше) я получаю следующее исключение при попытке десериализации:

System.SystemException: «Ошибка в XML-документе (1, 57)»

И более того:

System.InnerException: не ожидалось.

Какого черта? : S Я попытался добавить XmlRootAttribute, указывающий «SSN_Receipt», который не помог ни на один бит. Кто-нибудь знает, что происходит?

Обновление: соответствующие разделы из XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:ssn="urn:eu.emsa.ssn" 
    attributeFormDefault="unqualified" 
    elementFormDefault="qualified" 
    targetNamespace="urn:eu.emsa.ssn">
[...]
<xsd:element name="SSN_Receipt" type="ssn:SSN_ReceiptType"/>
[...]
<xsd:complexType name="SSN_ReceiptType">
    <xsd:annotation>
        <xsd:documentation xml:lang="en"/>
    </xsd:annotation>
    <xsd:sequence>
        <xsd:element name="Header" type="ssn:Header1Type"/>
    </xsd:sequence>
</xsd:complexType>

Ответы [ 3 ]

3 голосов
/ 15 ноября 2010

Для дальнейшего использования для других бедных душ, вот решение, которое я придумала.

Как уже упоминалось в моем вопросе, мои классы генерируются из XSD.Я проверил предыдущую версию наших классов, и они все еще отлично работают.Кроме того, SOAP-сервисы, которые используют те же классы, также работают.Осматривая журнал трассировки, я не вижу ничего особенно показательного.

Но я нашел конкретное решение.Я добавил в свой класс следующий атрибут:

[System.Xml.Serialization.XmlRoot(Namespace = "urn:eu.emsa.ssn", 
                                  ElementName = "SSN_Receipt")]

Теперь я не хочу засорять сгенерированные классы пользовательским кодом, поэтому я добавил частичный класс:

[System.Xml.Serialization.XmlRoot(Namespace = "urn:eu.emsa.ssn", 
                                  ElementName = "SSN_Receipt")]
public partial class SSN_ReceiptType {}

Это решает мою проблему полностью.Но я до сих пор не понимаю, почему это сломалось, во-первых.

Если кто-то может придумать хороший тестируемый ответ на вопрос, почему это сломалось, я сделаю это правильным ответом.Спасибо за ваше время, ребята!Это был образовательный опыт, в некоторой степени:)

0 голосов
/ 15 ноября 2010

Вы должны создать класс SSN_Receipt.Этот класс необходимо использовать при передаче его методу десериализации.

IE:

Deserialize<SSN_Receipt>(xmlGoesHere);

, а не SSN_ReceiptType

0 голосов
/ 12 ноября 2010

Я почти уверен, что ваш XML должен читать

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ssn:SSN_Receipt xmlns="urn:eu.emsa.ssn"> 
    <ssn:Header StatusMessage="SomethingSomething" StatusCode="Blabla" SSNRefId="N/A" MSRefId="2674762" Version="2.0" To="NCANOHAU1" SentAt="2010-11-12T14:48:44Z" From="SSN"/> 
</ssn:SSN_Receipt> 
...