XPath と LINQ to XML の機能はある程度似ています。どちらも XML ツリーに対してクエリを実行するために使用され、結果として、要素のコレクション、属性のコレクション、ノードのコレクション、要素や属性の値などを返します。ただし、相違点もいくつかあります。
XPath と LINQ to XML の違い
XPath では、新しい型を射影できません。XPath では、ツリーからノードのコレクションが返されるだけですが、LINQ to XML では、クエリを実行し、オブジェクト グラフまたは XML ツリーを新しい構造に射影できます。LINQ to XML クエリは、XPath 式と比べて、はるかに多機能かつ強力です。
XPath 式は、文字列内に独立して存在します。C# または Visual Basic コンパイラは、コンパイル時に XPath 式を解析できません。一方 LINQ to XML クエリは、C# または Visual Basic コンパイラによって解析され、コンパイルされます。コンパイラを使用することにより、多くのクエリ エラーを検出できます。
XPath の結果は厳密に型指定されません。多くの場合、XPath 式を評価した結果はオブジェクトであり、開発者が適切な型を決定し、必要に応じて結果をキャストする必要があります。一方、LINQ to XML クエリからの射影は厳密に型指定されます。
結果の順序付け
XPath 1.0 勧告には、XPath 式の評価結果であるコレクションは順序付けされないことが記載されています。
ただし、LINQ to XML の XPath 軸メソッドから返されるコレクションを反復処理すると、コレクション内のノードがドキュメント順に返されます。これは、ドキュメントの逆順として述語が表現されている preceding や preceding-sibling などの XPath 軸にアクセスする場合でも同様です。
一方、LINQ to XML 軸のほとんどはコレクションをドキュメント順に返しますが、Ancestors と AncestorsAndSelf の 2 つは、コレクションをドキュメントの逆順に返します。次の表では、軸を列挙し、それぞれのコレクションの順序を示します。
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 軸 |
---|---|
child (既定の軸) |
|
Parent (..) |
|
attribute 軸 (@) |
または |
ancestor 軸 |
|
ancestor-or-self 軸 |
|
descendant 軸 (//) |
または |
descendant-or-self |
または |
following-sibling |
または |
preceding-sibling |
または |
following |
同等の軸はありません。 |
preceding |
同等の軸はありません。 |