如何从大型XML的指定片段反序列化生成Item对象列表
问题场景
需要从大型XML中仅提取<items>节点下的所有<item>数据,生成Item对象列表。
示例XML结构
<tXML> <nameOfUser>MK</nameOfUser> <amouthOfPO>14</amouthOfPO> <todayDate></todayDate> <warehouses> <warehouse id="1"> <name>AD1</name> </warehouse> <warehouse id="2"> <name>AD2</name> </warehouse> <warehouse id="3"> <name>AD3</name> </warehouse> </warehouses> <items> <warehause id="1"> <items> <item> <name>item1</name> <protectionLevel>AMB</protectionLevel> <description>DescAMB1FORID1</description> </item> <item> <name>item2</name> <protectionLevel>CHL</protectionLevel> <description>DescCHL1FORID1</description> </item> <item> <name>item3</name> <protectionLevel>AMB</protectionLevel> <description>3</description> </item> </items> </warehause> <warehause id="3"> <items> <item> <name>item1AMB2222</name> <protectionLevel>AMBB222222</protectionLevel> <description>DESCRIPTIONITEM1AM222222B</description> </item> <item> <name>item222222CHL</name> <protectionLevel>C222222222LL</protectionLevel> <description>ITEM2CH22ILLERAD1</description> </item> <item> <name>2222222222223</name> <protectionLevel>222222223</protectionLevel> <description>3222222222222</description> </item> </items> </warehause> <warehause id="3"> <items> <item> <name>item1333333AMB</name> <protectionLevel>AM3333BB</protectionLevel> <description>DESCR333IPTIONITEM1AMB</description> </item> <item> <name>item233333CHL</name> <protectionLevel>C33333HLL</protectionLevel> <description>ITEM2CHI333LLERAD1</description> </item> <item> <name>33</name> <protectionLevel>33</protectionLevel> <description>33</description> </item> </items> </warehause> </items> </tXML>
已定义Item类
namespace UseFiles { public class Item { public string Name { get; set; } public string ProtectionLevel { get; set; } public string Description { get; set; } } }
最优实现方案
优先推荐 XmlReader + XmlSerializer 混合方案,优势如下:
- 流式读取不需要加载整个XML到内存,适配GB级超大XML,内存占用极低
- 无需手动逐个给属性赋值,后续字段增减只需修改Item类注解,维护成本低
- 直接定位目标节点反序列化,忽略无关节点,处理效率更高
步骤1:给Item类添加序列化注解
using System.Xml.Serialization; namespace UseFiles { [XmlRoot("item")] public class Item { [XmlElement("name")] public string Name { get; set; } [XmlElement("protectionLevel")] public string ProtectionLevel { get; set; } [XmlElement("description")] public string Description { get; set; } } }
步骤2:解析逻辑实现
using System.Collections.Generic; using System.Xml; using System.Xml.Serialization; public List<Item> ParseItemsFromXml(string xmlFilePath) { var items = new List<Item>(); var serializer = new XmlSerializer(typeof(Item)); // 流式读取XML,不加载全量内容到内存 using (var reader = XmlReader.Create(xmlFilePath)) { // 定位到所有<item>节点 while (reader.ReadToFollowing("item")) { // 直接反序列化当前<item>节点为对象 var item = (Item)serializer.Deserialize(reader.ReadSubtree()); items.Add(item); } } return items; }
备选方案:手动遍历节点实现
如果不想修改Item类加注解,且XML体积不大的场景可以用,代码更灵活但维护成本更高:
using System.Collections.Generic; using System.Xml; public List<Item> ParseItemsFromXmlManual(string xmlFilePath) { var items = new List<Item>(); var xmlDoc = new XmlDocument(); xmlDoc.Load(xmlFilePath); // XPath查询所有目标<item>节点 XmlNodeList itemNodes = xmlDoc.SelectNodes("//tXML/items//item"); foreach (XmlNode itemNode in itemNodes) { var item = new Item { Name = itemNode.SelectSingleNode("name")?.InnerText, ProtectionLevel = itemNode.SelectSingleNode("protectionLevel")?.InnerText, Description = itemNode.SelectSingleNode("description")?.InnerText }; items.Add(item); } return items; }
内容的提问来源于stack exchange,提问作者Mateusz Kaleta
相关产品推荐
相关产品推荐

