如何在C#中使用子元素反序列化XML?

时间:2012-12-12 11:20:07

标签: c# xml xml-serialization

我正在尝试序列化/反序列化以下XML代码结构:

<Person>
    <Name/>
    <Age/>
    <Address>
        <BuildingNumber/>
        <Street/>
        <Town/>
        <PostCode/>
    </Address>
</Person>

使用班级

public class Person {
    public string Name { get; set; }
    public int Age { get; set; }
    public Address Address { get; set; }
}

public class Address {
    public string BuildingNumber { get; set; }
    public string Street { get; set; }
    public string Town { get; set; }
    public string PostCode { get; set; }
}

我正在两个类上实现IXmlSerializable(对于这个特定的例子,它已经过度设计了,我知道,但是对于我正在处理的项目来说,它需要更复杂!),序列化工作很好,但反序列化没有。

问题出现在Person.ReadXml()方法中,我写成:

public void ReadXml(XmlReader reader) {
    reader.ReadStartElement();
    if (!reader.IsEmptyElement) {
        Name = reader.ReadElementContentAsString("Name", string.Empty);
        Age = reader.ReadElementContentAsInt("Age", string.Empty);
        Address = (Address)reader.ReadElementContentAs(typeof(Address), null, "Address", string.Empty);
        // Also failed: Address = (Address)reader.ReadElementContentAsObject("Address", string.Empty);
    }
    reader.ReadEndElement();
}

初始化Address的最后一行是抛出异常:

  

无法在具有子元素的元素上调用ReadElementContentAs()方法。 (XmlException)

基本上,我如何使用IXmlSerializable来处理包含子元素的元素?

2 个答案:

答案 0 :(得分:3)

我认为你可以在这里使用XmlSerializer

XmlSerializer serializer = new XmlSerializer(typeof(Person));
Person person = (Person)serializer.Deserialize(reader);

序列化也很简单:

serializer.Serialize(stream, person);

如果您需要自定义xml(不是当前的情况),那么只需使用xml序列化属性。

答案 1 :(得分:0)

您可以尝试这样:

public void ReadXml(XmlReader reader)
{
    reader.MoveToContent();
    reader.ReadStartElement();
    Name = reader.ReadElementString("Name");
    Age = Convert.ToInt32(reader.ReadElementString("Age"));
    var xmlSerializer = new XmlSerializer(typeof (Address));
    Address = (Address) xmlSerializer.Deserialize(reader);
    reader.ReadEndElement();
}
  • 请注意,每次新建一个XmlSerializer for adress可能效率低下,缓存它可能是一个好主意。
  • 如果地址实现IXmlSerializable或
  • ,这将独立工作
  • 正如其他人所说的那样,只使用IXmlSerializable作为最后的手段,如果属性可行,那么这是一个更好的方法。