前回に引き続き,今回もはてなダイアリー形式からJUGEM形式に変換するXSLTスタイルシートを例に,XSLTの基本構文を学習します。なお,例1のXSLTスタイルシートは第4回と同じ内容です。
例1 はてなダイアリー形式からJUGEM形式に変換するXSLTスタイルシート
 |
[画像のクリックで拡大表示] |
◇xsl:if命令
xsl:if命令(例1の38行目,41行目)は,test属性で指定された条件が真の場合にxsl:if命令の内容に記述されたテンプレートを実行します。test属性にはXPath式を記述し,真偽を判断します。
xsl:if命令による条件分岐
<xsl:if test="name()='date'">
・・・
</xsl:if>
|
test属性のXPath式に使用できる演算子は表1のとおりです。ただし,「<」や「<=」を使用する場合,「<」は『タグの開始』と見なされてしまうため,定義済み実体参照を使用して,「<」は「<」,「<=」は「<=」と記述します。「>」,「>=」は定義済み実体参照を使用しなくても記述できますが,「>」,「>=」と記述することで,見やすいXSLTスタイルシートを作成できます。
表1●XPath式で使用できる演算子
数値演算子 |
+ |
加算(足し算)
|
- |
減算(引き算) |
* |
乗算(掛け算) |
div |
除算(割り算) |
mod |
除算した結果の余り |
論理演算子 |
and |
論理積(左辺が偽のときは右辺を評価しない) |
or |
論理和(左辺が真のときは右辺を評価しない) |
比較演算子 |
= |
等しい |
!= |
等しくない |
< |
より小さい( < と記述する) |
> |
より大きい( > と記述することもできる) |
<= |
以下( <= と記述する) |
>= |
以上( >= と記述することもできる)
|
|
XSLTには一般的なプログラミング言語の「if ~ else ~」のelseに相当する命令がありません。しかし,XPathのnot関数を使うことで真偽の値を反転させることができます。例えば,「在庫数」要素の内容と「販売数」要素の内容を,xsl:if命令を使用して条件分岐する場合には,以下のような記述になります。
例:xsl:if命令のnot関数による真偽値の反転
<xsl:if test="在庫数 > 販売数">
商品の在庫があります。
</xsl:if>
<xsl:if test="not(在庫数 > 販売数)">
商品の在庫がありません。発注を依頼してください。
</xsl:if>
|
◇xsl:choose命令
XSLTで使用できる条件分岐の命令は,もう1つあります。それは,xsl:choose命令です。xsl:choose命令は,xsl:choose命令の内容として記述された一連のテンプレート(xsl:when要素またはxsl:otherwise要素)のうちのいずれか1つだけを実行します。xsl:choose命令を使用する際の制限としては,xsl:choose命令の内容に1つ以上のxsl:when要素が必要となります。xsl:otherwise要素は省略することもでき,記述する場合には1つだけとなります。xsl:when要素のtest属性は,前述のxsl:if命令と同じです。例1のXSLTスタイルシートの38行目~43行目をxsl:choose命令を使用して記述すると,以下のようになります。
xsl:choose命令を使用した例
<xsl:choose>
<xsl:when test="name()='title'">
<xsl:value-of select="." />
</xsl:when>
<xsl:when test="name()='date'">
<xsl:value-of select="translate(.,'-','/')" />
</xsl:when>
</xsl:choose>
|
確認問題1 次の条件分岐命令のうち,正しく記述されているものを選択してください。 |
(a) |
<xsl:if test="売上目標 < 売上">売上目標を達成しました。</xsl:if>
|
(b) |
<xsl:if test="売上目標 > 売上">売上目標を達成できませんでした。</xsl:if>
<xsl:else>売上目標を達成しました。</xsl:else>
|
(c) |
<xsl:choose>
<xsl:when test="売上目標 < 売上">売上目標を達成しました。</xsl:when>
<xsl:choose>
|
(d) |
<xsl:choose>
<xsl:otherwise test="売上目標 < 売上">売上目標を達成しました。</xsl:otherwise>
</xsl:choose>
|
|
正解は(c)です。(a)は,比較演算子に「<」を使用しています。「<」は『タグの開始』と見なされてしまいますので,定義済み実体参照「<」を使用しなければなりません。(b)は,xsl:if命令は正しく記述されていますが,XSLTではxsl:else命令はありません。(c)は正しく記述されています。xsl:otherwise要素は省略することができます。xsl:choose命令の内容には,1つ以上のxsl:when要素が記述されていなければならず,xsl:otherwise要素のみを記述することはできません。このため(d)は誤りです。
次にXSLTでノードをコピーする2つの命令について解説します。
◇xsl:copy-of命令
xsl:copy-of命令は,ソースXML文書(元となるXML文書)の一部をそのままコピーしたい場合に使用します。select属性で指定したXPath式に該当するノードを属性や子孫ノードを含めて,すべてそのままコピーします。
<xsl:template match="/">
<blog>
<entries>
<xsl:copy-of select="diary/day" />
</entries>
</blog>
</xsl:template>
|
上記の例では,「day」要素,「date」属性,「title」属性,「body」要素がコピーされます(図1)。ただし,xsl:copy-of命令のselect属性にルートノード(/)を指定した場合は,ルートノードはコピーされず,その子孫ノードがコピーされます。
 |
