使用LINQ to XML处理XML节点:解决空引用异常及节点重命名问题
解决LINQ to XML节点重命名迁移的空引用异常及需求实现
问题根源
你的代码出现空引用异常主要有以下几个原因:
- 使用
Nodes()遍历会包含文本节点(比如换行、空格),这些节点并非XElement类型,强制转换会导致空引用 - 嵌套遍历逻辑混乱,
DescendantsAndSelf(xParent.Name)的用法完全错误,没必要限定名称,且遍历过程中修改文档树会导致后续操作失效 xChild.Value.ToString()在节点无值或节点为空时会触发异常,且ReplaceWith后原节点已脱离文档树,后续操作毫无意义
正确实现代码
直接针对需求,精准处理Ingredients下的嵌套节点:
// 加载原始XML string originalXml = @"<?xml version=""1.0"" encoding=""utf-8""?> <Home> <Kitchen> <Pantry> <Ingredients> <Name>Tomato</Name> <Price> <ID>1</ID> <Name>SALES</Name> </Price> <Cost> <ID>2</ID> <Name>COGS</Name> </Cost> </Ingredients> </Pantry> </Kitchen> </Home>"; XElement root = XElement.Parse(originalXml); // 遍历所有Ingredients节点 foreach (var ingredients in root.Descendants("Ingredients")) { // 先把要处理的父节点(Price、Cost)存入List,避免遍历中修改文档树引发异常 var targetParentNodes = ingredients.Elements().Where(e => e.HasElements).ToList(); foreach (var parentNode in targetParentNodes) { string parentName = parentNode.Name.LocalName; // 遍历父节点的子元素,创建新命名节点并添加到Ingredients层级 foreach (var childNode in parentNode.Elements()) { string newNodeName = $"{parentName}_{childNode.Name.LocalName}"; ingredients.Add(new XElement(newNodeName, childNode.Value)); } // 移除原嵌套父节点(Price/Cost) parentNode.Remove(); } } // 输出处理后的XML Console.WriteLine(root.ToString());
代码说明
- 用
Elements()替代Nodes(),确保只处理元素节点,彻底规避文本节点导致的空引用 - 提前将待处理节点存入List,避免遍历过程中修改文档树引发集合变更异常
- 逻辑直接清晰:创建新命名节点→迁移到目标层级→删除原父节点,无冗余操作
- 使用
LocalName获取节点名称,兼容带命名空间的XML场景
输出结果
执行后生成的XML与目标完全一致:
<?xml version="1.0" encoding="utf-8"?> <Home> <Kitchen> <Pantry> <Ingredients> <Name>Tomato</Name> <Price_ID>1</Price_ID> <Price_Name>SALES</Price_Name> <Cost_ID>2</Cost_ID> <Cost_Name>COGS</Cost_Name> </Ingredients> </Pantry> </Kitchen> </Home>
内容的提问来源于stack exchange,提问作者RickyBelmont
相关产品推荐
相关产品推荐

