使用LINQ to XML获取指定XML元素结果为空,求原因及解决方法
问题分析与解决
问题重现
给定以下XML:
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1"> <NewDataSet xmlns=""> <Account diffgr:id="Account 1" msdata:rowOrder="0"> <ID>11</ID> <Name>Hello</Name> <Description>Good Boy</Description> </Account> <Account diffgr:id="Account 2" msdata:rowOrder="1"> <ID>12</ID> <Name>Nop</Name> <Description>Bad Boy</Description> </Account> <Collections diffgr:id="Collection 33" msdata:rowOrder="62"> <ID>1233</ID> <Name>Wrist Watches</Name> <Value>Expensive</Value> <IsArchieved>false</IsArchieved> </Collections> </NewDataSet> </diffgr:diffgram>
执行以下C#代码后无法获取目标节点:
List<string> nodeNames = new List<string>{"Account", "Collections"}; var n = nodeNames.Select(n => myXMLData.Descendants(XName.Get(n, "")));
错误原因
- 变量名冲突:代码中结果变量名
n与lambda参数名n重名,虽不影响编译,但易造成逻辑混淆,增加调试难度。 - 延迟加载的误解:
Select返回的是延迟执行的IEnumerable<IEnumerable<XElement>>,若未主动枚举(如调用ToList()、遍历),调试器中会显示为空,并非实际无结果。 - XName构造的直观性问题:
XName.Get(n, "")虽正确,但使用XNamespace.None + n更直观,可避免命名空间相关的潜在误解。
修正后的代码
步骤1:正确加载XML
// 替换为你的XML加载方式(Parse或Load) var myXMLData = XDocument.Parse("你的XML字符串"); List<string> nodeNames = new List<string>{"Account", "Collections"};
步骤2:获取目标节点
// 修正变量名冲突,用XNamespace.None构造空命名空间的XName var nodeElements = nodeNames.Select(name => myXMLData.Descendants(XNamespace.None + name)).ToList(); // 遍历验证结果 foreach (var elements in nodeElements) { Console.WriteLine($"找到 {elements.Count()} 个 {elements.First().Name.LocalName} 节点:"); foreach (var elem in elements) { Console.WriteLine($" ID: {elem.Element("ID").Value}"); } }
关键说明
NewDataSet节点的xmlns=""重置了默认命名空间,因此Account和Collections都属于空命名空间,使用XNamespace.None匹配是正确的。- 必须主动枚举结果序列(如
ToList()或遍历),才能触发LINQ查询的执行,看到实际节点数据。
内容的提问来源于stack exchange,提问作者Bohn
相关产品推荐
相关产品推荐

