XMLマスターへの道
〜「XMLマスター:ベーシック」試験対策〜

第12回 XPathによるノードの指定法を理解する

内藤一彦
NRIラーニングネットワーク株式会社
2003/12/23

 前回「第11回 XSLTで必須の制御命令を覚える」、前々回「第10回 XSLTの基本構造を理解する」と2回にわたりXML文書の変換を行うためのXSLTの利用方法について紹介しました。今回は、XSLTと密接な関係にあるXPathについて紹介します。前回に予習問題として下記の問題を出題しておきました。この問題を解くための解説をした後、解答を示します。

今回の問題
共通のXMLドキュメント
<?xml version="1.0" encoding="Shift_JIS" ?>
<EMPLOYEES>
  <EMPLOYEE  empid="A001">
    <Name>Kazuhiko Naito</Name>
    <Dept >Education</Dept>
    <Salary>200000</Salary>
  </EMPLOYEE>
  <EMPLOYEE  empid="B002">
    <Name>Masahiko Kondo</Name>
    <Dept >Sales</Dept>
    <Salary>300000</Salary>
  </EMPLOYEE>
  <EMPLOYEE  empid="C003">
    <Name>Reiko Sato</Name>
    <Dept >Education</Dept>
    <Salary>400000</Salary>
  </EMPLOYEE>
  <EMPLOYEE  empid="D004">
    <Name>Masao Ito</Name>
    <Dept >Sales</Dept>
    <Salary>500000</Salary>
  </EMPLOYEE>
</EMPLOYEES>

共通のXSLTテンプレート部分
<xsl:template match="/" >
<HTML>  <BODY>
Over 400000 Salary<BR/>
=================<BR/>
     <xsl:apply-templates select=" (1) "/>

  </BODY></HTML>
</xsl:template>

<xsl:template match="EMPLOYEE" >
      <xsl:value-of select="Name"/>
      <xsl:value-of select="Salary"/> <BR/>
 </xsl:template>

</xsl:stylesheet>

(Q1) 共通のXMLからSalaryが400000以上の社員情報を取得したい。共通のXSLTのテンプレートの(1)に入れるべき記述として正しいものを選択してください。

(a) /EMPLOYEES/EMPLOYEE(Salary &gt;=400000)
(b) /EMPLOYEES/EMPLOYEE[Salary&gt;=400000]
(c) /EMPLOYEES/EMPLOYEE/Salary&gt;=400000
(d) /EMPLOYEES/EMPLOYEE/[Salary&gt;=400000]

(Q2) 共通のXMLのEMPLOYEEのうち、先頭の2件(データの記述順)の社員情報を取得したい。共通のXSLTのテンプレートの(1)に入れるべき記述として正しいものを選択してください。

(a) /EMPLOYEES/EMPLOYEE[&lt;3]
(b) /EMPLOYEES/EMPLOYEE[EMPLOYEE&lt;3]
(c) /EMPLOYEES/EMPLOYEE[position()&lt;3]
(d) /EMPLOYEES/EMPLOYEE[position(&lt;3)]

 今回は、この問題に解答するうえで必要となる下記の内容について解説します。

  • XPathの概要
  • XPathのデータモデル
    • ノードの種類
  • ロケーションパス
    • ロケーションパスの記述方法
    • ノードテスト
    • 条件式

XPathの概要

 XPathとは、XML関連の規格の1つでXSLT version 1.0と同時期に標準仕様として勧告されています(W3C仕様原文)。XPathを使用すると、XMLドキュメント中のノードをアドレッシング(XMLドキュメント中のある場所を指し示して、その場所にアクセスする)できるようになります。また、XPath関数と呼ばれる30ほどの便利な関数が用意されています。

 XPathのノード・アドレッシング機能はいろいろな場面で利用されています。代表的なものはXSLTとの関係で、おそらくXSLTはXPathなしでは使えないといえます。例えばXSLTで要素や属性の値を取得したいときに、次のように記述しました(第10回 XSLTの基本構造を理解する XSLTの基本構造)。

xsl:value-of  select ="@empid"

 また、ある要素をテンプレートで処理したい場合、次のように記述しました。

xsl:apply-templates  select="/EMPLOYEES/EMPLOYEE"

 実は、どちらのselect属性も、指定するのはXPathに基づく式なのです。ほかにも、xsl:templateのmatch属性、xsl:for-eachのselect属性……などさまざまな個所で使用します。

 また、XPathをサポートしているリレーショナルデータベース製品では、データベース中のデータをXPathを使って検索できるものもあります(参考「XMLデータベース製品カタログ 2003」)。

