C # - XML ​​сериализация неоднозначных сложных типов - PullRequest
1 голос
/ 26 июля 2010

У меня есть проблема, которая, возможно, может быть решена более эффективным или чистым способом, чем мое текущее решение.

За последние дни я достаточно хорошо понял, как сериализацией Xml можно управлять с помощьюатрибуты, но одна часть структуры Xml настолько неясна, что мне не удалось найти разумное решение.

Мне передали схему Xml, которую нельзя изменить, и которую я должен создатькласс C #.

Код, который мне мешает, следующий:

<xs:complexType name="dataRefType">
    <xs:sequence>
        <xs:element name="Data" type="DataType"/>
        <xs:sequence minOccurs="0" maxOccurs="unbounded">
            <xs:element name="Separator" type="xs:string"/>
            <xs:element name="Data" type="DataType"/>
        </xs:sequence>
    </xs:sequence>
</xs:complexType>
<xs:complexType name="DataType">
    <xs:choice>
        <xs:sequence>
            <xs:element name="DataOwner" type="xs:string"/>
            <xs:element name="Name" type="xs:string"/>
        </xs:sequence>
        <xs:element name="XPath" type="xs:string"/>
    </xs:choice>
</xs:complexType>

Моя первая идея состояла в том, чтобы управлять этим, имея общий список, который мог бы быть одним из трех типов классов, который работал до сих пор, но проблема здесь в неоднозначном названии «Данные».

Вот код, который я первоначально сделал:

[XmlRoot("DataRef")]
public class DataRef
{
    protected List<DataRoot> m_Data = new List<DataRoot>(1);

    [XmlElement(typeof(DataUserField))]
    [XmlElement(typeof(DataMasterField))]
    [XmlElement(typeof(DataSeparator))]
    public List<DataRoot> Data { get { return m_Data; } set { m_Data = value; } }
}

public abstract class DataRoot { }

[XmlRoot("Data")]
public class DataUserField : DataRoot
{
    protected string m_DataOwner;
    protected string m_Name;

    [XmlElement("DataOwner")]
    public string DataOwner { get { return m_DataOwner; } set { m_DataOwner = value; } }
    [XmlElement("Name")]
    public string Name { get { return m_Name; } set { m_Name = value; } }
}

[XmlRoot("Data")]
public class DataMasterField : DataRoot
{
    protected string m_XPath;

    [XmlElement("XPath")]
    public string XPath { get { return m_XPath; } set { m_XPath = value; } }
}

[XmlRoot("Separator")]
public class DataSeparator : DataRoot
{
    protected string m_Text = "";

    [XmlText()]
    public string Text { get { return m_Text; } set { m_Text = value; } }
}

Это, к сожалению, не сработало, и япредположим, что это происходит из-за неоднозначного имени элемента «Данные», поскольку сообщение об ошибке довольно расплывчато, но содержит ссылку на номер строки ошибки.

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

Мое решение для тех, кто заинтересован, заключается в представлении одного класса "DataType "с одним полем для типа и тремя другими полями для" DataOwner "," Name "и" XPath ", где типом является перечисление, которое может быть либо" DataUserField ", либо" DataMasterField ".

Извинитедля длинного поста, но я чувствовал, что было бы лучше иметь некоторые правильные примеры кода, пожалуйста, скажите, если вам нужно больше информации.

1 Ответ

0 голосов
/ 26 июля 2010

Посмотрите на инструмент XSD.EXE, он генерирует для вас классы C # из схемы XSD.

Он должен быть уже установлен на вашем компьютере (C: \ Program Files \ Microsoft SDKs \ Windows\ v6.0A \ bin \ xsd.exe для .NET Framework 3.5).

Существует руководство по его использованию на codeproject.com

...