連載

.NETで簡単XML

第5回 DOMとXPath

株式会社ピーデー 川俣 晶
2003/06/10
Page1 Page2 Page3 Page4

最初のノード、最後のノード、指定番目のノード

 XPath式は、名前で対象を絞り込むだけではない。一連のノードの中で、最初、最後、あるいは、指定番目のノードを選択させることも容易である。ここでは、最初のノード、最後のノード、2番目のノードを選択させるサンプル・プログラムを見てみよう。

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  Dim doc As XmlDocument = New XmlDocument()
  doc.Load("c:\sample2.xml")
  Dim nsmgr1 As XmlNamespaceManager = New XmlNamespaceManager(doc.NameTable)
  nsmgr1.AddNamespace("smpl", "http://www.atmarkit.co.jp/xmlns/sample/shoseki/info")

  Trace.WriteLine("最初の名前")
  Dim list1 As XmlNodeList = doc.SelectNodes("(/smpl:書籍情報/smpl:著者/smpl:名前)[1]", nsmgr1)
  Dim node As XmlNode
  For Each node In list1
    Trace.WriteLine(node.InnerText)
  Next

  Trace.WriteLine("2番目の名前")
  Dim list2 As XmlNodeList = doc.SelectNodes("(/smpl:書籍情報/smpl:著者/smpl:名前)[2]", nsmgr1)
  For Each node In list2
    Trace.WriteLine(node.InnerText)
  Next

  Trace.WriteLine("最後の名前")
  Dim list3 As XmlNodeList = doc.SelectNodes("(/smpl:書籍情報/smpl:著者/smpl:名前)[last()]", nsmgr1)
  For Each node In list3
    Trace.WriteLine(node.InnerText)
  Next