XPathのデータモデル

ノードの種類

 XPathでは、XMLドキュメント中にある要素や属性などをノードとして、ツリー構造にモデリングして操作します。XPathのノードの種類には次のものがあります。

ノードの種類 XMLドキュメント内の対応
ルートノード XMLドキュメントで一番トップレベルのノード(ルート要素ではない)
要素ノード 要素
属性ノード 属性
テキストノード 要素の値
名前空間ノード 名前空間
処理命令ノード 処理命令
コメントノード コメント

 この中で、ルートノード、テキストノードに注意が必要です。ルートノードはXMLドキュメントで最上位に位置し、ほかのすべてのノードはこの子孫に含まれることなります(ルート要素は、このルートノードの子ノードです)。テキストノードは要素の値です。XPathでは、「要素の値」は要素ノードが持っているのではなく、「テキストノード」が持つことになっています。

 下記にXMLドキュメントの例を挙げますので、ノードの種類を整理しましょう。

<?xml version="1.0" encoding="Shift_JIS" ?>
<!--コメント-->
<?xml-stylesheet href="datamodel.xsl" type="text/xsl" ?>
<EMPLOYEES>
  <EMPLOYEE  empid="A001">
    <Name>Kazuhiko Naito</Name>
    <Dept>Education</Dept>
    <Salary>200000</Salary>
  </EMPLOYEE>
</EMPLOYEES>
リスト1 XML文書(datamodel.xml)

 このXMLドキュメントに含まれている各ノードのツリー構造は次のようになります。

図1 datamodel.xmlのツリー構造

 この階層構造で注意すべきノードは、属性ノードです。属性ノードは特別な扱いを受けており、要素ノードの子どもには含まれません(属性ノードの親は要素ノードですが)。ですから、EMPLOYEE要素ノードのすべての子ノードを取得しようとしても、empid属性ノードは含まれません。

 リスト1のXML(datamodel.xml)に次のようなXSLT変換を適用します。

<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

<xsl:template match="/" >
<HTML>  <BODY>
     <xsl:apply-templates select="node()|@*"/>
  </BODY></HTML>
</xsl:template>

<xsl:template match="node()" >
  <xsl:value-of select="name(.)"/>:::
  <xsl:value-of select="." /><BR/>
  <xsl:apply-templates  select="node()|@*"/>
</xsl:template>

