前回に引き続き,今回もはてなダイアリー形式からJUGEM形式に変換するXSLTスタイルシートを例に,XSLTの基本構文を学習します。

 以下のXSLTスタイルシートでも前回と同じ結果を出力することができます。今回はこのXSLTスタイルシートを使って,解説します。


例1 はてなダイアリー形式からJUGEM形式に変換するXSLTスタイルシート

[画像のクリックで拡大表示]

◇xsl:apply-templates命令

 xsl:apply-templates命令(例1の18行目,25行目,28行目)は,select属性で指定されたノードを選択し,選択されたノードセット内の各ノードに対してパターンが一致するテンプレートルールを探し,テンプレートを実行します。

テンプレートルールの呼び出し

  <xsl:apply-templates select="diary/day" />

呼び出されるテンプレートルール

  <xsl:template match="day">
・・・
</xsl:template>

 前回のXSLTスタイルシートとの違いは,xsl:for-each命令の記述を変更し,xsl:apply-templates命令でテンプレートを実行しているところです。xsl:for-each命令はxsl:apply-templates命令で代用することができるわけです。

 xsl:for-each命令は,select属性のXPath式で選択されたノードセットの各ノードに対して,xsl:for-each命令内のテンプレートを適用します。一方,xsl:apply-templates命令は前述のとおり,パターンが一致するテンプレートルールを選択して,呼び出します。

◇xsl:sort命令

 xsl:apply-templates命令,xsl:for-each命令には,xsl:sort要素を適用でき,xsl:apply-templates命令,xsl:for-each命令で選択されたノードセット内の順番を並び替えることができます。ただし,xsl:for-each命令にxsl:sort要素を適用する場合,xsl:for-each命令内のテンプレートより先に記述する必要があります。

 具体的には,まずxsl:sort要素のselect属性にソートのキーとなる値を抽出するためのXPath式を記述します。例えば,カレントノード(現在のノード)を指定する場合は「.」を記述します。そして,data-type属性に文字("text")としてソートするか,数値("number")としてソートするかを指定します。省略時は"text"となります。order属性に昇順("ascending")とするか降順("descending")とするかを指定し,省略すると"ascending"となります。

xsl:apply-templates命令にxsl:sort要素を適用した例

  <xsl:apply-templates select="diary/day">
<xsl:sort select="@date" data-type="text" order="ascending" />
</xsl:apply-templates>

xsl:for-each命令にxsl:sort要素を適用した例

  <xsl:for-each select="diary/day">
<xsl:sort select="@date" data-type="text" order="ascending" />
・・・
</xsl:for-each>

確認問題1
次のXML文書にXSLTスタイルシートを適用した場合,正しい変換結果を選択してください。

XML文書
<root>
 <e1>7</e1>
 <e1>1</e1>
 <e1>8</e1>
 <e1>2</e1>
</root>
XSLTスタイルシート
<?xml version="1.0" encoding="Shift_JIS"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" />

  <xsl:template match="/">
    <xsl:apply-templates select="root/e1">
      <xsl:sort select="." data-type="number" order="descending" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="e1">
    <xsl:value-of select="." />
  </xsl:template>
</xsl:stylesheet>

(a) 1278

(b) 8721

(c) 7182

(d) xsl:sort要素の記述に誤りがあるため正しく変換されない。

 正解は(b)です。xsl:sort要素のorder属性に"ascending"を指定すれば,(a)の結果を得ることができます。(b)は正しい変換結果です。(c)は,xsl:sort要素を適用しない場合の変換結果です。xsl:sort要素の記述に誤りはないため,(d)は正しくありません。

◇「|」演算子

  <xsl:template match="@title|@date">
・・・
</xsl:template>

 「|」演算子(例1の36行目)は,ノードの「和集合」を表し,ノードの選択やパターンで記述することができます。上の例では,title属性またはdate属性にこのテンプレートルールが適用されます。

◇xsl:element命令

  <xsl:element name="{name(.)}">
・・・
</xsl:element>

 xsl:element命令(例1の37行目)は出力結果として要素ノードを作成します。作成する要素の名前を指定するname属性には,「属性値テンプレート」(属性値が「{}」で囲まれて表現されている)を使用することで,XPath式を記述できます。このため,元のXML文書のデータを基に,要素の名前を動的に付けることができます。

 上の例では「name()」という,Xpath式で利用できるname関数を記述しています。name関数は,XPath式でカッコの中に指定したノードセット内の最初のノードの名前を返す関数です。ここでは,カッコ内に「.」を指定することで,カレントノードの属性名を取得し,その名前の要素を作成しています。xsl:attribute命令を使用すれば,属性ノードを作成できます。使い方はxsl:element命令と同じです。

確認問題2
XSLTスタイルシートにおいて,新たにノードを作成するための命令を選択してください。

(a) xsl:apply-templates命令

(b) xsl:sort要素

(c) xsl:element命令

(d) xsl:attribute命令

 正解は(c),(d)です。(a)はselect属性で指定されたノードを選択し,選択されたノードセット内の各ノードに対してパターンが一致するテンプレートルールを探し,テンプレートを実行します。 (b)はxsl:apply-templates命令,xsl:for-each命令で選択されたノードセット内の順番を並び替えるための命令です。(c)は要素ノードを作成するための命令。(d)は属性ノードを作成するための命令です。

 残りの説明は次回に・・・。



野中 康弘
インフォテリア 教育部 エンジニア。十数年間システム開発に携わり,そのうちの半分をデータベース管理者として奮闘する。現在は,インフォテリア認定教育センターのサポートや,XML技術者認定制度の「XMLマスター」に対応したコーステキストの開発などを担当している。