このXPathはLINQ to XMLならどう書くのでしょうか?

投稿者: Anonymous

初歩的な質問ですみません.普段XPathしか使っていません.LINQ to XMLを使用した場合、次のXPathと同等の結果を得るにはどう書いたら良いのでしょうか?

Imports System.Xml
Imports System.Xml.XPath
Imports Sgml
...
Dim sgml As SgmlReader = New SgmlReader()
sgml.DocType = "HTML"
sgml.Href = "http://www.data.jma.go.jp/obd/stats/data/mdrr/synopday/data1s.html"
sgml.IgnoreDtd = True
Dim htmlDoc As XDocument = XDocument.Load(sgml)
Dim nsTable As NameTable = New NameTable
Dim nsMgr As XmlNamespaceManager = New XmlNamespaceManager(nsTable)
nsMgr.AddNamespace("xhtml", "http://www.w3.org/1999/xhtml")
Dim targetTrs As IEnumerable(Of XElement) = htmlDoc.XPathSelectElements("//xhtml:table[@class = 'o1']//xhtml:tr[@class != 'o1h']", nsMgr)

気象庁の気象データから地点毎の最高気温を取得しようとしています.このプログラムはなんとか動きましたが、LINQで書けばどうなるのかがよくわかりません.

以上 よろしくお願いします.

解決

Visual BasicではXML対応しているため、別の記述が可能です。
まず、XML名前空間についてはImport構文で指定可能です。

Imports <xmlns:xhtml="http://www.w3.org/1999/xhtml">

次に//xhtml:tableについてはXML子孫軸プロパティで指定可能です。

Dim htmlDoc As XDocument = XDocument.Load(sgml)
Dim targetTables As IEnumerable(Of XElement) = htmlDoc...<xhtml:table>

次に[@class = 'o1']についてはWhereを使えますがその際XML属性軸プロパティが使えます。

Dim targetTables As IEnumerable(Of XElement) = htmlDoc...<xhtml:table> _
    .Where(Function(e) [email protected] = "o1")

最後にクエリ構文を使用することでシンプルになります。

Imports <xmlns:xhtml="http://www.w3.org/1999/xhtml">
...
Dim htmlDoc As XDocument = XDocument.Load(sgml)
Dim targetTrs As IEnumerable(Of XElement) = _
    From table In htmlDoc...<xhtml:table> _
    Where [email protected] = "o1" _
    From tr In table...<xhtml:tr> _
    Where [email protected] <> "o1h" _
    Select tr

なお、pgrhoさんの回答のXName.Getですが、XML名前空間を別途指定する2引数バージョンの他に、XML名前空間を含むXML名を指定することができる1引数バージョンも存在します。その上で、文字列からXNameへの暗黙の型キャストも用意されているため

d.Descendants("{http://www.w3.org/1999/xhtml}table") _
...

と記述できます。この方法はC#言語でも使用でき便利です。

回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *