簡體   English   中英

XML序列化:如何區分使用相同元素名稱但在屬性中具有不同值的類?

[英]XML Serialization: How to distinguish classes that use the same element name but have a different value in an attribute?

標題可能很長,請允許我解釋一下我的意思。 我不會為您提供需要使用的實際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序列化,我希望序列化BirdCreature通過type屬性區分MammalCreatureBirdCreature type

我已經找到了可以通過將xsi:type屬性設置為所需的類型名稱來實現此目的的解決方案,但是我想知道是否有針對我的情況的實際解決方案。

不只是屬性,不。 但是,這些看起來長毛的代碼確實可以將XML正確地讀入Root類:

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

對於不同類型使用相同的Xml元素名稱對您來說真的很重要嗎?

如果您可以像這樣使用Xml,那么最終可能會變得更加簡單:

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

XML序列化器不支持這種情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM