标题可能很长,让我解释一下我的意思。我不会向您提供我需要使用的实际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序列化,我希望序列化程序能够通过MammalCreature
属性区分BirdCreature
和type
类型。
我找到了可以通过将xsi:type
属性设置为我想要的类型名称来实现此解决方案的解决方案,但我想知道是否有一个实际的解决方案可以解决我的问题。
答案 0 :(得分:2)
不只是属性,没有。但是,这个毛茸茸的代码确实可以将您的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; }
}
答案 1 :(得分:0)
对于不同类型具有相同的Xml元素名称,这对您来说真的很重要吗?
如果你能像Xml那样生活,你的最终会变得更加简单:
<root>
<creatures>
<MammalCreature name="lion">
<sound>roarr</sound>
</MammalCreature>
<Birdcreature name="parrot">
<color>red</color>
</BirdCreature>
</creatures>
</root>
答案 2 :(得分:-2)
XML Serializer不支持此方案。