2010-07-26 7 views
1

J'ai un problème qui peut être résolu d'une manière plus efficace ou plus propre que ma solution actuelle. Au cours des derniers jours, j'ai acquis une assez bonne compréhension de la façon dont la sérialisation Xml peut être contrôlée via des attributs, mais une partie de la structure Xml est si obscure que je n'ai pas réussi à trouver une solution intelligente.C# - Xml sérialisation des types complexes ambiguës

J'ai reçu un schéma Xml, qui ne peut pas être modifié, et auquel je dois créer une classe C#.

Le code qui me dérange est la suivante:

<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> 

Ma première idée était de gérer cela en ayant une liste générique, qui pourrait être l'un des trois types de classes, qui a travaillé jusqu'à présent, mais le problème ici est le nom ambigu "Data".

Voici le code que je l'origine fait:

[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; } } 
} 

Malheureusement, cela n'a pas fonctionné, et je suppose qu'il est à cause du nom de l'élément ambigu « Data », puisque le message d'erreur est assez vague, mais a une référence au numéro de ligne de l'erreur. Comme je l'ai dit au début, j'ai déjà une solution, mais elle est loin d'être élégante, et certainement pas dans l'esprit .Net, c'est pourquoi j'apprécierais grandement toute aide. Ma solution à ceux qui sont intéressés implique une classe pour représenter "DataType" avec un champ pour le type et trois autres champs pour "DataOwner", "Name" et "XPath", où le type est une énumération qui peut être soit "DataUserField" ou "DataMasterField".

Désolé pour le poste long, mais je pensais qu'il serait préférable d'avoir des échantillons de code appropriés, s'il vous plaît dites si vous avez besoin de plus d'informations.

Répondre

0

Jetez un oeil à l'outil XSD.EXE, il va générer des classes C# pour vous à partir d'un schéma XSD.

Il doit déjà être installé sur votre ordinateur (SDK C: \ Program Files \ Microsoft \ Windows \ v6.0A \ bin \ xsd.exe pour .NET Framework 3.5).

Il y a un tutoriel pour l'utiliser sur codeproject.com

+0

Merci pour cette note, mais je préfère un peu plus de contrôle sur le processus de sérialisation ... BTW: Je l'ai déjà essayé XSD.exe et il est la solution était de avoir une classe pour "Data" contenant deux tableaux de chaînes, une avec le nom de type et une avec le contenu. Ce que je ressens, et s'il vous plaît corrigez-moi si vous pensez que je me trompe, n'est pas vraiment la façon .Net ... – reSPAWNed