Что-то с теми сгенерированными классами.
Проблема происходит потому, что MaryFrank.Joe
объявляется как двумерный массив MaryFrankJoeSusan
объектов, но он украшен XmlArrayItemAttribute
который говорящее сериалайзер, что каждый элемент этого 2D массива имеют тип MaryFrankJoeSusan
, когда они, конечно, MaryFrankJoeSusan[]
.
Если вы измените эту строку в сгенерированные классы:
[System.Xml.Serialization.XmlArrayItemAttribute("Susan", typeof(MaryFrankJoeSusan),
Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
к этому:
[System.Xml.Serialization.XmlArrayItemAttribute("Susan", typeof(MaryFrankJoeSusan[]),
Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
тогда будет сериализовать без ошибок. Однако вы не получите результаты, которые вы ищете. Вместо этого:
<Mary>
<Frank>
<Joe>
<Susan>
<Stuff>my data</Stuff>
</Susan>
</Joe>
</Frank>
</Mary>
вы получите (обратите внимание на дополнительный MaryFrankJoeSusan
тег):
<Mary>
<Frank>
<Joe>
<Susan>
<MaryFrankJoeSusan>
<Stuff>my data</Stuff>
</MaryFrankJoeSusan>
</Susan>
</Joe>
</Frank>
</Mary>
Реальная проблема, кажется, что инструмент xsd.exe
сформировал структуру класса неправильно с самого начала. Он не создает класс в иерархии, чтобы представлять Джо, но вместо этого пытается объединить Джо и Сьюзан вместе, что на самом деле не работает здесь.
Я побежал исходный XML от вопроса с помощью инструмента для создания схемы XSD, и я получил это:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Mary" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="Mary" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Frank">
<xs:complexType>
<xs:sequence>
<xs:element name="Joe" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Susan" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Stuff" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
, который выглядит нормально для меня. Затем я взял ту же схему и снова запускал ее через инструмент для создания классов C#. Я ожидал бы получить что-то похожее на это:
[Serializable]
[XmlRoot(Namespace = "", ElementName = "Mary")]
public class Mary
{
[XmlElement("Frank")]
public Frank[] Frank { get; set; }
}
[Serializable]
public class Frank
{
[XmlElement("Joe")]
public Joe[] Joe { get; set; }
}
[Serializable]
public class Joe
{
[XmlElement("Susan")]
public Susan[] Susan { get; set; }
}
[Serializable]
public class Susan
{
[XmlElement("Stuff")]
public string Stuff { get; set; }
}
, но вместо этого я получил те же разбитые классы, которые связаны в этом вопросе. Так что это похоже на ошибку в инструменте xsd для меня.
Чтобы заставить его работать, вы можете использовать ручной закодированы классы, которые я сделал выше, изменения кода инициализации это:
var susan = new Susan { Stuff = "my data" };
var joe = new Joe { Susan = new Susan[] { susan } };
var frank = new Frank { Joe = new Joe[] { joe } };
var mary = new Mary { Frank = new Frank[] { frank } };
--или--
другой альтернативой является изменить xsd. Заменить xs:sequence
индикаторов для Frank
и Joe
элементов с xs:choice
вместо, как это:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Mary" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="Mary" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Frank">
<xs:complexType>
<xs:choice> <!-- was xs:sequence -->
<xs:element name="Joe" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:choice> <!-- was xs:sequence -->
<xs:element name="Susan" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Stuff" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice> <!-- was /xs:sequence -->
</xs:complexType>
</xs:element>
</xs:choice> <!-- was /xs:sequence -->
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
С помощью этой схемы, сгенерированные классы выходят гораздо лучше: есть класс для представления Джо в настоящее время. (Я упростил сгенерированный код здесь и удалены некоторые атрибуты для краткости):
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class Mary {
[System.Xml.Serialization.XmlElementAttribute("Frank", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public MaryFrank[] Items { get; set; }
}
[System.SerializableAttribute()]
public partial class MaryFrank {
[System.Xml.Serialization.XmlElementAttribute("Joe", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public MaryFrankJoe[] Items { get; set; }
}
[System.SerializableAttribute()]
public partial class MaryFrankJoe {
[System.Xml.Serialization.XmlElementAttribute("Susan", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public MaryFrankJoeSusan[] Items { get; set; }
}
[System.SerializableAttribute()]
public partial class MaryFrankJoeSusan {
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Stuff { get; set; }
}
код установки затем становится:
var susan = new MaryFrankJoeSusan() { Stuff = "my data" };
var joe = new MaryFrankJoe() { Items = new MaryFrankJoeSusan[] { susan } };
var frank = new MaryFrank() { Items = new MaryFrankJoe[] { joe } };
var mary = new Mary { Items = new MaryFrank[] { frank } };
И мы получим ожидаемый результат:
<?xml version="1.0" encoding="utf-16"?>
<Mary xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Frank>
<Joe>
<Susan>
<Stuff>my data</Stuff>
</Susan>
</Joe>
</Frank>
</Mary>
Фантастический ответ Брайан. Спасибо. Похоже, я вернусь к классу ручной работы, потому что он намного чище. Я тестировал ваше решение выше, и он работает. – TERACytE