Десериализовать XML-файл для объекта в C # - PullRequest
0 голосов
/ 17 декабря 2018

Я пытался десериализовать XML в объект, используя C #, но я получаю некоторые ошибки.

Мой XML-файл:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:transmission xmlns:ns0="blabla.xsd">
<ns0:DiagnosisErrorResponse>
<ns0:ID>7</ns0:ID>
<ns0:ErrorCode>9</ns0:ErrorCode>
<ns0:ErrorDescription>sometext</ns0:ErrorDescription>
<ns0:ErrorDate>11-12-2018</ns0:ErrorDate>
</ns0:DiagnosisErrorResponse>
</ns0:transmission>

У меня есть такая сущность:

[XmlRoot(Namespace = "blabla.xsd", ElementName = "ns0:transmission", DataType = "string", IsNullable = true)]
public class DiagnosisErrorResponse
{
    [XmlElement("ID")]
    public long ID { get; set; }

    [XmlElement("ErrorCode")]
    public int ErrorCode { get; set; }

    [XmlElement("ErrorDescription")]
    public string ErrorDescription { get; set; }

    [XmlElement("ErrorDate")]
    public string ErrorDate { get; set; }
}

и моя ошибка:

<transmission xmlns='blabla.xsd'> was not expected.

Моя функция такова:

private void ReadXmlFileByPath(string filePath)
{
    string xmlText = string.Empty;
    XmlDocument d = new XmlDocument(); 

    using (XmlTextReader tr = new XmlTextReader(filePath))
    {
        tr.Namespaces = true;
        d.Load(tr);
        xmlText = d.InnerXml;
    }

     XmlSerializer xs = new XmlSerializer(typeof(DiagnosisErrorResponse), "");

    using (TextReader reader = new StringReader(xmlText))
    {
        DiagnosisErrorResponse result = (DiagnosisErrorResponse)xs.Deserialize(reader);
    }
}

Обновление : я удалил 'ns0:префикс из атрибута XmlElement на объекте, но я все еще получаю ту же ошибку.

1 Ответ

0 голосов
/ 17 декабря 2018

Ваша проблема в том, что ваша модель данных c # не соответствует вашему XML.В частности:

  1. Вы указали, что имя элемента для DiagnosisErrorResponse должно быть "ns0:transmission".Префикс пространства имен ns0: должен быть включен , а не , это просто поиск в файле XML для поиска фактического пространства имен, которое определяется атрибутом xmlns xmlns:ns0="blabla.xsd".

  2. XML имеет уровень вложенности, не учитываемый в вашей модели данных.XML в вашем вопросе не имеет отступов;если я сделаю отступ, то это будет выглядеть так:

    <ns0:transmission xmlns:ns0="blabla.xsd">
      <ns0:DiagnosisErrorResponse>
        <ns0:ID>7</ns0:ID>
        <ns0:ErrorCode>9</ns0:ErrorCode>
        <ns0:ErrorDescription>sometext</ns0:ErrorDescription>
        <ns0:ErrorDate>11-12-2018</ns0:ErrorDate>
      </ns0:DiagnosisErrorResponse>
    </ns0:transmission>
    

    Как теперь видно, ID и т. д. не являются детьми transmission, они являются детьми DiagnosisErrorResponse, который является потомкомtransmission.Это необходимо учитывать в ваших классах c #.

Сочетая эти две проблемы, ваша модель данных должна выглядеть следующим образом:

[XmlRoot(Namespace = "blabla.xsd", ElementName = "transmission", IsNullable = true)]
public class Transmission
{
    [XmlElement("DiagnosisErrorResponse")]
    public DiagnosisErrorResponse DiagnosisErrorResponse { get; set; }
}

[XmlRoot(Namespace = "blabla.xsd", IsNullable = true)]
public class DiagnosisErrorResponse
{
    [XmlElement("ID")]
    public long ID { get; set; }

    [XmlElement("ErrorCode")]
    public int ErrorCode { get; set; }

    [XmlElement("ErrorDescription")]
    public string ErrorDescription { get; set; }

    [XmlElement("ErrorDate")]
    public string ErrorDate { get; set; }
}

И ваш код десериализации должен выглядетьнапример:

private DiagnosisErrorResponse ReadXmlFileByPath(string filePath)
{
    using (var xmlReader = XmlReader.Create(filePath))
    {
        XmlSerializer xs = new XmlSerializer(typeof(Transmission));
        var result = (Transmission)xs.Deserialize(xmlReader);
        return result.DiagnosisErrorResponse;
    }
}   

Демо-скрипта # 1 здесь .

В качестве альтернативы, если вы пытались десериализовать только элемент <DiagnosisErrorResponse> внутри XML-файла без созданияМодель данных для корневого элемента, вы можете использовать XmlReader для сканирования вперед в XML, пока не будет найден соответствующий элемент:

private DiagnosisErrorResponse ReadXmlFileByPath(string filePath)
{
    using (var xmlReader = XmlReader.Create(filePath))
    {
        if (!xmlReader.ReadToDescendant("DiagnosisErrorResponse", "blabla.xsd"))
            return null;
        XmlSerializer xs = new XmlSerializer(typeof(DiagnosisErrorResponse));
        var result = (DiagnosisErrorResponse)xs.Deserialize(xmlReader);
        return result;
    }
}       

Демонстрационная скрипка # 2 здесь .

Примечания:

  • Нет необходимости загружать файл XML в XmlDocument, повторно сериализовать его как строку, а затем десериализовать строку.XML может быть десериализован непосредственно из файла за один шаг, используя XmlReader или StreamReader.

  • XmlTextReader устарел Microsoft в своей документации .XmlReader.Create() следует использовать вместо.

  • Вы можете избежать ошибок моделирования, таких как описанные выше, используя один из инструментов генерации кода, упомянутых в GenerateКласс C # из XML .

  • Самый простой способ диагностировать ошибку десериализации XML - это сериализовать экземпляр вашего корневого типа, а затем сравнить полученный результатXML с XML для десериализации.Несоответствия, как правило, легко обнаруживаются и указывают на наличие проблем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...