図1●変換後のXML文書の構造
|
ルートノード(/)はルート要素ではありません。XPathでは,ルート要素はルートノードの子ノードとなりますので,注意が必要です(図2)。
 |
図2●XPathでのルートノードとルート要素の違い
|
xsl:copy-of命令を使用した変換結果
 |
[画像のクリックで拡大表示] |
◇xsl:copy命令
xsl:copy命令は,xsl:copy-of命令とは異なり,カレントノードが要素の場合は,要素だけをコピーし,その要素が持っている属性や子孫ノードをコピーしません。xsl:copy命令は,カレントの要素だけをコピーして新しい属性を追加したり,要素の内容を変更したりする場合に使用します。
<xsl:template match="/">
<blog>
<entries>
<xsl:apply-templates select="diary/day" />
</entries>
</blog>
</xsl:template>
<xsl:template match="day">
<xsl:copy>
<date><xsl:value-of select="@date" /></date>
<title><xsl:value-of select="@title" /></title>
<description><xsl:value-of select="body" /></description>
</xsl:copy>
</xsl:template>
|
xsl:copy-of命令を使用した変換結果
 |
[画像のクリックで拡大表示] |
確認問題2
次のXML文書にXSLTスタイルシートを適用した場合,正しい変換結果を選択してください。
XML文書
<?xml version="1.0" encoding="Shift_JIS" ?>
<diary>
<day date="2006-08-30" title="ようやくXML Schemaの勉強開始" >
<body>今日XML Schemaの勉強を開始しました。結構難しい・・・</body>
</day>
</diary>
XSLTスタイルシート
<?xml version="1.0" encoding="Shift_JIS"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<data>
<xsl:copy-of select="." />
</data>
</xsl:template>
</xsl:stylesheet>
(a) |
<?xml version="1.0" encoding="UTF-8"?>
<data>
<diary>
<day date="2006-08-30" title="ようやくXML Schemaの勉強開始">
<body>今日XML Schemaの勉強を開始しました。結構難しい・・・</body>
</day>
</diary>
</data>
|
(b) |
<?xml version="1.0" encoding="UTF-8"?>
<data>
<day date="2006-08-30" title="ようやくXML Schemaの勉強開始">
<body>今日XML Schemaの勉強を開始しました。結構難しい・・・</body>
</day>
</data>
|
(c) |
<?xml version="1.0" encoding="UTF-8"?>
<data>
<diary/>
</data>
|
(d) |
xsl:copy-of命令のselect属性の記述に誤りがあるので,正しい変換結果はない。 |
|
この問題のXSLTスタイルシートでは,ルートノードを処理するテンプレートルールの中で,xsl:copy-of命令が記述されており,そのselect属性にはカレントノード「.」が指定されています。すなわち,このXSLTスタイルシートはルートノードを含め,属性やその子孫要素,すべてコピーするように記述されています。よって正解は(a)です。
インフォテリア 教育部エンジニア。十数年間システム開発に携わり,そのうちの半分をデータベース管理者として奮闘する。現在は,インフォテリア認定教育センターのサポートや, XML技術者認定制度の「XMLマスター」に対応したコーステキストの開発などを担当している。 |
|