XDocument.Descendants()返回所有子孙元素节点(IEnumerable),仅含元素,忽略文本、注释等非元素节点;支持按名称或命名空间筛选,区别于仅查直接子元素的Elements()。

XDocument.Descendants() 方法用于获取文档中所有子孙元素节点(即递归查找所有嵌套层级的 ),它返回一个 IEnumerable,不包含文本节点、注释、处理指令等非元素节点。
Descendants() 只返回 XElement 节点
该方法只遍历并返回 XML 中的**元素(Element)节点**,忽略文本内容(XText)、CDATA、注释(XComment)、处理指令(XProcessingInstruction)等。如果需要访问所有类型节点(包括文本),需用 DescendantNodes() 或递归遍历 Node.Nodes()。
-
doc.Descendants()→ 所有元素,无论嵌套多深 -
doc.DescendantNodes()→ 所有节点:元素、文本、注释、空白等 -
doc.Root?.DescendantsAndSelf()→ 包含根元素自身的所有后代元素(含自己)
按名称筛选特定子孙元素
可传入元素名(字符串或 XName)来只获取指定名称的子孙元素:
-
doc.Descendants("Book")→ 所有名为的元素(不管在哪一层) -
doc.Descendants(ns + "Title")→ 支持命名空间,ns是XNamespace实例 - 结果仍是
IEnumerable,可链式调用.Where()、.Select()等 LINQ 方法
遍历并处理每个子孙元素
典型用法是 foreach 遍历,或结合 LINQ 查询属性/内容:
foreach (var el in doc.Descendants()) { Console.WriteLine(el.Name); }var titles = doc.Descendants("Title").Select(t => t.Value).ToList();var emptyElements = doc.Descendants().Where(e => !e.HasElements && string.IsNullOrWhiteSpace(e.Value));
注意 Descendants() 和 Elements() 的区别
Elements() 只返回**直接子元素**(一层深度),而 Descendants() 是**全部后代元素**(任意深度):
-
root.Elements()→(仅一级) -
root.Descendants()→,,(所有层级) - 若想获取所有节点(含文本),改用
root.DescendantNodes(),再用node.GetType()判断类型
