XML反序列化:将XML元素属性映射为类属性的实现问题
XML反序列化为指定类的解决方法
给定XML结构:
<data> <element id='abc.pqr'>1</element> <element id='abc.xyz'>2</element> </data>
要反序列化为包含pqr、xyz两个字符串属性的Data类,且属性值分别对应XML中element节点的文本内容。直接用XmlRoot和XmlAttribute属性无法满足需求,因为默认序列化逻辑会把每个<element>节点当作独立对象处理,导致无法正确赋值到同一个Data实例的属性上,以下是两种可行方案:
方案一:实现IXmlSerializable接口手动解析
让Data类实现IXmlSerializable接口,手动读取XML节点并赋值:
using System; using System.Xml; using System.Xml.Schema; using System.Xml.Serialization; public class Data { public string Pqr { get; set; } public string Xyz { get; set; } public XmlSchema GetSchema() => null; public void ReadXml(XmlReader reader) { // 跳过根节点的开始标签 reader.ReadStartElement("data"); while (reader.NodeType != XmlNodeType.EndElement) { if (reader.Name == "element") { var id = reader.GetAttribute("id"); var value = reader.ReadElementContentAsString(); // 根据id后缀匹配属性 if (id == "abc.pqr") Pqr = value; else if (id == "abc.xyz") Xyz = value; } else { // 跳过未知节点 reader.Skip(); } } // 读取根节点的结束标签 reader.ReadEndElement(); } public void WriteXml(XmlWriter writer) { // 如果需要序列化回XML,可在此实现写入逻辑 writer.WriteStartElement("element"); writer.WriteAttributeString("id", "abc.pqr"); writer.WriteString(Pqr); writer.WriteEndElement(); writer.WriteStartElement("element"); writer.WriteAttributeString("id", "abc.xyz"); writer.WriteString(Xyz); writer.WriteEndElement(); } }
使用方式:
var serializer = new XmlSerializer(typeof(Data)); using var reader = XmlReader.Create("your-xml-file-path.xml"); var data = (Data)serializer.Deserialize(reader);
方案二:先反序列化为中间类再映射
先定义一个对应XML结构的中间类,反序列化后再将数据映射到目标Data类:
using System.Collections.Generic; using System.Xml.Serialization; // 中间类,匹配XML的结构 [XmlRoot("data")] public class DataXml { [XmlElement("element")] public List<Element> Elements { get; set; } = new List<Element>(); } public class Element { [XmlAttribute("id")] public string Id { get; set; } [XmlText] public string Value { get; set; } } // 目标类 public class Data { public string Pqr { get; set; } public string Xyz { get; set; } }
映射逻辑:
var serializer = new XmlSerializer(typeof(DataXml)); using var reader = XmlReader.Create("your-xml-file-path.xml"); var dataXml = (DataXml)serializer.Deserialize(reader); var data = new Data(); foreach (var elem in dataXml.Elements) { switch (elem.Id) { case "abc.pqr": data.Pqr = elem.Value; break; case "abc.xyz": data.Xyz = elem.Value; break; } }
这两种方案都能解决默认属性映射无法正确赋值的问题,方案一适合直接绑定目标类,方案二更灵活,适合后续需要扩展更多element节点的场景。
内容的提问来源于stack exchange,提问作者MaxRecursion
相关产品推荐
相关产品推荐

