如何使用LINQ to XML遍历XML文档并转换指定XML结构?
嘿,来帮你搞定这两个LINQ to XML的问题,都是日常处理XML时经常碰到的需求~
1. 如何使用LINQ to XML遍历XML文档?
LINQ to XML靠XDocument和XElement这两个核心类,提供了非常直观的遍历方式,我给你举几个常用场景:
假设我们有这样一份XML文档:
<Employees> <Employee> <Name>Avi Malhotra</Name> <Age>55</Age> </Employee> <Employee> <Name>John Doe</Name> <Age>30</Age> </Employee> </Employees>
- 按层级遍历子元素:如果你清楚XML的层级结构,用
Elements()方法可以直接获取指定层级的子元素:
// 加载XML文档(也可以用XDocument.Parse从字符串加载) XDocument doc = XDocument.Load("employees.xml"); // 遍历所有<Employee>子元素 foreach (XElement employee in doc.Root.Elements("Employee")) { string name = employee.Element("Name").Value; int age = int.Parse(employee.Element("Age").Value); Console.WriteLine($"员工姓名: {name}, 年龄: {age}"); }
- 全局查找指定元素:如果需要找到所有某个名称的元素(不管它在XML的哪个层级),用
Descendants()方法就很方便:
// 获取所有<Name>元素,无论层级 foreach (XElement nameElement in doc.Descendants("Name")) { Console.WriteLine($"员工姓名: {nameElement.Value}"); }
- 递归遍历所有节点:如果要遍历整个XML的每一个元素(包括所有层级的子节点),可以写个简单的递归方法:
void TraverseAllElements(XElement currentElement) { Console.WriteLine($"元素名称: {currentElement.Name}, 内容: {currentElement.Value}"); // 递归处理子元素 foreach (XElement child in currentElement.Elements()) { TraverseAllElements(child); } } // 从根节点开始遍历 TraverseAllElements(doc.Root);
2. 实现XML结构转换:从
<name>Avi malhotra</name><age>55</age>到目标格式 首先要注意,合法的XML必须有根节点,我先假设你的输入是包裹在根节点里的结构,然后用LINQ的查询语法完成转换:
using System.Globalization; // 构造输入XML(实际场景可以从文件/字符串加载) XElement inputXml = new XElement("Root", new XElement("name", "Avi malhotra"), new XElement("age", "55") ); // 执行转换:把每个原元素拆成<Column>和<Value>对 var transformedNodes = inputXml.Elements() .SelectMany(elem => new[] { // 生成<Column>元素,内容是原元素的名称 new XElement("Column", elem.Name.LocalName), // 生成<Value>元素,name字段顺便转成首字母大写的格式 new XElement("Value", elem.Name.LocalName == "name" ? CultureInfo.CurrentCulture.TextInfo.ToTitleCase(elem.Value) : elem.Value) }); // 把转换后的节点组合成新的XML(如果需要根节点的话) XElement outputXml = new XElement("Result", transformedNodes); // 输出结果 Console.WriteLine(outputXml.ToString());
这段代码的核心是SelectMany,它能把每个输入元素转换成两个新元素,然后扁平化输出。运行后得到的XML就是:
<Result> <Column>name</Column> <Value>Avi Malhotra</Value> <Column>age</Column> <Value>55</Value> </Result>
如果你的输入是没有根节点的两个独立元素(虽然语法上不合法,但假设是从某个数据源拿到的单独元素),只需要把它们放到一个集合里,用同样的逻辑处理就行:
var inputElements = new List<XElement> { new XElement("name", "Avi malhotra"), new XElement("age", "55") }; var transformedNodes = inputElements .SelectMany(elem => new[] { new XElement("Column", elem.Name.LocalName), new XElement("Value", elem.Name.LocalName == "name" ? CultureInfo.CurrentCulture.TextInfo.ToTitleCase(elem.Value) : elem.Value) }); // 直接输出每个转换后的元素 foreach (var node in transformedNodes) { Console.WriteLine(node.ToString()); }
这样就能得到你想要的无结构的<Column>和<Value>对啦。
内容的提问来源于stack exchange,提问作者Velayuthan Rengasamy
相关产品推荐
相关产品推荐