End Sub
最初、2番目、最後のノードを選ぶサンプル(VB.NET版C#版

 これを実行すると以下のようになる。

 SelectNodesの引数に注目してほしい。前の例で分かるとおり、“/smpl:書籍情報/smpl:著者/smpl:名前”は3つの要素ノードを選択する。その最初のものを選択するには、“[1]”という表記を付加すればよい。しかし、単純に“/smpl:書籍情報/smpl:著者/smpl:名前[1]”という式を記述すると、3つのノードが選択されてしまい、意図した結果にならない。これは、“[1]”が“smpl:名前”に対して作用するためで、“/smpl:書籍情報/smpl:著者”で選択されるノードの子ノードである“名前”要素の1番目、という機能を果たしてしまう。すると、“/smpl:書籍情報/smpl:著者”で選択されるノードは3つあるので、結果として3つのノードが返ってきてしまうのである。そこで括弧を付けて解釈する順番を強制する必要がある。“(/smpl:書籍情報/smpl:著者/smpl:名前)[1]”と記述すれば、間違いなく、“/smpl:書籍情報/smpl:著者/smpl:名前”で選択した3つのノードの中の1番目となる。

 2番目のノードも、同様に記述して指定することができる。

 最後のノードは、ノードが何個あるか分かっていれば同様に指定できるが、分からない場合は“last()”と記述することで指定できる。

 2番目や3番目だけが欲しいというケースは多くないかも知れないが、最初だけ、あるいは最後だけを取得したいケースはしばしば遭遇する。そのような場合に便利な記述方法である。

属性値を指定した選択

 “[……]”の書式によって対象を限定する方法は、単に順番の数値を指定するだけでなく、もっと複雑な指定を記述可能である。ここでは、ある属性がある値を持っている要素を選択する例と、子要素の内容がある文字列である要素を選択する例を見てみよう。

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  Dim doc As XmlDocument = New XmlDocument()
  doc.Load("c:\sample2.xml")
  Dim nsmgr1 As XmlNamespaceManager = New XmlNamespaceManager(doc.NameTable)
  nsmgr1.AddNamespace("smpl", "http://www.atmarkit.co.jp/xmlns/sample/shoseki/info")

  Dim writerNode1 As XmlNode = doc.SelectSingleNode("//smpl:著者[@id='writer302']", nsmgr1)
  Dim writerNameNode As XmlNode = writerNode1.SelectSingleNode("smpl:名前", nsmgr1)
  Trace.WriteLine(writerNameNode.InnerText)

  Dim writerNode2 As XmlNode = doc.SelectSingleNode("//smpl:著者[smpl:名前='森野大樹']", nsmgr1)
  Dim writerOrgNode As XmlNode = writerNode2.SelectSingleNode("smpl:所属", nsmgr1)
  Trace.WriteLine(writerOrgNode.InnerText)
End Sub
属性値を指定するサンプル(VB.NET版C#版

 これを実行すると以下のようになる。

 まず、最初のXPath式は、“//smpl:著者[@id='writer302']”である。新しい書式が出てきているが、分かってしまえば難しくはない。“@”は属性を示す記号で、名前の先頭に付けると属性を示す。この場合、“@id”はidという名前の属性を示す。どの要素の属性かというと、その手前の式で選択された要素に付く属性である。そして、“'writer302'”はwriter302という文字列そのものを示している。くくる文字は“'”でも“"”でもよいが、ここでは“"”でくくられた文字列中にそのまま記述できる“'”の方を使っている。そして、“=”は同じであることを示す演算子である。つまり、“@id='writer302'”は、id属性の値がwriter302という文字列であるかどうかを判定する式である。

 さて、もう1つこれまで登場していなかった表記がある。それは先頭の“//”である。これは、ルート・ノード以下のすべてのノードを対象とする、という意図を表現する。ルート・ノードと対象とするノードの間に、いくつのノードがあっても選択される。同じように、“a//b”という表記も可能である。これは、aとbの間に、いくつのノードがあっても選択される式である。

 これらの指定によって、“//smpl:著者[@id='writer302']”というXPath式は、文書中のすべての“著者”要素の中で、id属性の値がwriter302という文字列であるものを選択してくれるわけである。

 次は、“//smpl:著者[smpl:名前='森野大樹']”という式である。“smpl:名前”が処理されるときは、基準点が“著者”要素にある。そのため、これは、“//smpl:著者”によって選択された“著者”要素の子要素を意味する。そして、“=”記号と、“'森野大樹'”は上の例と同様の意味を持つので、“名前”要素の内容が“森野大樹”という文字列であるかどうかを判断する式になる。

 つまりこの式は、文書中のすべての“著者”要素の中で、子要素の“名前”要素の値が“森野大樹”という文字列であるものを選択してくれるわけである。

 もう1つ、このサンプル・プログラムでは、SelectNodesメソッドではなく、SelectSingleNodeメソッドを使用している。SelectNodesメソッドは結果をリストで返すが、SelectSingleNodeメソッドは1つの結果だけを返す。このSelectSingleNodeメソッドは、結果がXmlNodeListクラスのインスタンスではなく、XmlNodeクラスのインスタンスで返ってくるほかは、ほとんど同じように使用することができる。

次回予告

 今回の解説では、高度な機能を多数持つXPathの表面を撫でた程度に過ぎない。ごく大ざっぱであり、不正確な用語も多数使用している。しかし、このくらいの知識でも、知っているとDOMプログラミングの役に立つことも事実である。ぜひ、活用していただきたい。そして本当に役に立つと思ったときは、もっと奥深い真のXPathの勉強にも取り組んでいただきたいと思う。

 次回は、XslTransformクラスを用いて、VB.NETやC#プログラム中でXSLTスクリプトを実行させる方法を解説する予定である。ある種のXML文書の加工は、XSLTスクリプトを使用した方が効率よく実現できる場合があるが、それをVB.NETやC#プログラム中で実行させることも可能である。End of Article


 INDEX
  .NETで簡単XML
  第5回 DOMとXPath
    1.DOMの死角
    2.XPathによるノード選択例とXPathの歴史
    3.名前空間の指定方法/文書のノード以外のノードから使う
  4.指定番目、属性値によるノード選択
 
インデックス・ページヘ  「連載 :.NETで簡単XML」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間