Проблема десериализации проверенного XML, невозможно преобразовать в / из массива - PullRequest
2 голосов
/ 01 мая 2009

Я немного не в себе. Я использовал xsd.exe для создания схемы xsd из файла xml, а затем для создания класса C # из этого xsd. Кажется, что все работает нормально.

В данный момент я просто пытаюсь десериализовать XML. Файл, который я десериализирую, если тот самый файл, который я использовал для создания класса изначально. Вот мой код:

String xsdPath=@"C:\Users\tol56881\Documents\dnd4e.xsd";
String xmlPath=@"C:\Users\tol56881\Documents\dnd4e.xml";
String xsdNamespace="";

//Validation stuff
XmlParserContext context = new XmlParserContext(null, null, "", XmlSpace.None);
XmlValidatingReader vr = new XmlValidatingReader(xmlPath, XmlNodeType.Element, context);
vr.ValidationType = ValidationType.Schema;
vr.Schemas.Add(xsdNamespace, xsdPath);
while (vr.Read()) ;

//Actually reading the file
TextReader tr = new StreamReader(xmlPath);
D20Character character = (D20Character)(new XmlSerializer(typeof(D20Character))).Deserialize(tr);

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

Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'Namespace.ObjectName[]' to 'Namespace.ObjectName'
error CS0029: Cannot implicitly convert type 'Namespace.ObjectName' to 'Namespace.ObjectName[]'

Так что похоже, что программа пытается перейти от массива к объекту и обратно к массиву, но я не совсем уверен. Сгенерированный автоматически код класса - это огромный беспорядок, который трудно преодолеть. Я надеюсь, что, может быть, здесь есть что-то простое, чего мне не хватает.

Спасибо!

Ответы [ 2 ]

10 голосов
/ 01 мая 2009

Мне удалось это исправить. Каждый из четырех рассматриваемых объектов был сгенерирован как массивы с двойной индексацией, такие как:

    private loot[][] lootTallyField;

и

    public loot[][] LootTally
    {
        get
        {
            return this.lootTallyField;
        }
        set
        {
            this.lootTallyField = value;
        }
    }

Все, что я сделал, это удалил один набор скобок, и все, кажется, работает нормально. Отсутствие проблем с десериализацией и быстрой проверкой десериализованного объекта позволяет сделать вывод, что данные были загружены правильно.

    private loot[] lootTallyField;

и

    public loot[] LootTally
    {
        get
        {
            return this.lootTallyField;
        }
        set
        {
            this.lootTallyField = value;
        }
    }

Все еще не уверен, почему xsd.exe сделал их дважды проиндексированными, если они не должны быть. Мне кажется, что я все еще что-то упускаю, поэтому этот вопрос все еще открыт.

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

5 голосов
/ 24 мая 2015

Существует проблема с инструментом xsd.exe, я постараюсь объяснить.

Если у вас есть complexType с последовательностью внутри, у которой есть дочерний complexType с последовательностью, а у первого нет никаких других элементов / атрибутов, то сгенерированный класс будет иметь только 1 сгенерированный тип вместо 2 и быть двойным массивом.

Если вы сделаете двойной массив в один массив, вы сможете отлично десериализовать ваш xml. ОДНАКО это даст следующий неожиданный результат. Если ваш xml выглядит следующим образом.

<root>
    <loot>
        <tally>value1</tally>
        <tally>value2</tally>
    </loot>
    <loot>
        <tally>value3</tally>
        <tally>value4</tally>
    </loot>
</root>

Тогда ваш десериализованный объект в массиве lootTally будет содержать только элементы value3 и value4 вместо всех 4.

Таким образом, у вас есть 2 варианта, чтобы исправить это правильно:

  1. Измените файл xsd, добавив пустышку в первой последовательности, и снова запустите xsd.exe, чтобы при создании класса он не создавал двойной массив, а затем вы можете удалить атрибут класса из класса.
  2. Измените сгенерированный класс, добавьте новый класс с именем loot, который будет содержать массив объектов подсчета, которые у вас уже есть (и нужно только изменить имя).

Обратите внимание, что в варианте 2 вам, возможно, придется изменить некоторые объявления, если у вас есть атрибут XmlArrayItemAttribute для XmlElementAttribute.

Надеюсь, это поможет

...