</xsl:stylesheet>
リスト2 XSLT文書(datamodel.xsl


 このXSLTでは、ルートノード以外の各ノードの名前と値(xsl:value-of)を取得します。XMLファイルをIEで開くと次のような表示結果が得られます。

図2 IEによる変換結果の確認(datamodel.xml

 表示内容は、ノードごとに「ノードの名前:::xsl:value-ofの結果」となっています。コメントノードやテキストノードは、要素ノードや属性ノードと異なり、ノード名を持たない特別なノードです。

ロケーションパス

ロケーションパスの記述方法

 ロケーションパスとは、ノードを指し示すための式です。XPathの機能の中で最も利用される機能でしょう。ロケーションパスの記述方法は、OSのディレクトリ階層と同じような書式を取り、階層構造はノード名とノード名を「/」で区切り記述します(ノード名/ノード名/ノード名)。また、絶対パス(ルートノードから階層構造を指定)と相対パス(現在の作業位置からの相対的指定)の2通りの記述ができます。

 現在の作業位置がEMPLOYEE要素ノードだとすると、Name要素ノードを選択するのに次のような記述が行えます。

  絶対パス: "/EMPLOYEES/EMPLOYEE/Name"
  相対パス: "Name"

 式の先頭が「/」(ルート)から始まっていれば絶対パスです。

ノードテスト

 ノードテストとは、ノードの種類を評価する関数です。テキストノード用のノードテストはtext()で、そのノードがテキストノードであれば、「true」が結果として返ります。

ノードテストの種類 trueが返るノードの種類
comment() コメントノード
text() テキストノード
processing-instruction() 処理命令ノード
node() すべてのノード

 コメントノードやテキストノードはノード名を持たないので、これらのノードを指定したい場合には名前の代わりにノードテストを使います。以下に2つの例を挙げます。

 
 /EMPLOYEE/EMPLOYEE/Name/text()
  Name要素の値(Name要素ノードの子のテキストノード)
 
 /EMPLOYEE/EMPLOYEE/node()
 

EMPLOYEE要素のすべての子ノードが選択されます。ただし、属性ノードは含まれません。XPathデータモデルでは属性ノードは要素の子ノードではないためです。

 

条件式

 ロケーションパス式の中で、ノードを選択するための条件式を付加できます。条件式は、ノード名に続けて[ ]内に記述します。

<?xml version="1.0" encoding="Shift_JIS" ?>
<?xml-stylesheet href="filter.xsl" type="text/xsl" ?>
<EMPLOYEES>
  <EMPLOYEE  empid="A001">
    <Name>Kazuhiko Naito</Name>
    <Dept>Education</Dept>
    <Salary>200000</Salary>
  </EMPLOYEE>
  <EMPLOYEE  empid="B002">
    <Name>Masahiko Kondo</Name>
    <Dept>Sales</Dept>
    <Salary>300000</Salary>
  </EMPLOYEE>
  <EMPLOYEE  empid="C003">
    <Name>Reiko Sato</Name>
    <Dept>Education</Dept>
    <Salary>400000</Salary>
  </EMPLOYEE>
  <EMPLOYEE  empid="D004">
    <Name>Masao Ito</Name>
    <Dept>Sales</Dept>
    <Salary>500000</Salary>
  </EMPLOYEE>

</EMPLOYEES>
リスト3 サンプルXML文書(filter.xml)

<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
<xsl:template match="/">
<HTML>  <BODY>
Over 400000 Salary<BR/>
=================<BR/>
   <xsl:apply-templates
    select="/EMPLOYEES/EMPLOYEE[Salary&gt;=400000]"/>

  </BODY></HTML>
</xsl:template>

<xsl:template match="EMPLOYEE" >
      <xsl:value-of select="Name"/>
      <xsl:value-of select="Salary"/><BR/>
</xsl:template>

</xsl:stylesheet>
リスト4 XSLT文書(filter.xsl

 EMPLOYEE要素に対してテンプレートの呼び出しを行いますが、Salaryの値が400000以上という条件を設けています(式の中で「<」や「>」など特殊記号を使用する場合は注意してください)。

図3 IEによる変換結果の確認(filter.xml

 ここで使用しているサンプルのXMLファイルとXSLTファイルは、前回予習問題として取り上げたものです。これが、前回の問題(Q1)の解答となります。

 このサンプルでは、[ ]内にtrue/falseが返る条件式を記述していますが、数値(または数値を返す式)も記述できます。その場合、n番目の要素を指定します。

 リスト3と同じ内容のXMLファイル(filter2.xml)に次のXSLTを適用してみます。

<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   version="1.0">
<xsl:template match="/" >
<HTML>  <BODY>
Second Employee<BR/>
=================<BR/>
   <xsl:apply-templates
    select="/EMPLOYEES/EMPLOYEE[2]"/>

  </BODY></HTML>
</xsl:template>

<xsl:template match="EMPLOYEE" >
      <xsl:value-of select="Name"/>
      <xsl:value-of select="Salary"/> <BR/>
</xsl:template>

</xsl:stylesheet>
リスト5 XSLT文書(filter2.xsl

 EMPLOYEE要素に対してテンプレートの呼び出しを行いますが、2番目のEMPLOYEEを指定しています。

図4 IEによる変換結果の確認(filter2.xml

 n番目の指定には、このように[2]と記述する方法もありますが、XPath関数のposition関数を使って、[position()=2]と記述しても同様に2番目のノードが得られます。予習問題(Q2)にあるように、 position() < nや position() > nという書式を取れば、n番目より前(後ろ)という指定になります。リスト3と同じ内容のXMLファイル(filter3.xml)に次のXSLTを適用してみます。

<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
<xsl:template match="/" >
<HTML>  <BODY>
First 2 Employee<BR/>
=================<BR/>
   <xsl:apply-templates
    select="/EMPLOYEES/EMPLOYEE[position()&lt;3]"/>

  </BODY></HTML>
</xsl:template>
<xsl:template match="EMPLOYEE" >
      <xsl:value-of select="Name"/>
      <xsl:value-of select="Salary"/> <BR/>
</xsl:template>
</xsl:stylesheet>
リスト6 XSLT文書(filter3.xsl

 EMPLOYEE要素に対してテンプレートの呼び出しを行いますが、3番目より前のEMPLOYEEを指定しています。

図5 IEによる変換結果の確認(filter3.xml

参考

 ノードに対する条件の指定は、ロケーションパスの途中のノードでも記述することができます。以下に例を挙げます。

/EMPLOYEES/EMPLOYEE[position()&lt;3]/Name


今回の問題の解答

 それでは、予習問題の解答です。

(Q1) 共通のXMLからSalaryが400000以上の社員情報を取得したい。共通のXSLTのテンプレートの(1)に入れるべき記述として正しいものを選択してください。


 答えは、(b)の/EMPLOYEES/EMPLOYEE[Salary&gt;=400000]です。

 「ロケーションパス(条件式)」で、この問題をサンプルに取り上げていますので、もう一度確認しておきましょう。

(Q2) 共通のXMLのEMPLOYEEのうち、先頭の2件(データの記述順)の社員情報を取得したい。共通のXSLTのテンプレートの(1)に入れるべき記述として正しいものを選択してください。

 答えは、(c)の/EMPLOYEES/EMPLOYEE[position()&lt;3]です。

 n番目の指定で、「=」を使う場合、position関数を使って

[position()=2]

と記述する代わりに、

[2]

のような指定もできます。しかし、「<」「>」を使用する場合は、position関数が必要となります。

[position() &lt;3]

という指定は

[&lt;3]

とは記述できません。「ロケーションパス(条件式)」で、この問題をサンプルに取り上げていますので、もう一度確認しておきましょう。

次回の予習問題

 次回のために予習問題を掲載します。

 次回は名前空間DOMです。名前空間はXMLを活用するうえで何かと使用されている機能です。基本的な概念や宣言方法を紹介します。また、DOMはJavaなどのアプリケーションからXMLを操作するときに使用する標準のAPIです。詳しい内容は、XMLマスター・プロフェッショナルの範疇になりますが、次回はXMLマスター・ベーシックの範疇である基本的な内容を紹介します。

予習問題

(Q1) 下記に示されるXMLインスタンスがあります。NAME要素のnickname属性が属する名前空間はどれでしょう。

<EMPLIST  xmlns="http://www.abc.com/employee">
  <EMPLOYEE  id ="A0149">
    <NAME  xmlns="http://www.abc.com/emp2"
           nickname="Taka" >Taro Yamada</NAME>
    <DEPT>Sales</DEPT>
  </EMPLOYEE>
</EMPLIST>

(a)次の名前空間に属する
http://www.abc.com/employee

(b)次の名前空間に属する
http://www.abc.com/emp2

(c)下記の2つの名前空間に属する
http://www.abc.com/employee
http://www.abc.com/emp2

(d)どの名前空間にも属さない

(Q2) DOMに関する説明として正しいものをすべて選んでください。

 (a)DOMツリーと呼ばれるツリーを構築して各ノードにアクセスする
 (b)
ノードにアクセスするためのAPIが規定されている
 (c)
Javaプログラム言語用のAPIである
 (d)
ツリーの最上位のノードはドキュメントノードである
 


まとめノート:XPathによるノードの指定法を理解する

○今回の試験対策のポイント

  • XPathの概要
  • XPathのデータモデル
    • ノードの種類
  • ロケーションパス
    • ロケーションパスの記述方法
    • ノードテスト
    • 条件式

○今回の学習内容で出題範囲となる仕様

○今回の学習内容で参考になる@ITの記事

○今回の学習内容で参考になるXML用語集 @IT XML用語事典より)

(13)名前空間を理解しDOMの概要をつかむ

Index
連載:XMLマスターへの道
  (1)XMLマスター:ベーシック試験のレベルは?
  (2)XMLの概要と起源、関連規格
  (3)XML文書の要素、エンコーディング、宣言
  (4)すべてのXM文書は整形式である
  (5)valid XMLとDTDの関係
  (6)模擬問題:XMLの基本
  (7)模擬問題:W3C XML Schema
  (8)模擬問題:DOM
  (9)DTDの実体宣言と記法宣言
  (10)XSLTの基本構造を理解する
  (11)XSLTで必須の制御命令を覚える
(12)XPathによるノードの指定法を理解する
  (13)名前空間を理解しDOMの概要をつかむ
  (14)XML Schemaを利用したスキーマ定義
  (最終回)XML Schema―型の再利用と名前空間


連載:XMLマスターへの道


XML & SOA フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

HTML5+UX 記事ランキング

本日月間