在C#中动态将XML反序列化为List<T>类型的实现方案
嘿,我来帮你搞定把QBPOSXML的SalesOrderRet反序列化为C# List
第一步:定义匹配QBPOSXML结构的实体类
首先得把QBPOSXML的结构映射成C#的实体类——毕竟反序列化的核心就是让.NET能把XML节点对应到类的属性上。假设你的XML结构大概是这样的(如果和实际有出入,你只需要调整类的属性和特性就行):
return (<QBPOSXML> <SalesOrderRet> <TxnID>SO-001</TxnID> <SalesOrderItemRet> <ItemRef><FullName>Wireless Mouse</FullName></ItemRef> <Quantity>3</Quantity> </SalesOrderItemRet> </SalesOrderRet> <SalesOrderRet> <TxnID>SO-002</TxnID> <SalesOrderItemRet> <ItemRef><FullName>Mechanical Keyboard</FullName></ItemRef> <Quantity>1</Quantity> </SalesOrderItemRet> </SalesOrderRet> </QBPOSXML> )
对应的C#实体类要加上XML序列化特性,确保和XML节点完全匹配:
using System.Xml.Serialization; // 根节点类,用来包裹所有SalesOrderRet条目 [XmlRoot("QBPOSXML")] public class QbPosXmlRoot { // 用XmlElement指定元素名,这样多个SalesOrderRet会被识别为同级集合 [XmlElement("SalesOrderRet")] public List<SalesOrderRet> SalesOrders { get; set; } = new List<SalesOrderRet>(); } // 订单主数据实体类 public class SalesOrderRet { [XmlElement("TxnID")] public string TransactionId { get; set; } // 订单子项集合,同样用XmlElement指定子元素名 [XmlElement("SalesOrderItemRet")] public List<SalesOrderItemRet> OrderItems { get; set; } = new List<SalesOrderItemRet>(); // 这里可以根据你的XML结构添加其他字段,比如CustomerRef、TxnDate、TotalAmount等 } // 订单项实体类 public class SalesOrderItemRet { [XmlElement("ItemRef")] public ItemReference ItemReference { get; set; } [XmlElement("Quantity")] public decimal Quantity { get; set; } // 按需添加Price、Amount等其他字段 } // 商品引用子类 public class ItemReference { [XmlElement("FullName")] public string ProductName { get; set; } }
这里要注意几个细节:
- XML是区分大小写的,所以
XmlElement特性里的名称必须和XML节点完全一致 - 如果你的XML带有命名空间,要在
XmlRoot和XmlElement里加上Namespace="你的XML命名空间" - 对于可能缺失的可选字段,用可空类型(比如
decimal? Quantity)或者设置IsNullable=true避免反序列化报错
第二步:编写反序列化逻辑
接下来用.NET自带的XmlSerializer实现反序列化,不用额外安装第三方包。我写了两种常用场景的版本:
using System.IO; using System.Xml.Serialization; public class QbPosXmlParser { // 从XML字符串反序列化为订单集合 public List<SalesOrderRet> DeserializeFromXmlString(string xmlContent) { var serializer = new XmlSerializer(typeof(QbPosXmlRoot)); using var stringReader = new StringReader(xmlContent); var root = (QbPosXmlRoot)serializer.Deserialize(stringReader); return root.SalesOrders; } // 从本地XML文件反序列化为订单集合 public List<SalesOrderRet> DeserializeFromXmlFile(string filePath) { var serializer = new XmlSerializer(typeof(QbPosXmlRoot)); using var streamReader = new StreamReader(filePath); var root = (QbPosXmlRoot)serializer.Deserialize(streamReader); return root.SalesOrders; } }
第三步:调用示例
写完解析类,调用起来就很简单了,给你整个实际调用的例子:
// 模拟的QBPOSXML字符串 string sampleXml = @"<QBPOSXML> <SalesOrderRet> <TxnID>SO-001</TxnID> <SalesOrderItemRet> <ItemRef><FullName>Wireless Mouse</FullName></ItemRef> <Quantity>3</Quantity> </SalesOrderItemRet> </SalesOrderRet> <SalesOrderRet> <TxnID>SO-002</TxnID> <SalesOrderItemRet> <ItemRef><FullName>Mechanical Keyboard</FullName></ItemRef> <Quantity>1</Quantity> </SalesOrderItemRet> </SalesOrderRet> </QBPOSXML>"; // 初始化解析器并反序列化 var parser = new QbPosXmlParser(); List<SalesOrderRet> orders = parser.DeserializeFromXmlString(sampleXml); // 遍历处理订单数据 foreach (var order in orders) { Console.WriteLine($"订单ID: {order.TransactionId}"); foreach (var item in order.OrderItems) { Console.WriteLine($" 商品: {item.ItemReference.ProductName}, 数量: {item.Quantity}"); } }
容易踩的坑及解决办法
- 元素名称不匹配:务必确保
XmlElement特性里的名称和XML节点完全一致(包括大小写),不然会出现字段为空的情况 - 命名空间问题:如果XML带有命名空间,一定要在所有相关类的XML特性里指定对应的命名空间,否则反序列化会失败
- 空/缺失元素:对于可能不存在的字段,用可空类型或者设置
IsNullable=true,避免抛出反序列化异常
内容的提问来源于stack exchange,提问作者B. Abdo
相关产品推荐
相关产品推荐

