XMLマスターポイントレッスン ~ ベーシック編 ~
第10回 XSLTのさまざまな機能
インフォテリア認定教育センター 鈴木智也 SUZUKI, Tomoya
今回は、XSLTの豊富な機能を2つのテーマに絞って紹介します。1つは、より高度なXSLTスタイルシートを記述するために必要な制御命令、もう1つは、XSLTスタイルシートによる XML 文書の生成です。XSLTスタイルシートでは、元になるXML 文書からHTML 文書だけでなく別の構造のXML 文書なども生成できます。 前回同様、ベーシックV2 試験のセクション5「XSLT/XPath」を攻略するための必須知識ですので、しっかり学習しましょう。
XSLTの制御命令
XSLTスタイルシートには、プログラミング言語のように選択処理や反復処理を行なうための命令が用意されています。これらの命令により、変換内容を条件によって変更したり、項目を繰り返し処理したりすることができます。
選択処理
選択処理としては、条件が真となる場合のみ処理を実行する「xsl:if命令」と、条件分岐で最初に真となる処理を実行する「xsl:choose命令」の2種類が用意されています。
条件付きの処理xsl:if命令
xsl:if命令では、test属性に記述したXPath式によって、結果が真であればそのxsl:if命令内に書かれたテンプレートを実行します(図1)。真でなければ何も実行しません。プログラミング言語のようにif~else~というような、真でない場合に対応するテンプレートの記述はありません。そのような場合は、次に紹介するxsl:choose命令を使用します。
それでは、xsl:if命令の例を見てみましょう。ソースXML文書(LIST1)にXSLTスタイルシート(LIST2)を適用します。これは商品をリスト表示するHTMLを生成するためのスタイルシートです。このとき、新製品属性の属性値が「true」となっている場合には、リストに「新製品」マークを表示します(LIST2の18行目)。このように、ある条件に合致するときだけ何かを表示させたい場合にxsl:if命令を使って処理を選択できます。
LIST1:ソースXML文書(list1.xml)
01 <xml version="1.0" encoding="Shift_JIS"?>
02 <?xml-stylesheet type="text/xsl" ⇒
href="list2.xsl"?>
03 <商品リスト>
04 <商品コード="XML001" 新製品="true">
05 <品名>XMLボールペン</品名>
06 <単価>500</単価>
07 </商品>
08 <商品コード="XML002">
09 <品名>XMLマウスパッド</品名>
10 <単価>150</単価>
11 </商品>
12 </商品リスト>
(※誌面の都合により⇒で折り返しています。なお、行番号は解説の便宜上付けたもので、
実際のコードには不要です。以下同)
LIST2:XSLTスタイルシート(list2.xsl)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <xsl:stylesheet version="1.0"
03 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
04 <xsl:template match="/">
05 <html>
06 <body>
07 <h1>商品リスト</h1>
08 <table border="1">
09 <tr><th>商品名</th><th>単価</th></tr>
10 <xsl:apply-templates select="商品リスト/商品" />
11 </table>
12 </body>
13 </html>
14 </xsl:template>
15 <xsl:template match="商品">
16 <tr>
17 <td>
18 <xsl:if test="@新製品='true'" >[新製品]</xsl:if>
19 <xsl:value-of select="品名" />
20 </td>
21 <td><xsl:value-of select="単価" /></td>
22 </tr>
23 </xsl:template>
24 </xsl:stylesheet>
条件分岐の処理xsl:choose命令
条件によって何通りかのテンプレートを使い分けたいときには、xsl:choose命令を使います(図2)。
xsl:choose命令の子要素としてxsl:when命令を記述します。xsl:when命令に指定されたtest属性が真となる場合、そのxsl:when命令内のテンプレートを実行します。複数のxsl:when命令を記述することもでき、その場合には最初に真となるxsl:when命令内のテンプレートだけが実行されます。
また、xsl:choose命令内にはxsl:otherwise命令を1つだけ記述することもできます。xsl:when命令のtest属性に真となるものがなかった場合、xsl:otherwise命令内のテンプレートが処理されます。xsl:when命令のtest属性に真となるものがなく、xsl:otherwise命令が記述されていない場合は何も実行されません。 LIST3のXML文書内には備考要素(7行目、12行目)があり、LIST4のXSLTスタイルシートを適用して内容をHTML形式で出力します。
LIST3:XML文書(list3.xml)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <?xml-stylesheet type="text/xsl" href="list4.xsl"?>
03 <商品リスト>
04 <商品コード="XML001">
05 <品名>XMLボールペン</品名>
06 <単価>500</単価>
07 <備考>限定30名</備考>
08 </商品>
09 <商品コード="XML002">
10 <品名>XMLマウスパッド</品名>
11 <単価>150</単価>
12 <備考/>
13 </商品>
14 </商品リスト>
LIST4:XSLTスタイルシート(list4.xsl)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <xsl:stylesheet version="1.0"
03 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
04 <xsl:template match="/">
05 <html>
06 <body>
07 <h1>商品リスト</h1>
08 <table border="1">
09 <tr><th>商品名</th><th>単価</th><th>備考⇒
</th></tr>
10 <xsl:apply-templates select="商品リスト/商品" />
11 </table>
12 </body>
13 </html>
14 </xsl:template>
15 <xsl:template match="商品">
16 <tr>
17 <td><xsl:value-of select="品名" /></td>
18 <td><xsl:value-of select="単価" /></td>
19 <xsl:choose>
20 <xsl:when test="備考/text()">
21 <td><xsl:value-of select="備考" /></td>
22 </xsl:when>
23 <xsl:otherwise>
24 <td>とくにありません</td>
25 </xsl:otherwise>
26 </xsl:choose>
27 </tr>
28 </xsl:template>
29 </xsl:stylesheet>
このとき、備考要素にテキスト内容が記述されていればその内容を出力し、テキスト内容が記述されていない場合には「とくにありません」というメッセージを出力します。
LIST5では、売上情報をLIST6のXSLTスタイルシートを適用してHTML形式で出力します。このとき、売上の数量に応じてbgcolor属性によって背景色を指定して表示します。通常は背景色なしで出力します。
LIST5:XML 文書(list5.xml)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <?xml-stylesheet type="text/xsl" href="list6.xsl"?>
03 <売上表>
04 <商品コード="XML001">
05 <品名>XMLボールペン</品名>
06 <単価>500</単価>
07 <数量>2</数量>
08 </商品>
09 <商品コード="XML002">
10 <品名>XMLマウスパッド</品名>
11 <単価>150</単価>
12 <数量>18</数量>
13 </商品>
14 <商品コード="XML003">
15 <品名>XMLストラップ</品名>
16 <単価>150</単価>
17 <数量>13</数量>
18 </商品>
19 </売上表>
LIST6:XSLT スタイルシート(list6.xsl)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <xsl:stylesheet version="1.0"
03 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
04 <xsl:template match="/">
05 <html>
06 <body>
07 <h1>売上リスト</h1>
08 <table border="1">
09 <tr><th>商品名</th><th>単価</th><th>数量</th></tr>
10 <xsl:apply-templates select="売上表/商品" />
11 </table>
12 </body>
13 </html>
14 </xsl:template>
15 <xsl:template match="商品">
16 <tr>
17 <td><xsl:value-of select="品名" /></td>
18 <td><xsl:value-of select="単価" /></td>
19 <xsl:choose>
20 <xsl:when test="数量>15">
21 <td bgcolor="lightgreen"><xsl:value-of select=quot;数量" /></td>
22 </xsl:when>
23 <xsl:when test="数量>10">
24 <td bgcolor="lightblue"><xsl:value-of select="数量" /></td>
25 </xsl:when>
26 <xsl:otherwise>
27 <td><xsl:value-of select="数量" /></td>
28 </xsl:otherwise>
29 </xsl:choose>
30 </tr>
31 </xsl:template>
32 </xsl:stylesheet>
反復処理
選択されたノードごとにテンプレートを繰り返し処理する場合には、「xsl:apply-templates命令」や「xsl:for-each命令」を使うことができます。
繰り返し処理するxsl:for-each命令
xsl:for-each命令のselect属性にノードセットとなるようなXPathを指定し、選択されたノードごとにxsl:for-each内のテンプレートを繰り返し実行します(図3)。
例えば、LIST7に記述された講座の情報をLIST8のXSLTスタイルシートを適用してHTML形式で出力します。このとき、内容要素内の章要素ごとに繰り返し箇条書きで出力されます。xsl:for-each命令内では選択されたノードがカレントノードとなるので、内部で相対パスを指定するときには注意が必要です(LIST8の12行目)。
LIST7:XML文書(list7.xml)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <?xml-stylesheet type="text/xsl" href="list8.xsl"?>
03 <講座詳細>
04 <コース名>XML入門</コース名>
05 <コード>1234</コード>
06 <内容>
07 <章>XMLの概要</章>
08 <章>XML文書の作成</章>
09 <章>DTD</章>
10 <章>XML Schema</章>
11 <章>XSLT, XPath</章>
12 <章>名前空間</章>
13 </内容>
14 </講座詳細>
LIST8:XSLTスタイルシート(list8.xsl)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <xsl:stylesheet version="1.0"
03 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
04 <xsl:template match="/">
05 <html>
06 <body>
07 <h1><xsl:value-of select="講座詳細/コース名" /></h1>
08 コース名:<xsl:value-of select="講座詳細/コース名" /><br/>
09 コースコード:<xsl:value-of select="講座詳細/コード" /><br/>
10 内容:<br/>
11 <xsl:for-each select="講座詳細/内容/章">
12 ・<xsl:value-of select="." /><br/>
13 </xsl:for-each>
14 </body>
15 </html>
16 </xsl:template>
17 </xsl:stylesheet>
xsl:apply-templatesとxsl:for-eachの使い分け
xsl:apply-templates命令では、選択されたノードセットに対し個々にxsl:template要素が適用されるため、xsl:for-each命令と同じように反復処理を表現することもできます。xsl:for-each命令は小規模の繰り返しを表現するのに適しており、データ内の末端の小項目を単純に繰り返し出力する場合にはとても便利です。
しかし、データ内の大きな項目を繰り返すときには、その内部の小項目を変換するテンプレートルールが長くなるため、xsl:foreach命令で繰り返しを表現すると命令自体の記述が長くなってしまいます。また、複雑な入れ子構造となるためインデントが深くなってしまいます。このように、xsl:for-each命令のみですべての繰り返しを記述しようとすると、スタイルシート全体の流れが見通しにくくなります。
そこで、プログラミングのサブルーチンのように、表示したい項目をxsl:template要素で1つのテンプレートルールとして作成しておき、xsl:apply-templates命令で選択した項目を適用するようにします。このとき、表示項目ごとにテンプレートルールで分割したほうが分かりやすくなります。また、xsl:for-each命令ではその内部に記述された1つのテンプレートのみを繰り返しますが、xsl:template要素のmatch属性には述部を用いたXPathを指定することもできるので、適用するテンプレートルールを切り替えることもできます(図4)。
図4:テンプレートルールによる変換方法の切り替え
さらに、xsl:for-each命令の中でxsl:choose命令を組み合わせて分岐することもできますが、記述が長くなって見にくくなるので、記述文量によって使い分けると良いでしょう。
XML文書の生成
XSLTを利用することで、ソースXML文書を別の構造の文書へ変換できます。前回まではHTML形式への変換を中心に話を進めてきましたが、HTML以外にもXML文書やテキスト文書、別のフォーマットのXML文書にも変換できるほか、文書の一部分を抜粋したり、CSV形式などへも変換できます。
要素や属性の生成
テンプレートルール内に、直接要素や属性を記述することで、変換結果として要素や属性を出力できます。例えば、LIST9のソースXML文書では日本語の要素名を使ってデータが記述されていますが、LIST10のXSLTスタイルシートによって英語要素名のXML文書へと変換できます。
LIST9:XML文書(list9.xml)
1 <?xml version="1.0" encoding="Shift_JIS"?>
2 <?xml-stylesheet type="text/xsl" href="list10.xsl"?>
3 <商品リスト>
4 <商品コード="XML001">
5 <品名>XMLボールペン</品名>
6 <単価>500</単価>
7 </商品>
8 </商品リスト>
LIST10:XSLTスタイルシート(list10.xsl)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <xsl:stylesheet version="1.0"
03 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
04 <xsl:template match="/">
05 <products>
06 <item>
07 <name><xsl:value-of select="商品リスト/商品/品名" /></name>
08 <price><xsl:value-of select="商品リスト/商品/単価" /></price>
09 </item>
10 </products>
11 </xsl:template>
12 </xsl:stylesheet>
また、xsl:element命令やxsl:attribute命令を使って任意の名前で要素や属性を出力できます。xsl:element命令やxsl:attribute命令では、name属性に指定された値を要素名や属性名として出力できます(図5)。
xsl:element命令やxsl:attribute命令を使用することにより、ソースXML文書内の情報を基に要素名を決定できます。また、要素から属性への変換や属性から要素への変換も可能です。
属性から要素への変換
ソースXML文書で属性として記述されていたものを要素として出力できます。LIST10のXSLTスタイルシートでは、要素を直接記述しています。また、LIST11のXSLTスタイルシートでは、xsl:element命令を使ってソースXML文書に記述されているコード属性(LIST9の4行目)を要素として出力します(LIST11の7行目~9行目)。
LIST11:XSLTスタイルシート(list11.xsl)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <xsl:stylesheet version="1.0"
03 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
04 <xsl:template match="/">
05 <xsl:element name="商品リスト">
06 <xsl:element name="商品">
07 <xsl:element name="コード">
08 <xsl:value-of select="商品リスト/商品/@コード" />
09 </xsl:element>
10 <xsl:element name="品名">
11 <xsl:value-of select="商品リスト/商品/品名" />
12 </xsl:element>
13 <xsl:element name="単価">
14 <xsl:value-of select="商品リスト/商品/単価" />
15 </xsl:element>
16 </xsl:element>
17 </xsl:element>
18 </xsl:template>
19 </xsl:stylesheet>
ノードのコピー
XML文書から別のXML文書へ変換する場合、元のXML文書の一部をそのまま使える場合があります。このとき、「xsl:copy-of命令」や「xsl:copy命令」を使って元のXML文書から要素や属性をコピーして出力できます。
xsl:copy-of命令
xsl:copy-of命令のselect属性に指定されたノードとその子孫ノードを一括してコピーできます(図6)。
例えば、商品名が記述されているXML文書(LIST12)の中から、コードが「XML001」である商品要素のみを抽出するXSLTスタイルシート(LIST13)を適用したとします。この場合、xsl:copy-of命令により該当する商品要素を一括してコピーし、結果を出力します(LIST14)。
LIST12:XML文書(list12.xm l)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <?xml-stylesheet type="text/xsl" href="list13.xsl"?>
03 <売上表>
04 <商品コード="XML001">
05 <品名>XMLボールペン</品名>
06 <単価>500</単価>
07 <数量>2</数量>
08 </商品>
09 <商品コード="XML002">
10 <品名>XMLマウスパッド</品名>
11 <単価>150</単価>
12 <数量>18</数量>
13 </商品>
14 <商品コード="XML003">
15 <品名>XMLストラップ</品名>
16 <単価>150</単価>
17 <数量>13</数量>
18 </商品>
19 </売上表>
LIST13:XSLTスタイルシート(list13.xsl)
1 <?xml version="1.0" encoding="Shift_JIS"?>
2 <xsl:stylesheet version="1.0"
3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
4 <xsl:template match="/">
5 <商品情報>
6 <xsl:copy-of select="売上表/商品[@コード='XML001']"/>
7 </商品情報>
8 </xsl:template>
9 </xsl:stylesheet>
LIST14:変換結果(list14.xml)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <商品情報>
03 <商品コード="XML001">
04 <品名>XMLボールペン</品名>
05 <単価>500</単価>
06 <数量>2</数量>
07 </商品>
08 </商品情報>
xsl:copy命令
xsl:copy-of命令のように、一括してコピーするのではなく、部分的にコピーしたり、別の要素を追加したり、細かい単位でコピーする場合にはxsl:copy命令を使用することでカレントノードだけをコピーできます(図7)。
xsl:copy命令では、テンプレートルールと組み合わせることにより再帰的にコピーを繰り返します。
例えば、LIST15の9~13行目では、ノードを再帰的にコピーしています。また、16~20行目ではコード属性に対してテンプレートルールが適用され、属性を要素に変換してコピーしています。14~15行目のテンプレートルールは数量要素に対して適用されますが、テンプレートルールの中身が空のためコピーされません(LIST16)。
LIST15:XSLTスタイルシート(list15.xsl)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <xsl:stylesheet version="1.0"
03 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
04 <xsl:template match="/">
05 <商品情報>
06 <xsl:apply-templates select="売上表/商品[@コード='XML001']"/>
07 </商品情報>
08 </xsl:template>
09 <xsl:template match="*|text()">
10 <xsl:copy>
11 <xsl:apply-templates select="node()|@*"/>
12 </xsl:copy>
13 </xsl:template>
14 <xsl:template match="数量">
15 </xsl:template>
16 <xsl:template match="@コード">
17 <xsl:element name="{name(.)}">
18 <xsl:value-of select="."/>
19 </xsl:element>
20 </xsl:template>
21 </xsl:stylesheet>
LIST16:変換結果(list16.xml)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <商品情報>
03 <商品>
04 <コード> XML001 </コード>
05 <品名>XMLボールペン</品名>
06 <単価>500</単価>
07 </商品>
08 </商品情報>
xsl:param要素を使った値の格納
xsl:param要素により、変数名と値を関連付けて宣言できます。これにより、条件の値を複雑なXPathではなく変数名で表現し、分かりやすく記述できます。変数名と値を関連付けるには、次の2つの方法があります(図8)。
[1] select属性による値の指定
xsl:param要素のselect属性に値を指定します(LIST17の18行目)。XPathで指定する場合は属性値テンプレートを使用して指定します。
[2] テンプレートによる値の指定
xsl:param要素の子要素として値を指定します。ツリー構造の要素をテンプレートとして指定することもできます。
LIST17:XSLTスタイルシート(list17.xsl)
01 <?xml version="1.0" encoding="Shift_JIS"?>
02 <xsl:stylesheet version="1.0"
03 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
04 <xsl:template match="/">
05 <html>
06 <body>
07 <h1>売上リスト</h1>
08 <table border="1">
09 <tr><th>商品名</th><th>単価</th><th>数量</th></tr>
10 <xsl:apply-templates select="売上表/商品" >
11 <xsl:with-param name="key" select="10"/>
12 </xsl:apply-templates>
13 </table>
14 </body>
15 </html>
16 </xsl:template>
17 <xsl:template match="商品">
18 <xsl:param name="key" select="20"/>
19 <xsl:if test="数量>$key">
20 <tr>
21 <td><xsl:value-of select="品名" /></td>
22 <td><xsl:value-of select="単価" /></td>
23 <td><xsl:value-of select="数量" /></td>
24 </tr>
25 </xsl:if>
26 </xsl:template>
27 </xsl:stylesheet>
変数の利用
「$変数名」で変数を指定できます(LIST17の19行目)。xsl:value-of命令で値を出力したり、述部で条件の値として指定したりできます。また、xsl:copy-of命令にツリー構造と関連付けられた変数を指定し、変換結果として出力することもできます。
xsl:with-param要素による値渡し
xsl:apply-templates命令の子要素にxsl:with-param要素を記述することにより、適用されるテンプレートルール内のxsl:paramで指定された変数に対して値を渡すことができます(LIST17の11行目)。xsl:with-param要素はxsl:param要素と同様の記述ができます(図9)。
もし、適用されるテンプレートに該当するパラメータがない場合は無視されます。
プログラムによる外部からの値渡し
xsl:param要素の変数に関連付けされる値に対して、XSLTスタイルシートを処理するプログラムから指定することもできます。これにより、条件の値を変数で仮置きし、実行時に値を指定することで変換内容を変更できます。
例えば、商品リストから商品コードによって1つの商品に関する情報を抽出するXSLTスタイルシートを作成し、外部から抽出対象の商品コードを指定するようにすれば、任意の商品データを抽出できるようになります。プログラム外部から指定する方法に関しては、それぞれの開発環境のAPIドキュメントを参考にしてください。
XSLTスタイルシートを記述する際の注意点
最後に、実際に自分でXSLTスタイルシートを記述するときの注意点について、ポイントを紹介します。
整形式にする
XSLTスタイルシートはXML文書です。そのため、最低限の決まりとして整形式である必要があります。
その中でも特に忘れやすいのが、空要素の「/」です。xsl:value-of命令やxsl:apply-templates命令は通常、空要素となります。また、HTMLのbrタグやimgタグはXSLTスタイルシート内では空要素として記述する必要がありますので注意しましょう。
XPathを正しく指定する
カレントノードを誤って考えてしまうと、正しくXPathを指定できません。そのため、常に「現在のカレントノードはどこか」を確認しながら指定するようにしましょう。誤った指定をすると次のような現象が発生します。
●何も表示されない
xsl:value-of命令のselect属性で誤ったXPathを指定すると何も出力されません。また、xsl:apply-templates命令のselect属性で誤ったXPathを指定した場合も何も表示されません。これは、ノードが選択されず、テンプレートルールが適用されないためです。したがって、適用する予定のテンプレートルールが処理されないので、その部分がまったく表示されないわけです。
●ソースXML文書のテキスト内容が連なって表示される
xsl:templates命令のmatch属性で誤ったXPathを指定すると、選択されたノードに適用できるテンプレートルールが存在しないことになります。そのため、選択されたノードセットに組み込みテンプレートルールが適用され、テキスト内容が連なって表示されます。
今月の確認問題
さて、ここまでXSLTの機能として、選択処理や反復処理といった制御命令の記述方法やXMLの要素や属性を生成したり、コピーしたりする方法について紹介してきました。ここで、今回解説した内容がしっかりと理解できているかどうか、確認問題で復習してみましょう。
問題1
XSLTの機能について、誤った記述を選択してください。
- xsl:if命令は、test属性の条件が真となる場合に実行されるテンプレートを記述する
- xsl:for-each命令は、select属性に指定されたすべてのノードに対して繰り返し処理ができる
- xsl:choose命令で条件が真となるものがない場合、xsl:else要素のテンプレートが処理される
- xsl:copy命令では、カレントノードのみがコピーされる
解説
xsl:choose命令は、xsl:when要素のtest属性に記述された式が真となる最初のテンプレートを処理します。条件が真となるものがない場合には、xsl:otherwise要素のテンプレートが処理されます。よって、誤っている記述はCです。
問題2
次のXML文書AにXSLTスタイルシートを適用し、XML文書Bを出力します。XSLTスタイルシートの(1)の部分に当てはまる記述を選択してください。
[XML文書A]
<?xml version="1.0" encoding="Shift_JIS"?>
<商品>
<みかん単価="40"/>
</商品>
[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="/">
<果物>
<xsl:apply-templates select="/商品/みかん"/>
</果物>
</xsl:template>
<xsl:template match="みかん">
<みかん>
</みかん>
</xsl:template>
</xsl:stylesheet>
[XML文書B]
<?xml version="1.0" encoding="Shift_JIS"?>
<果物>
<みかん><単価>40</単価></みかん>
</果物>
-
<xsl:attribute name="単価">
<xsl:value-of select="単価"/>
</xsl:attribute> - <xsl:element name="単価">
<xsl:value-of select="単価"/>
</xsl:element> - <xsl:attribute name="単価">
<xsl:value-of select="@単価"/>
</xsl:attribute> - <xsl:element name="単価">
<xsl:value-of select="@単価"/>
</xsl:element>
解説
出力結果であるXML文書Bでは、みかん要素の子要素として単価要素が記述されています。よって、(1)に当てはまるのは単価要素を生成する記述です。要素を生成するのはxsl:element命令です。xsl:attribute命令は属性を生成する命令です。また、要素内容を出力するにはxsl:valueof命令を使用し、seletct属性に出力する値を示すXPath式を指定します。ソースXML文書では単価は属性として記述されているので「@」を付けて指定します。よって、正解はDです。
問題3
次のXML文書AにXSLTスタイルシートを適用し、XML文書Bを出力します。XSLTスタイルシートの(1)の部分に当てはまる記述を選択してください。
[XML 文書A]
<?xml version="1.0" encoding="Shift_JIS"?>
<item>
<itemName>XMLボールペン</itemName>
<itemNo>PN001</itemNo>
<size unit="cm">15</size>
</item>
[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="/">
<xsl:apply-templates select="item"/>
</xsl:template>
<xsl:template match="item">
</xsl:template>
</xsl:stylesheet>
[XML文書B]
<?xml version="1.0" encoding="Shift_JIS"?>
<size unit="cm">15</size>
- <xsl:copy-of select="size"/>
- <xsl:copy select="size"/>
- <xsl:copy-of match="size"/>
- <xsl:element name="size"/>
解説
xsl:copy-of命令は、select 属性に指定したXPath式に当てはまる子孫ノードをすべてコピーします(属性や要素内容も含む)。xsl:copy命令はカレントノードのみをコピーするための命令で、select属性は指定できません。xsl:element命令は要素しか作成されません。よって正しい記述はAです。
* * *
今回は、XSLTの豊富な機能の中から、選択処理や反復処理の記述方法やXMLの要素や属性を生成したり、コピーしたりする方法について紹介しました。制御命令を組み合わせることで、より高度で柔軟な変換処理を記述できるようになるだけでなく、ソースXML文書から別のXML文書へと構造を変換したり、一部分を抽出したXML文書を生成したりもできるようになります。制御命令やXML要素を生成する命令には似たような名前が多くややこしいかも知れませんが、違いをしっかり覚えて大事なときに混乱しないようにしておきましょう。
次回からは、XMLのボキャブラリを区別するための仕組みである「XML名前空間」について紹介します。
鈴木智也(すずきともや)
株式会社東芝OAコンサルタント教育ソリューション技術部に勤務。主にXML やプログラミング言語の講師を担当。 テニスサークルの夏合宿(別名:肝臓強化合宿)に行ってきました。貸切バスなので、朝の8 時からアルコールを摂取。 で、現地に着いたら、即テニスで汗を流し(アルコールを抜き)、温泉に入って夕食後は宴会。飲む、打つ、浸かると3 つそろった合宿で、 帰りは皆さん爆睡(酔)状態でした……。
<掲載> P.196-202 DB Magazine 2006 November