如何在C#中将XML中item0-itemNN反序列化为数组/列表?
解决XML中带数字后缀的元素反序列化为列表的问题
针对你遇到的这个XML反序列化问题——把item0到itemNN这类带数字后缀的元素映射到data类的列表属性里,我有两种实用的解决方案,你可以根据自己的需求选择:
方案一:使用[XmlAnyElement]手动处理元素(推荐,无需额外事件绑定)
这种方法通过在类中添加一个用于XML序列化的中间属性,把所有未被映射的元素捕获后转换为你的item对象,同时对外暴露一个干净的Items列表供业务代码使用:
public class data { private List<item> _items = new List<item>(); // 用于XML序列化/反序列化的中间属性,捕获所有未匹配的元素 [XmlAnyElement] public XmlElement[] ItemsXml { get { // 序列化时:把Items列表转换为带数字后缀的XML元素 var doc = new XmlDocument(); return _items.Select((item, index) => { var elem = doc.CreateElement($"item{index}"); elem.SetAttribute("attr1", item.attr1); elem.SetAttribute("attr2", item.attr2); elem.SetAttribute("attr3", item.attr3.ToString()); elem.SetAttribute("attr4", item.attr4.ToString()); return elem; }).ToArray(); } set { // 反序列化时:把捕获的XML元素转换为item对象,添加到列表 _items.Clear(); if (value == null) return; foreach (var elem in value) { // 只处理以"item"开头的元素 if (elem.Name.StartsWith("item", StringComparison.Ordinal)) { var newItem = new item { attr1 = elem.GetAttribute("attr1"), attr2 = elem.GetAttribute("attr2"), attr3 = bool.Parse(elem.GetAttribute("attr3")), attr4 = double.Parse(elem.GetAttribute("attr4")) }; _items.Add(newItem); } } } } // 供业务代码使用的忽略XML的列表属性 [XmlIgnore] public List<item> Items { get => _items; set => _items = value ?? new List<item>(); } [XmlAttribute("timestamp")] public int timestamp; } public class item { [XmlAttribute("attr1")] public string attr1 { get; set; } [XmlAttribute("attr2")] public string attr2 { get; set; } [XmlAttribute("attr3")] public bool attr3 { get; set; } [XmlAttribute("attr4")] public double attr4 { get; set; } }
方案二:利用XmlSerializer的UnknownElement事件处理
如果你不想修改类的结构,可以在反序列化的时候绑定UnknownElement事件,捕获所有未被映射的item*元素并手动添加到列表中:
// 首先保持你的类结构(修正原来的错误属性) public class data { // 这里不需要错误的[XmlElement("itemNN?")],用XmlIgnore暂时忽略,通过事件填充 [XmlIgnore] public List<item> Items { get; set; } = new List<item>(); [XmlAttribute("timestamp")] public int timestamp; } public class item { [XmlAttribute("attr1")] public string attr1 { get; set; } [XmlAttribute("attr2")] public string attr2 { get; set; } [XmlAttribute("attr3")] public bool attr3 { get; set; } [XmlAttribute("attr4")] public double attr4 { get; set; } } // 反序列化时的处理代码 var serializer = new XmlSerializer(typeof(data)); // 绑定未知元素处理事件 serializer.UnknownElement += (sender, e) => { var currentData = (data)e.ObjectBeingDeserialized; // 判断元素是否是我们需要的item* if (e.Element.Name.StartsWith("item", StringComparison.Ordinal)) { var newItem = new item { attr1 = e.Element.GetAttribute("attr1"), attr2 = e.Element.GetAttribute("attr2"), attr3 = bool.Parse(e.Element.GetAttribute("attr3")), attr4 = double.Parse(e.Element.GetAttribute("attr4")) }; currentData.Items.Add(newItem); } }; // 执行反序列化 using (var reader = new StringReader(yourXmlContent)) { var result = (data)serializer.Deserialize(reader); // 此时result.Items已经包含了所有item0到itemNN的对象 }
注意事项
- 两种方案都能处理任意数量的
item*元素,不管后缀数字是多少 - 如果你的XML中还有其他类似命名的元素(比如
otherItem0),可以调整判断条件(比如用正则匹配^item\d+$)来更精准地筛选目标元素 - 方案一的优势是序列化和反序列化都能自动处理,方案二更适合临时的反序列化场景
内容的提问来源于stack exchange,提问作者raiserle
相关产品推荐
相关产品推荐

