.NETでLINQのXDocumentに対してXPathSelectElementsにXPath式を指定してノードを選択する例を示します.非常に単純でドキュメントノードに対してXPathSelectElementsを適用するだけです.
Module Main
Sub Main()
Dim xd As XDocument = XDocument.Load("MusicLibrary.xml")
Dim titles As IEnumerable(Of XElement) = xd.XPathSelectElements("musicLibrary/cd[string(year) = '1994']/title")
For Each title As XElement In titles
Console.WriteLine("The title is '{0}'", title.Value)
Next
End Sub
End Module
結果は The title is 'The Dark Side of the Moon' と表示されます.
ここで考えておかねばならないことですが、まずMicrosoftのXPathの実装はXPath 1.0レベルであるということです.Javaの場合は、SaxonにXPathのモジュールを動的に変えてすぐXPath 2.0が使えましたが、.NETではサードパーティのライブラリでも使わない限りXPath 2.0は使えないです.
Performance Differences
XPath queries that use the XPath functionality in LINQ to XML will not perform as well as LINQ to XML queries.
Dim titles As IEnumerable(Of XElement) = _
From title In xd.<musicLibrary>.<cd>.<title> _
Where title.Ancestors().ElementAt(0).<year>.Value = "1994" _
Select title
まさにキーワードの順番は違いますがSQLを書いているのとまったく同じ感じですね.これで同じ結果を得ることができます.このように直感的にタグでかけるのと同様に
Dim titles As IEnumerable(Of XElement) = _
From title In xd.Element("musicLibrary").Elements("cd").Elements("title") _
Where title.Ancestors().ElementAt(0).Element("year").Value = "1994" _
Select title
とも書けます.なかなか柔軟性が高いです.ここでXElementはクラスでElementは関数で別物です.
またこのようにクェリー式を書くのではなくて以下のようにしてもできます.
Dim titles As IEnumerable(Of XElement) = xd.<musicLibrary>.<cd>.Where(AddressOf selectYear).<title>
Function selectYear(cd As XElement) As Boolean
Return cd.<year>.Value.Equals("1994")
End Function
Dim titles As IEnumerable(Of XElement) = xd.<musicLibrary>.<cd>.Where(Function(cd) cd.<year>.Value.Equals("1994")).<title>
あとLINQを使えば、XPathが1.0しか使えないという制限を取り除くことができます.JavaのところでSaxonにやらせた正規表現の判定も次のように.NETの正規表現の関数を使用すれば実現できます.
Imports System.Text.RegularExpressions.Regex
Dim titles As IEnumerable(Of XElement) = xd.<musicLibrary>.<cd>.Where(Function(cd) IsMatch(cd.<artist>.Value, "^P.+ F.+")).<title>
これでartistが"Pink Floyd"のcd要素が選択され同じように、
結果は The title is 'The Dark Side of the Moon' と表示されます.
LINQはMicrosoftが力を入れているだけあってなかなかおもしろく便利です.でもXPathは「標準」です.やっぱりMicrosoftにも2.0以降を実装してもらいたいという声はありますし私もそう思います.このあたりの事情はstackoverflow.comの以下のページに詳しく議論されています.