データベース入門 資料 7
XSLT スタイルシートの基本構造と反復処理

今野 英明

平成27年5月25日


目次


1 XSLT スタイルシートの基本構造

XSLT スタイルシート(以下,単にスタイルシートと呼ぶことがある)は,XML 文書をどのような形に変換するかを,XSLT で記したものである。

次の例は,前回の資料で紹介した,変換対象となる XML 文書から,XML 宣言やタグ等を除いた文字データ部分をすべて出力するスタイルシートである。

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="UTF-8" />
  <xsl:template match="/">
    <xsl:value-of select="/" />
  </xsl:template>
</xsl:stylesheet>

XSLT スタイルシート自体も整形式の XML 文書なので,スタイルシートにも XML の用語(XML 宣言や要素,属性等)や規則が当てはまることは紹介済みである。 それに加え,XSLT には独自の規則や役割を持つ要素があるので,上記のスタイルシートを元にこれらを説明する。

2 XSLT の反復構造

前回資料の XML 文書例(以下,単に「XML 文書例」と呼ぶ)を以下に示す。
<?xml version="1.0" ?> 
<ref>
 <book isbn="1111">
  <title>Title1</title>
  <author>Author1</author>
 </book>
 <book>
  <title>Title2</title>
  <author>Author2</author>
 </book>
 <web>
  <title>Title3</title>
 </web>
</ref>
本章では,この XML 文書例から
Title1 Title2
のような出力を得るための XSLT テンプレートの書き方を紹介する。 このような出力はノードセット /reb/book に''反復処理''を施すことで得られる。 XML 文書例の構造を木構造で表現した図も以下に再掲する。
/
|
+- ref
    |
    +- book
    |   |
    |   +- @isbn (1111)
    |   |
    |   +- title (Title1)
    |   |                 
    |   +- author (Author1)   
    |   
    +- book   
    |   |
    |   +- title (Title2)   
    |   |
    |   +- author (Author2)
    |   
    +- web   
        |   
        +- title (Title3)


2.1 XSLT における相対ロケーションパスの基点

XSLT における相対ロケーションパスの基点は,カレントノード (current node) と呼ばれる, 現在処理中のノードであり,これを .(ドット)で表す。

XSLT スタイルシートでは,ロケーションパスをテンプレート内で使うが, その際の (初期の) カレントノードは xsl:template 要素の match 属性によって決まる。 例えば,<xsl:template match="/"> で始まるテンプレート内の初期カレントノードはルートノードである。 従って, このテンプレートでは / と . は等価であり, <xsl:value-of select="/" /><xsl:value-of select="." /> の出力は同じである。 また, ロケーションパス /ref/book と ./ref/book および ref/book は等価である。

ただし, テンプレート内にカレントノードを変更する XSLT の要素があれば, その中ではカレントノードに応じて相対ロケーションパスの基点が変わる 2


2.2 xsl:for-each 要素による反復

XSLT スタイルシートのテンプレート内に xsl:for-each 要素を置くことで, テンプレート内で反復処理を指定することができる。 次に示すのは xsl:for-each を使ったスタイルシートの例である。
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="UTF-8" />
  <xsl:template match="/">
    <xsl:for-each select="/ref/book">
      <xsl:value-of select="title" />
      <xsl:value-of select="author" />
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>
これを XML 文書例に適用すると,次の出力が得られる3
Title1Author1Title2Author2
以下では,上記のスタイルシートのうち, xsl:for-each の動作に関わる部分について説明する。

3 データの並べ換えと空白文字の出力

第 2.2節の XSLT スタイルシートにおいて, xsl:for-each 要素を
<xsl:for-each select="/ref/book">
  <xsl:sort order="descending"/>
  <xsl:value-of select="title" />
  <xsl:text> </xsl:text>
  <xsl:value-of select="author" />
  <xsl:text>
</xsl:text>
</xsl:for-each>
に変更して,XML 文書例を処理すると,出力は次のとおりとなる。
Title2 Author2
Title1 Author1
この出力を得るために行っているテンプレート内の処理について,以下に記す。


3.1 xsl:sort 要素による並べ換え

xsl:for-each 要素は,特に指定しなければ, XML 文書に現れた順にカレントノードを変更して反復処理を行うが, xsl:for-each の内容の始めに xsl:sort 要素を置くことで, 処理の順序を変更できる。

例えば,先の <xsl:sort order="descending"/> は, 出力される文字列値が辞書の逆順(降順)になるように, xsl:for-each が処理するノードの順序を並べ換えるものである。

xsl:order 要素の動作を指定する属性は幾つかあり, order 属性は並べ換えの順を指定するものである。 属性値には ascending (昇順)か descending (降順)を指定する (order 属性を略すと昇順になる)。

他の属性としては,並べ換えに使うキーを指定する select 属性があり, <xsl:sort select="author" order="descending"/> とすれば,author ノードの文字列値が降順になるように, 処理順序の並べ換えが行われる。


3.2 xsl:text 要素を使った空白文字の出力

第 2.2 節の実行結果において, 空白や改行無しに Title1 や Author1 などが続いて出力されたのは, テンプレート内で, 空白文字(ブランクや改行)からなる文字データをタグの外に書いても, それらが出力されないためである。

テンプレートに記述した空白や改行を出力したければ, xsl:text 要素が使える。 例えば,内容が空白文字である xsl:text 要素

<xsl:text> </xsl:text>
<xsl:text>
</xsl:text>
をテンプレート内に書けば,空白や改行を出力できる。


4 練習問題

  1. 2.2 節の XSLT スタイルシートにおける xsl:value-of 要素の select 属性値 title と author を,各々 /ref/book/title と /ref/book/author に変更して, XML 文書例 (/pub/db_a/xml/data_model.xml) を xsltproc コマンドで処理してみなさい。 その出力が得られる理由を考えなさい。

  2. 参考文献の XML データ (/pub/db_a/xml/ref.xml) から, title 要素の内容のみを全て出力するための XSLT テンプレートを作成し, xsltproc コマンドで処理しなさい。 xsl:for-each 要素を使うこと。 xsl:text 要素を使って,適切な改行を出力すること。 xsl:sort 要素の使い方も確認してみなさい。

  3. 「資料 5. XMLの基礎」の 4. 練習問題の 4. で作成した郵便番号の XML 文書から,元の設問にあるような郵便番号の一覧を作るための XSLT テンプレートを作成しなさい。 ただし,各列の標題である「市名 町名 郵便番号」の出力は省いてよい。



脚注

... 形式1
text 形式は変換結果からタグを除去 (テキストノードの内容のみ出力) し, 文字データのエスケープ (変換) を行わないで出力する形式。 text の他には xml と html がある。
... その中ではカレントノードに応じて相対ロケーションパスの基点が変わる2
xsl:for-each 要素がこれに該当する。
... 文書例に適用すると,次の出力が得られる3
xsltproc /pub/db_a/xml/for_each.xsl /pub/db_a/xml/data_model.xml