Проблема с десериализацией XML в сгенерированные классы XSD - PullRequest
12 голосов
/ 14 сентября 2009

У меня довольно подробный XML-файл. Ниже приведены узлы верхнего уровня (я включил эллипс, поскольку узлы нижнего уровня все хорошо сформированы и правильно заполнены данными):

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <Models>...</Models>
    <Data>...</Data>
</config>

Я создал файл xsd из командной строки Visual Studio 2008:

xsd sample.xml

Это создает файл xsd просто отлично. Затем я автоматически генерирую классы из xsd с помощью команды:

xsd sample.xsd /classes

Для десериализации xml-файла в объект класса я использую функцию чтения из вспомогательного класса:

public class XmlSerializerHelper<T>
{
    public Type _type;

    public XmlSerializerHelper()
    {
        _type = typeof(T);
    }

    public void Save(string path, object obj)
    {
        using (TextWriter textWriter = new StreamWriter(path))
        {
            XmlSerializer serializer = new XmlSerializer(_type);
            serializer.Serialize(textWriter, obj);
        }
    }

    public T Read(string path)
    {
        T result;
        using (TextReader textReader = new StreamReader(path))
        {
            XmlSerializer deserializer = new XmlSerializer(_type);
            result = (T)deserializer.Deserialize(textReader);
        }
        return result;
    }
}

При попытке десериализации с помощью:

var helper = new XmlSerializerHelper<configModels>();
var obj = new configModels();
obj = helper.Read(filepath);

Я получаю ошибку, которую вывел, потому что десериализатор ищет узел «Модели», но соответствующее имя класса было сгенерировано как комбинация корневого узла и узла «Модель» (configModels). Почему имена классов генерируются так?

Я попытался десериализоваться с верхнего узла, используя:

var helper = new XmlSerializerHelper<config>();
var obj = new config();
obj = helper.Read(filepath);

К сожалению, это приводит к множеству ошибок, подобных следующим:

System.InvalidOperationException was unhandled by user code
Message="Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'Application.Lease[]' to 'Application.Lease'
error CS0030: Cannot convert type 'Application.CashFlow[]' to 'Application.CashFlow'
...ect.

Может кто-нибудь направить меня к тому, что я могу делать неправильно с моим автоматическим генерированием xsd?

Ответы [ 4 ]

11 голосов
/ 14 сентября 2009

XSD.EXE - хорошее начало, но далеко не идеальное. Кроме того, на основе предоставленного вами XML-файла XSD.EXE не всегда может точно определить, является ли что-то отдельным экземпляром объекта или открытым массивом объектов.

Похоже, это относится к вашим двум элементам - Application.Lease и Application.CashFlow. Как они определены в сгенерированном файле XSD? Это имеет смысл для вас? Вполне возможно, вам придется добавить несколько подсказок, таких как:

<xs:element name="Lease" minOccurs="0" maxOccurs="1" />

для необязательного свойства, это только ноль или один случай. Подобные вещи очень трудно понять инструменту xsd.exe, основываясь только на одном файле примера XML.

Марк

10 голосов
/ 13 января 2012

Перейдите к созданному вами классу и измените все с [] [] ---> []

3 голосов
/ 14 сентября 2009

Существует проблема с xsd.exe и списками. Вы должны зайти в сгенерированный класс и вручную отредактировать файл для правильного типа. Я перешел на использование Xsd2Code. Пока, похоже, нет этой проблемы.

0 голосов
/ 31 мая 2012

Другая проблема, которая может вызвать эту проблему, заключается в том, что содержимое файла xml между тегами (то есть содержимым) по-прежнему кодируется, когда это не должно быть. Например, теги <br> в моем контенте были по-прежнему <br> вместо &lt;br /&gt;. Генератор xsd превратил их в элементы схемы, а затем неправильно назвал их неограниченными, так как было найдено более одного. Их расшифровка позволила решить проблему и правильно сгенерировать классы.

...