2009-05-01 2 views
2

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

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

String [email protected]"C:\Users\tol56881\Documents\dnd4e.xsd"; 
String [email protected]"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[]' 

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

Спасибо!

+0

Хмм, разбор DDI Character Builder файлы? Я посмотрю позже и посмотрю, могу ли я предложить какие-то мысли. –

+0

Действительно. Они были достаточно любезны в последнем обновлении, чтобы сделать файлы XML более дружественными к третьим сторонам, поэтому подумал, что я возьму их на себя. Мне удалось это исправить. О том, чтобы добавить подробности об исправлении, хотя я оставляю проблему открытой, так как я не понимаю, почему проблема возникла в первую очередь. – Asmor

+0

Это старый вопрос, но все еще действительный, и вот больше информации, если кто-то еще сталкивается с этим: http://blog.coderunnr.com/2012/06/net-xmlserializer-unable-to-generate-a-temporary-class /. Сообщение включает немного более элегантное решение (добавление атрибута к схеме) с примером. Проблема на самом деле является ошибкой в ​​XmlSerializer .NET: http://connect.microsoft.com/VisualStudio/feedback/details/349967/xsd-exe-generates-code-with-the-wrong-type-in-an-xmlarrayitemattribute – spork

ответ

9

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

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 сделал это дважды проиндексированы, если они не должны быть. Я чувствую, что у меня все еще что-то не хватает, поэтому почему этот вопрос все еще открыт.

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

+0

Вместо изменения сгенерированного класса вы также можете отредактировать созданный XSD-файл, удалив атрибут maxOccurs = "unbounded" для элементов, которые не должны быть массивами (это причина этих 2d-массивов) –

4

Там это проблема с инструментом 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. Alter файл XSD, добавив фиктивный в первой последовательности, и запустить xsd.exe снова, так что, когда он генерирует класс не будет создайте двойной массив, а затем вы можете удалить атрибут dummy из класса.
  2. Внесите сгенерированный класс, добавьте новый класс с именем loot, который будет содержать массив объектов подсчета, которые у вас уже есть (и нужно только изменить имя).

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

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

+0

Это отличный ответ. Сэкономил мне много времени. Я создал SalesForce Enterprise WSDL и использовал VS2017 для генерации POCOs из этого файла, но у меня также были дважды индексированные массивы. – Adrian

Смежные вопросы