連載

.NETで簡単XML

第5回 DOMとXPath

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

名前空間の指定方法

 さて、先ほどの例では名前空間を扱っていなかった。前出のサンプルXML文書に名前空間の指定を付けて、これを処理するにはどうすればよいのだろうか。

 XML文書は以下のように書き換えたとしよう。

<?xml version='1.0' encoding="UTF-8" ?>
<書籍情報 xmlns="http://www.atmarkit.co.jp/xmlns/sample/shoseki/info">
  <編集者 id="editor123">
    <名前>海野波男</名前>
    <所属>海浜出版</所属>
  </編集者>
  <著者 id="writer201">
    <名前>山岡岳男</名前>
    <所属>山岳協会</所属>
  </著者>
  <著者 id="writer302">
    <名前>野原草男</名前>
    <所属>原野愛好会</所属>
  </著者>
  <著者 id="writer404">
    <名前>森野大樹</名前>
    <所属>森林保護会</所属>
  </著者>
</書籍情報>
サンプルとするXML文書2(C:\sample2.xml)

 このXML文書を次のサンプル・プログラムで処理する。

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 list1 As XmlNodeList = doc.SelectNodes("/smpl:書籍情報/smpl:著者/smpl:名前", nsmgr1)
  Dim node As XmlNode
  For Each node In list1
    Trace.WriteLine(node.InnerText)
  Next
End Sub
名前空間を指定してXML文書を扱うサンプル(VB.NET版C#版

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

 サンプル・プログラムを見ると、前のサンプル・プログラムと比較して、役割が分かりにくい行が増え、式も複雑になっている。相違点は主に4つある。

 まず、XPath式に“/smpl:書籍情報/smpl:著者/smpl:名前”というように“smpl”という接頭辞が付いている。これは名前空間を明示的に指定するために付加されたものである。だが、このsmplという接頭辞はどこから来たのだろうか。XML文書内には、そのような接頭辞は存在しない。この接頭辞の情報を用意するためにほかの追加された行が存在するわけである。もう1つ注意すべき点は、XML文書で使用される接頭辞には、(通常)特定の名前を使用する強制力はないことである。つまり、XML文書中の接頭辞の名前に依存するプログラムを作成することは好ましくない。それゆえに、XPath式で使用する接頭辞の宣言は、XML文書と独立してプログラム中で行うべきものなのである。

 2番目の相違は、SelectNodesメソッドの第2引数が指定されていることである。前のサンプル・プログラムでは、引数が1個しかないバリエーションを使用していたが、ここでは引数2個を指定している。2番目の引数には、System.Xml.XmlNamespaceManagerクラスのインスタンスを指定する。これは、XML文書の名前空間に関する情報を管理するクラスである。この引数で指定するオブジェクトに、接頭辞“smpl”に関する情報が含まれていれば、XPath式は解釈可能になるわけである。

 3番目の相違は、当然、System.Xml.XmlNamespaceManagerクラスのインスタンスの作成である。VB.NETでは、

Dim nsmgr1 As XmlNamespaceManager = New XmlNamespaceManager(doc.NameTable)

という部分がこれにあたる。C#では、

XmlNamespaceManager nsmgr1 = new XmlNamespaceManager(doc.NameTable);

という部分がこれにあたる。引数には、文書オブジェクトの名前テーブルを渡す。名前テーブルについては、今回は直接扱わないので説明を割愛するが、ここでは処理対象となるXmlDocumentオブジェクトのNameTableプロパティの値を設定しておけばよい。

 4番目の相違は、最後に残された作業を行う部分である。つまり、接頭辞smplは“http://www.atmarkit.co.jp/xmlns/sample/shoseki/info”という名前空間に対応するという情報を設定することである。それには、XmlNamespaceManagerクラスのAddNamespaceメソッドを使用する。このメソッドの引数に、接頭辞と名前空間URIを指定すれば、必要な情報が設定されるわけである。これで、XPath式内の接頭辞smplが正しい対象を示すようになったのである。

文書のノード以外のノードから使う

 GetElementsByTagNameメソッドは文書ノードと要素ノードで使用できるメソッドだが、SelectNodesメソッドは任意のノードで使用できるメソッドである。ここでは、要素ノードでSelectNodesメソッドを使用する例を見てみよう。まず“/smpl:書籍情報/smpl:著者”というXPath式で著者ノードのリストを得て、それらのノードの子ノードとしてある“名前”要素を探し出してみよう。

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 list1 As XmlNodeList = doc.SelectNodes("/smpl:書籍情報/smpl:著者", nsmgr1)
  If list1.Count > 0 Then
    Dim list2 As XmlNodeList = list1(0).SelectNodes("smpl:名前", nsmgr1)
    Dim node As XmlNode
    For Each node In list2
      Trace.WriteLine(node.InnerText)
    Next
  End If
End Sub
要素ノードでSelactNodesメソッドを使うサンプル(VB.NET版C#版

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

 ここでは、まず、最初のSelectNodesメソッドの呼び出しにより、list1には“著者”ノードのリストが得られる。これは3個のノードを含むリストになる。次に、このリストの最初のノードに対して、2番目のSelectNodesメソッドを呼び出している。最初のSelectNodesメソッドはルート・ノードから呼び出しているので、調べる起点はルート・ノードになるが、2番目のSelectNodesメソッドは式が調べる起点が“著者”ノードになっている。最初の呼び出しは、ルート・ノードからの経路をすべて指定しているので、起点がどこであろうと結果は同じである。しかし、2番目の呼び出しでは、ルート・ノードからの指定ではないため、起点の位置が重要な意味を持つ。この場合は、起点の子にあたる“名前”要素が対象となる。ディレクトリとファイルでたとえれば、これはカレント・ディレクトリにあたる概念だと思うとよいだろう。“C:\one\two\three.txt”というファイルがあるとき、カレント・ディレクトリが“C:\one\two”なら、単に“three.txt”と記述するだけでそのファイルを指定することができる。それと同じことである。

 XPath式は複雑な条件を記述することができるが、このようにSelectNodesメソッドを使用するノードを選んで利用すると、XPath式の複雑さを軽減できる場合もある。ぜひ活用したいテクニックである。


 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 記事ランキング

本日 月間