XPath 和 LINQ to XML 提供一些类似的功能。二者都可用于查询 XML 树,返回诸如元素集合、属性集合、节点集合或者元素或属性的值等这样的结果。但也有一些差异。
XPath 和 LINQ to XML 之间的差异
XPath 不允许新类型的投影。它只能从树中返回节点集合,而 LINQ to XML 可以执行查询并将对象图或 XML 树投影为新形状。LINQ to XML 查询包含更多功能并且比 XPath 表达式的功能强大得多。
XPath 表达式在字符串中孤立存在。C# 或 Visual Basic 编译器不能帮助在编译时分析 XPath 表达式。相比之下,C# 或 Visual Basic 编译器可以分析和编译 LINQ to XML 查询。编译器能够捕捉许多查询错误。
XPath 结果不是强类型。在许多情况下,XPath 表达式的计算结果是一个对象,并且该对象需要由开发人员确定属性类型并根据需要强制转换结果。相比之下,LINQ to XML 查询生成的投影是强类型。
结果排序
XPath 1.0 建议规定,作为 XPath 表达式计算结果的集合是无序的。
但在循环访问由 LINQ to XML XPath 轴方法返回的集合时,集合中的节点将按文档顺序返回。即使是在访问按反向文档顺序表示谓词的 XPath 轴(如 preceding 和 preceding-sibling)时,情况也如此。
相比之下,多数 LINQ to XML 轴都按文档顺序返回集合,但其中 Ancestors 和 AncestorsAndSelf 两个轴按反向文档顺序返回集合。下表枚举各个轴并指示每个轴的集合顺序:
| LINQ to XML 轴 | 排序方式 | 
|---|---|
| XContainer.DescendantNodes | 文档顺序 | 
| XContainer.Descendants | 文档顺序 | 
| XContainer.Elements | 文档顺序 | 
| XContainer.Nodes | 文档顺序 | 
| XContainer.NodesAfterSelf | 文档顺序 | 
| XContainer.NodesBeforeSelf | 文档顺序 | 
| XElement.AncestorsAndSelf | 反向文档顺序 | 
| XElement.Attributes | 文档顺序 | 
| XElement.DescendantNodesAndSelf | 文档顺序 | 
| XElement.DescendantsAndSelf | 文档顺序 | 
| XNode.Ancestors | 反向文档顺序 | 
| XNode.ElementsAfterSelf | 文档顺序 | 
| XNode.ElementsBeforeSelf | 文档顺序 | 
| XNode.NodesAfterSelf | 文档顺序 | 
| XNode.NodesBeforeSelf | 文档顺序 | 
位置谓词
在 XPath 表达式中,很多轴的位置谓词都按文档顺序表示,但是反向轴 preceding、preceding-sibling、ancestor 和 ancestor-or-self 则按反向文档顺序表示。例如,XPath 表达式 preceding-sibling::*[1] 返回前面紧邻的同级。即使最终结果集按文档顺序表示,情况也是这样。
相比之下,LINQ to XML 中的所有位置谓词始终按轴顺序表示。例如,anElement.ElementsBeforeSelf().ToList()[0] 返回所查询元素的父级的第一个子元素,而不是前面紧邻的同级。再例如:anElement.Ancestors().ToList()[0] 返回父元素。
请注意,上面的方法具体化整个集合。这不是编写该查询的最有效方法。以这种方式编写查询是为了演示位置谓词的行为。编写同一查询的更恰当的方式是使用 First 方法,如下所示:anElement.ElementsBeforeSelf().First()。
如果要查找 LINQ to XML 中的前面紧邻元素,则应编写下面的表达式:
ElementsBeforeSelf().Last()
性能差异
使用 LINQ to XML 中 XPath 功能的 XPath 查询的执行性能比 LINQ to XML 查询低。
撰写方式的比较
LINQ to XML 查询的撰写在某种程度上类似于 XPath 表达式的撰写,但其语法大不相同。
例如,如果名为 customers 的变量中有一个元素,并且您想在所有名为 Customer 的子级元素下查找名为 CompanyName 的孙级元素,则应编写如下所示的 XPath 表达式:
customers.XPathSelectElements("./Customer/CompanyName");
customers.XPathSelectElements("./Customer/CompanyName")
等效的 LINQ to XML 查询是:
customers.Element("Customer").Elements("CompanyName");
customers.Element("Customer").Elements("CompanyName")
每个 XPath 轴都有一些相似处。
| XPath 轴 | LINQ to XML 轴 | 
|---|---|
| 子级(默认轴) | |
| 父级 (..) | |
| 属性轴 (@) | 或 | 
| 上级轴 | |
| 上级或自身轴 | |
| 后代轴 (//) | 或 | 
| 后代或自身 | 或 | 
| 后面同级 | 或 | 
| 前面同级 | 或 | 
| 后面 | 无直接等效项。 | 
| 前面 | 无直接等效项。 |