C#使用Linq to XML提升XML元素层级并修改XName为parent_child格式
C# Linq to XML 节点提升+重命名实现方案
核心需求
需要实现两个XML修改逻辑:
- 将
<School>节点下的名称、地址子节点向上提升一个层级,作为<Child>节点的直接子节点,和原<School>节点同级 - 移动节点时将两个节点分别重命名为
School_Name、School_Address,符合父级_子级的命名格式
原代码问题定位
原有代码无法正常运行的原因有两点:
- 循环逻辑失效:foreach遍历所有Child节点的集合时,循环内部没有使用当前迭代的节点变量,始终固定取第一个Child节点操作,导致后续节点永远不会被处理
- 缺少重命名逻辑:没有修改提取出的节点的
XName属性,移动后节点名仍为原始的Name、Address
注:给出的目标XML示例中<Sex>Male/Sex</Sex>属于笔误,以下实现会保留原始Sex节点的正确值,如有特殊修改需求可自行添加逻辑。
原始XML结构
<?xml version="1.0" encoding="utf-8"?> <GreatGrandParent> <GrandParent> <Parent> <Child> <Name>John</Name> <Address>California</Address> <Sex>Male</Sex> <Age>18</Age> <School> <Name>Cool School</Name> <Address>California</Address> </School> </Child> <Child> <Name>Mary</Name> <Address>New Orleans</Address> <Sex>Female</Sex> <Age>16</Age> <School> <Name>Pretty School</Name> <Address>New Orleans</Address> </School> </Child> </Parent> </GrandParent> </GreatGrandParent>
目标XML结构
<?xml version="1.0" encoding="utf-8"?> <GreatGrandParent> <GrandParent> <Parent> <Child> <Name>John</Name> <Address>California</Address> <Sex>Male</Sex> <Age>18</Age> <School_Name>Cool School</School_Name> <School_Address>California</School_Address> </Child> <Child> <Name>Mary</Name> <Address>New Orleans</Address> <Sex>Female</Sex> <Age>16</Age> <School_Name>Pretty School</School_Name> <School_Address>New Orleans</School_Address> </Child> </Parent> </GrandParent> </GreatGrandParent>
可直接运行的实现代码
XDocument doc = XDocument.Load(@"D:\Xml\Childs Profile.xml"); // 提前ToList固定所有Child节点集合,避免遍历过程中修改节点结构触发枚举异常 List<XElement> childNodes = doc.Descendants("Child").ToList(); foreach (XElement child in childNodes) { XElement schoolNode = child.Element("School"); // 容错:当前Child下不存在School节点则直接跳过 if (schoolNode == null) continue; // 提取学校名称节点,重命名后挂载到当前Child节点下 XElement schoolName = schoolNode.Element("Name"); if (schoolName != null) { schoolName.Name = "School_Name"; child.Add(schoolName); } // 提取学校地址节点,重命名后挂载到当前Child节点下 XElement schoolAddress = schoolNode.Element("Address"); if (schoolAddress != null) { schoolAddress.Name = "School_Address"; child.Add(schoolAddress); } // 移除处理完成的空School节点 schoolNode.Remove(); } doc.Save(@"D:\Xml\Childs Profile.xml");
实现说明
- 直接通过
Descendants("Child")获取文档中所有Child节点,不需要手动逐层定位Parent节点,对XML结构变动的兼容性更好 - 循环全程操作当前迭代到的Child实例,不会出现固定操作第一个节点的问题
- Linq to XML中修改节点的父级关系不需要手动复制节点,直接将节点Add到新父节点下会自动脱离原有父节点
- 增加了空值校验,避免部分节点缺失时抛出空引用异常
- 默认将重命名后的节点添加到Child节点的子元素末尾,和目标结构顺序一致,如果需要调整插入位置,可以用
AddFirst、AddBeforeSelf、AddAfterSelf方法指定位置
内容的提问来源于stack exchange,提问作者RickyBelmont
相关产品推荐
相关产品推荐

