C#解析含CDATA的XML并批量提取30个节点值的实现方法
嵌套CDATA的XML字段批量提取方案
前置处理:正确解析CDATA封装的SOAP内容
你现有代码直接在外层XML查找row节点的逻辑不严谨,row节点实际封装在ASOUPReply的CDATA区段内,需要先提取CDATA内容再做二次解析:
// 解析外层XML XDocument outerXml = XDocument.Parse(text); // 提取ASOUPReply节点内的CDATA文本 string soapContent = outerXml.Descendants("ASOUPReply") .First() .Nodes() .OfType<XCData>() .First() .Value; // 解析CDATA内的SOAP格式XML XDocument soapXml = XDocument.Parse(soapContent); // 定位到row节点 XElement rowNode = soapXml.Descendants().First(x => x.Name.LocalName == "row");
批量提取方案(无需逐个手写字段赋值)
方案1:XML序列化自动映射(推荐)
只要模型属性名和XML节点名完全一致,就可以通过序列化直接生成完整对象,30个字段仅需补充属性定义即可,无需写赋值逻辑:
- 给模型类添加序列化特性:
[XmlRoot(ElementName = "row")] public class SPR4664 { public string NOM_VAG { get; set; } public string ROD_VAG_UCH { get; set; } public string KOD_SOB { get; set; } public DateTime? DATE_NACH { get; set; } public int STAN_NACH { get; set; } // 剩余所有字段直接按XML节点名补充属性定义即可,支持int、DateTime等类型和可空类型 }
- 直接反序列化得到完整对象:
XmlSerializer serializer = new XmlSerializer(typeof(SPR4664)); SPR4664 result = (SPR4664)serializer.Deserialize(rowNode.CreateReader());
该方案原生支持处理xsi:nil="true"的空值场景,只要将对应属性声明为可空类型(如DateTime?、int?)即可自动识别。
方案2:反射自动赋值
如果不想依赖序列化,可以通过反射自动匹配属性和节点完成赋值:
SPR4664 result = new SPR4664(); XNamespace ns = rowNode.Name.Namespace; // 获取模型所有公共属性 var properties = typeof(SPR4664).GetProperties(); foreach (var prop in properties) { XElement element = rowNode.Element(ns + prop.Name); if (element == null) continue; // 处理xsi:nil空值 var nilAttr = element.Attribute(XName.Get("nil", "http://www.w3.org/2001/XMLSchema-instance")); if (nilAttr != null && nilAttr.Value == "true") continue; // 按属性类型自动转换赋值 object value = Convert.ChangeType(element.Value, prop.PropertyType); prop.SetValue(result, value); }
注意事项
- 两种方案都要求模型属性名和XML内的节点名完全一致,不需要额外配置命名空间
- 对于特殊格式的日期、数字类型,可以在转换逻辑中添加自定义格式化规则
内容的提问来源于stack exchange,提问作者Boris
相关产品推荐
相关产品推荐

