2010-12-06 8 views
2

タイトルが長いかもしれませんが、私が意味するものを説明させてください。私が実際に必要とするXMLをあなたに提供するつもりはありませんが、私が直面している問題を示すものを提供します。XMLシリアル化:同じ要素名を使用するが、属性に異なる値を持つクラスを区別するにはどうすればよいですか?

私はこのようなXMLを持っている:

<root> 
    <creatures> 
     <creature type="mammal" name="lion"> 
      <sound>roarr</sound> 
     </creature> 
     <creature type="bird" name="parrot"> 
      <color>red</color> 
     </creature> 
    </creatures> 
</root> 

は、以下のクラスを想像:
は(もちろんこれらは、いずれかの私の本当のクラスではありませんが、あなたはポイントを得る。)

public class Creature 
{ 
    public string Name { get; set; } 
} 

public class MammalCreature : Creature 
{ 
    public string Sound { get; set; } 
} 

public class BirdCreature : Creature 
{ 
    public string Color { get; set; } 
} 

属性を持つXMLシリアル化を使用して、シリアライザがタイプMammalCreatureBirdCreaturetype属性で区別するようにしたいと考えています。

xsi:type属性をタイプ名に設定することで、これを行うことができる解決策が見つかりましたが、私のケースでこれを行う実際の解決策があるかどうかを知りたいと思います。

答えて

2

属性だけではなく、しかし、この毛深い探しのコードが実際にRootクラスに適切にXMLを読むことができます:

[XmlRoot("root")] 
public class Root : IXmlSerializable 
{ 
    [XmlElement("creatures")] 
    public Creatures Items { get; set; } 

    /// <summary> 
    /// This method is reserved and should not be used. When implementing 
    /// the IXmlSerializable interface, you should return null (Nothing in 
    /// Visual Basic) from this method, and instead, if specifying a custom 
    /// schema is required, apply the 
    /// <see cref="T:System.Xml.Serialization.XmlSchemaProviderAttribute"/> 
    /// to the class. 
    /// </summary> 
    /// <returns> 
    /// An <see cref="T:System.Xml.Schema.XmlSchema"/> that describes the 
    /// XML representation of the object that is produced by the 
    /// <see cref="M:System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter)"/> 
    /// method and consumed by the 
    /// <see cref="M:System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader)"/> 
    /// method. 
    /// </returns> 
    public XmlSchema GetSchema() 
    { 
     return null; 
    } 

    /// <summary> 
    /// Generates an object from its XML representation. 
    /// </summary> 
    /// <param name="reader">The <see cref="T:System.Xml.XmlReader"/> stream 
    /// from which the object is deserialized. </param> 
    public void ReadXml(XmlReader reader) 
    { 
     reader.ReadStartElement("root"); 
     reader.ReadStartElement("creatures"); 

     List<Creature> creatures = new List<Creature>(); 

     while ((reader.NodeType == XmlNodeType.Element) 
      && (reader.Name == "creature")) 
     { 
      Creature creature; 
      string type = reader.GetAttribute("type"); 
      string name = reader.GetAttribute("name"); 

      reader.ReadStartElement("creature"); 

      switch (type) 
      { 
       case "mammal": 
        MammalCreature mammalCreature = new MammalCreature(); 

        reader.ReadStartElement("sound"); 
        mammalCreature.Sound = reader.ReadContentAsString(); 
        reader.ReadEndElement(); 
        creature = mammalCreature; 
        break; 
       case "bird": 
        BirdCreature birdCreature = new BirdCreature(); 

        reader.ReadStartElement("color"); 
        birdCreature.Color = reader.ReadContentAsString(); 
        reader.ReadEndElement(); 
        creature = birdCreature; 
        break; 
       default: 
        reader.Skip(); 
        creature = new Creature(); 
        break; 
      } 

      reader.ReadEndElement(); 
      creature.Name = name; 
      creature.Type = type; 
      creatures.Add(creature); 
     } 

     reader.ReadEndElement(); 
     this.Items = new Creatures(); 
     this.Items.Creature = creatures.ToArray(); 
     reader.ReadEndElement(); 
    } 

    /// <summary> 
    /// Converts an object into its XML representation. 
    /// </summary> 
    /// <param name="writer">The <see cref="T:System.Xml.XmlWriter"/> stream 
    /// to which the object is serialized. </param> 
    public void WriteXml(XmlWriter writer) 
    { 
     new XmlSerializer(typeof(Creatures)).Serialize(writer, this.Items); 
    } 
} 

[XmlRoot("creatures")] 
public class Creatures 
{ 
    [XmlElement("creature")] 
    public Creature[] Creature { get; set; } 
} 

[XmlInclude(typeof(MammalCreature))] 
[XmlInclude(typeof(BirdCreature))] 
public class Creature 
{ 
    [XmlAttribute("type")] 
    public string Type { get; set; } 

    [XmlAttribute("name")] 
    public string Name { get; set; } 
} 

public class MammalCreature : Creature 
{ 
    [XmlElement("sound")] 
    public string Sound { get; set; } 
} 

public class BirdCreature : Creature 
{ 
    [XmlElement("color")] 
    public string Color { get; set; } 
} 
+0

+1あなたの答えをありがとう!ええ、私はKISSソリューションを探していましたが、IXmlSerializableを実装すると解決策が得られると思いました。おそらく、スキーマを作成した人に属性ベースのXMLシリアライゼーションでサポートされている方法に変更するよう説得するでしょう。 – Venemo

+0

この回答が掲載された後はこれが長いことは分かっていますが、私はこのようなやり方でいくつか問題があります。 – Hewins

+0

@Hewinsそれから、あなたがやったこととあなたが直面している正確な問題を新しい質問に投稿するべきです。 –

0

異なるタイプの同じXMLエレメント名を持つことは、本当に重要ですか?

<root> 
    <creatures> 
     <MammalCreature name="lion"> 
      <sound>roarr</sound> 
     </MammalCreature> 
     <Birdcreature name="parrot"> 
      <color>red</color> 
     </BirdCreature> 
    </creatures> 
</root> 
+0

を私は同意するが、明らかに私は、XMLスキーマを作成するための責任を負うものではありませんよ。 – Venemo

-2

XMLシリアライザは、このシナリオをサポートしていません:あなたはXMLがそのように見ていると一緒に暮らすことができるかどう

はあなたがはるかにシンプルになってしまうことができます。

関連する問題