Imports System.Xml
Module XPath2
Sub Main()
Dim xpDoc As XPathDocument = New XPathDocument("MusicLibraryNS.xml")
Dim xpNav As XPathNavigator = xpDoc.CreateNavigator()
Dim nt As NameTable = New NameTable
Dim nsm As XmlNamespaceManager = New XmlNamespaceManager(nt)
nsm.AddNamespace("cdp", "uri:music:cd")
nsm.AddNamespace("ttlp", "uri:music:title")
Dim xpNodeIter As XPathNodeIterator = xpNav.Select(xpExp, nsm)
For Each title As XPathNavigator In xpNodeIter
Console.WriteLine("The title is '{0}'", title.Value)
Next
End Sub
End Module
VBで書くときはNamespaceManagerに、XPathで使用するネームスペースプレフィックスとネームスペースを登録して、それをXPathNavigatorクラスのSelectメソッドにXPathと一緒に指定してやります.Javaより超簡単で素直ですね.あとXPathNavigatorクラスはValueメソッドがあって、string値を一発で持ってこれるところもやはり魅力です.
このプログラムで、恒例のごとく以下のように出てくれます.
Imports System.Text.RegularExpressions.Regex
Imports <xmlns:cdp="uri:music:cd">
Imports <xmlns:ttlp="uri:music:title">
Module Linq2
Sub Main()
Dim xd As XDocument = XDocument.Load("MusicLibraryNS.xml")
Dim titles1 As IEnumerable(Of XElement) = _
From title In xd.<mlp:musicLibrary>.<cdp:cd>.<ttlp:title> _
Select title
For Each title As XElement In titles1
Console.WriteLine("The title is '{0}'", title.Value)
Next
End Sub
End Module
なんとVBではImportステートメントでXMLの記法そのままにネームスペースの宣言が書けてしまいます.そして、Linq式もそのネームスペースプリフィックスを使用してXMLライクな記法で直感的に書けます.これは他の言語にはない機能ですね.VBをバカにする(自称プロの)人が居ますけれど、なかなかどうしてVBはすごく進化していると思います.
あとこのようなLinqの書き方はイマイチという人のために次のようにも書けます.でもこちらはすこし冗長です.
Imports System.Text.RegularExpressions.Regex
Imports <xmlns:cdp="uri:music:cd">
Imports <xmlns:ttlp="uri:music:title">
Module Linq2
Sub Main()
Dim xd As XDocument = XDocument.Load("MusicLibraryNS.xml")
Dim mlns As XNamespace = GetXmlNamespace(mlp)
Dim cdns As XNamespace = GetXmlNamespace(cdp)
Dim ttlns As XNamespace = GetXmlNamespace(ttlp)
Dim titles2 As IEnumerable(Of XElement) = _
From title In xd.Element(mlns + "musicLibrary").Elements(cdns + "cd").Elements(ttlns + "title") _
Where title.Ancestors().ElementAt(0).Element(mlns + "year").Value = "1994" _
Select title
For Each title As XElement In titles2
Console.WriteLine("The title is '{0}'", title.Value)
Next
End Sub
End Module
また次のようにも書けます.
Dim titles3 As IEnumerable(Of XElement) = _
xd.Element(mlns + "musicLibrary").
Elements(cdns + "cd").
Where(Function(cd) cd.Element(mlns + "year").Value.Equals("1994")).
Elements(ttlns + "title")
For Each title As XElement In titles3
Console.WriteLine("The title is '{0}'", title.Value)
Next
あとほとんど変わりませんが次ではF#の例を紹介します.