XPath と LINQ to XML の比較

XPath と LINQ to XML は、いくつかの点で似ています。 どちらも XML ツリーに対してクエリを実行するために使用され、結果として、要素のコレクション、属性のコレクション、ノードのコレクション、要素や属性の値などを返します。 ただし、この 2 つのオプションには、大きな違いがあります。

XPath と LINQ to XML の違い

XPath では、新しい型を射影できません。 XPath では、ツリーからノードのコレクションが返されるだけですが、LINQ to XML では、クエリを実行し、オブジェクト グラフまたは XML ツリーを新しい構造に射影できます。 LINQ to XML クエリは、XPath 式よりもはるかに多くのことができます。

XPath 式は、文字列内に独立して存在します。 C# コンパイラは、コンパイル時に XPath 式を解析できません。 一方 LINQ to XML クエリは、C# コンパイラによって解析され、コンパイルされます。 コンパイラによって、多くのクエリ エラーをキャッチできます。

XPath の結果は厳密に型指定されません。 多くの場合、XPath 式を評価した結果はオブジェクトであり、開発者が適切な型を決定し、必要に応じて結果をキャストする必要があります。 一方、LINQ to XML クエリからの射影は厳密に型指定されます。

結果の順序付け

XPath 1.0 勧告には、XPath 式の評価結果であるコレクションは順序付けされないことが記載されています。

ただし、LINQ to XML の XPath 軸メソッドから返されるコレクションを反復処理すると、コレクション内のノードがドキュメント順に返されます。 これは、ドキュメントの逆順として述語が表現されている precedingpreceding-sibling などの XPath 軸にアクセスする場合でも同様です。

これに対し、LINQ to XML 軸のほとんどは、ドキュメント順にコレクションを返します。 ただし、これらのうち 2 つ (AncestorsAncestorsAndSelf) は、ドキュメントの逆順でコレクションを返します。 次の表では、軸を列挙し、それぞれのコレクションの順序を示します。

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 式では、多くの軸で位置述語がドキュメント順として表現されますが、逆方向軸の場合は、ドキュメントの逆順で表現されます。 逆方向軸は、precedingpreceding-siblingancestorancestor-or-self です。 たとえば、XPath 式 preceding-sibling::*[1] は、直前の兄弟を返します。 これは、最終的な結果セットがドキュメント順で表される場合も同様です。

一方、LINQ to XML の位置述語は、常に軸の順序として表現されます。 たとえば、anElement.ElementsBeforeSelf().ElementAt(0) は、直前の兄弟ではなく、クエリされる要素の親の最初の子要素を返します。 別の例として、anElement.Ancestors().ElementAt(0) は親要素を返します。

LINQ to XML で直前の要素を検索する場合は、次の式を記述します。

ElementsBeforeSelf().Last()
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.Elements("Customer").Elements("CompanyName")
customers.Elements("Customer").Elements("CompanyName")

同様の対応関係が XPath 軸ごとに存在します。

XPath 軸 LINQ to XML 軸
child (既定の軸) XContainer.Elements
Parent (..) XObject.Parent
attribute 軸 (@) XElement.Attribute

or

XElement.Attributes
ancestor 軸 XNode.Ancestors
ancestor-or-self 軸 XElement.AncestorsAndSelf
descendant 軸 (//) XContainer.Descendants

、または

XContainer.DescendantNodes
descendant-or-self XElement.DescendantsAndSelf

、または

XElement.DescendantNodesAndSelf
following-sibling XNode.ElementsAfterSelf

、または

XNode.NodesAfterSelf
preceding-sibling XNode.ElementsBeforeSelf

or

XNode.NodesBeforeSelf
following 同等の軸はありません。
preceding 同等の軸はありません。