XMLマスターへの道
〜「XMLマスター:ベーシック」試験対策〜
第10回 XSLTの基本構造を理解する
内藤一彦NRIラーニングネットワーク株式会社
2003/10/10
XML文書の変換を行うためのXSLTについて、本稿より2回にわたって解説します。今回は、基本的なXSLTの使用方法を紹介します。前回「第9回 DTDの実体宣言と記法宣言」で予習問題として下記の問題を出題しておきました。この問題を解くための解説をした後、解答を示します。
今回の問題 | |||
(Q1) 次のXSLT要素のうちトップレベル要素となれるものをすべて選択してください。
|
|||
(Q2) 次のXSLTスタイルシートが処理されるとき、最初に実行されるテンプレートはどれでしょう。
|
今回は、この問題に解答するうえで必要となる下記の内容について解説します。
- XSLTの概要
- XSLTの基本構造
- 基本構造、トップレベル要素
- テンプレート
- テンプレートの処理順序
- テンプレートの競合
■XSLTの概要
XSLT(XSL Transformations)は、1999年にW3Cで勧告された標準仕様でXML文書の構造変換を行うための機能です。
XSLTの使用環境は次のようになります。
図1 XSLTの使用環境 |
図1のXSLTプロセッサは、XSLT仕様に基づいた変換を行うためのプログラムです。GUIベースのソフトウェアからXMLパーサに組み込まれているプログラムベースで使用するソフトウェアまで、有償/無償のさまざまな製品があります。どんな種類があるか興味のある方は、OASISのソフトウェア紹介のWebページをご覧になるとよいでしょう。
このXSLTプロセッサに、変換元となるXML文書と変換内容を定義しているXSLTスタイルシート文書を読み込ませて、変換処理を行わせます。何を隠そう、XSLTスタイルシート文書もXML形式をとります。
つまり、XSLTで定められている要素や属性を使用して、XML形式のドキュメントとして変換内容を定義することになります。
まずはサンプル文書を使って、実際に変換を行ってみましょう。
<?xml version="1.0" encoding="Shift_JIS" ?> |
リスト1 変換元のXML文書(employee.xml) |
<?xml version="1.0" encoding="Shift_JIS" ?> |
リスト2 XSLTスタイルシート文書(employee.xsl) |
なお、簡単に変換結果を確認したいのであれば、「第5回 valid XMLとDTDの関係」で紹介されているMicrosoft社のInternet Explorer Tools for Validating XML and Viewing XSLT OutputのViewing XSL Outputを使うとよいでしょう。
Internet
Explorer Tools for Validating XML and Viewing XSLT Outputのインストール手順 ダウンロードするファイルはiexmltls.exeです。これを解凍すると、デフォルトでC:\IEXMLTLSが作成されます。このフォルダ内にある「msxmlval.inf」「msxmlvw.inf」をそれぞれ右クリックして「インストール」を選びます。IEを再起動させると、右クリックから「Validate XML」「 View XSL Output」の2つのメニューが有効になります。 |
このツールを使用する場合、変換元のXML文書で次のような命令を挿入してください。
<?xml version="1.0" encoding="Shift_JIS" ?> |
リスト3 Viewing XSLT Output用の追加命令(employee2.xml) |
このXMLをIE(Internet Explorer)で開いた後に、ウィンドウ内で右クリックしメニューから「View XSL Output」を実行します。
図2 View XSL Outputでの表示内容 |
では、いよいよXSLTスタイルシートを見ていきましょう。まず、着目すべきは、「XSLTスタイルシートはXML形式である」ということです。次の構造になっていることを押さえておきましょう。
図3 employee.xslの構造 |
XML文書では必ず1つのルート要素がありますが、XSLTではstylesheet要素を使用します。次のような記述をします。
<xsl:stylesheet |
stylesheet要素の記述内容 |
stylesheet要素の子としてtemplate要素やoutput要素などトップレベル要素を記述します。トップレベル要素とはstylesheet要素の直接の子要素となれるものを指し、次の種類があります。
attribute-set | decimal-format | import |
include | key | namespace-alias |
output | param | preserve-space |
strip-space | template | variable |
テンプレート
実際の変換内容は、トップレベル要素であるtemplate要素内に記述していくことになります。employee.xslには、2つのテンプレートブロックが存在しています。これらのテンプレートが呼び出され、変換処理が行われていきます。
<xsl:template match="/"> |
テンプレート1 |
<xsl:template match="EMPLOYEE"> |
テンプレート2 |
template要素のmatch属性では、どのノードを処理するためのものかを指定します。つまり、テンプレート1は「/(ルート)」(注)を変換するため、テンプレート2は「EMPLOYEE要素」を処理するためのテンプレートになります。
(注) /(ルート)は、ルート要素(EMPLOYEES要素)ではありません。ルート要素の親に当たり、XML文書の階層構造で考えると最上位になります。すべてのものはこの子孫に含まれるようになるので、/(ルート)を変換するということは、文書全体を変換することになります。 |
では、このスタイルシートでの処理の流れを確認しましょう。
(1)/(ルート)用のテンプレートの呼び出し
実際に変換処理が行われる際には、必ず、/(ルート)用のテンプレートが最初に呼び出され処理されます。従って、テンプレート1が呼び出されることになります。
(2)/(ルート)用のテンプレート内の処理
このテンプレートでは、次のことを行っています。
- 「社員一覧」要素の作成
- EMPLOYEE用テンプレートの呼び出し
テンプレート内を見ると、「社員一覧」という開始タグ・終了タグがあります。このように、直接タグ形式で記述すると、変換により要素が作成されます。もし、HTMLに変換するためのスタイルシートを作成したいのであれば、直接HTMLタグを埋め込めばよいわけです(HTMLに変換するためのスタイルシートのサンプル)。
直接タグを記述するほかに、XSLTのelement要素を使って、要素を作成することもできます。
<xsl:template match="/"> |
xsl:elementを使用した例 |
さて、これで「社員一覧」要素が作成されますが、開始タグ・終了タグの間を見てみましょう。apply-templates要素が記述されています。select属性で処理したいノードを指定し、そのノード用のテンプレートを呼び出します。つまり、EMPLOYEEを処理するためのテンプレートを呼び出すことになります。
「社員一覧」要素の開始タグ・終了タグの間に記述されているので、最終的には呼び出したテンプレートの処理結果が「社員一覧」要素の子として挿入されます。
(3)EMPLOYEE用のテンプレートの呼び出し
前述のapply-templates要素により呼び出されるのが、テンプレート2(match="EMPLOYEE"のxsl:template)です。変換元のemployee.xmlでは、EMPLOYEEが2つありますので、それぞれに対してテンプレートが呼び出されます。
(4)EMPLOYEE用のテンプレート内の処理
このテンプレートでは、次のことを行っています。
- 「社員」要素の作成
- 「社員番号」「氏名」「部署名」要素の作成
- 値の取得
テンプレート1と同様、タグを直接記述し新しい要素を作成しています。
「社員番号」「氏名」「部署名」の開始タグ・終了タグの間では、それぞれ、value-of要素が使われています。この命令を使用するとselect属性で指定されたノードの値を取得することができます。それぞれのvalue-ofの結果が「社員番号」「氏名」「部署名」要素の値として挿入されることになります。
なお、属性名を指定する場合には、
<xsl:value-of select="@empid" />
のように、属性名に“@”を付けて記述します。
ここまで、初歩的なXSLTスタイルシートの構造について解説してきました。いままで取り上げたXSLT要素をまとめておきます。
- xsl:stylesheet(XSLTスタイルシートのルート要素)
XSLTのバージョンを宣言する(version="1.0")。
XSLTの名前空間を宣言する(xmlns:xsl="http://www.w3.org/1999/XSL/Transform")。 - xsl:apply-templates(テンプレートブロックの呼び出しを行う)
テンプレートを呼び出し処理するノードを指定する(select="/EMPLOYEES/EMPLOYEE")。
select属性は省略することもできる。その場合には、カレントノード(現在の作業位置)から見てすべての子ノードに対して呼び出しをかける。 - xsl:template(テンプレートブロックの定義を行う)
どのノードを処理するためのテンプレートか指定する(match="EMPLOYEE")。 - xsl:value-of(値を取得する)
値を取り出したいノードを指定する(select="@empid")。
テンプレートの競合
xsl:apply-templates要素命令を使用してテンプレートを呼び出すとき、次のテンプレートが存在していた場合にはどうなるでしょう。どちらも呼び出されるだけの条件はそろっています。
: |
リスト4 テンプレートが競合している(employeepri.xslの一部) |
このスタイルシートを適用させるXML文書(employeepri.xml)をIEで開いた後、View XSL Outputで表示した結果は次のとおりです。
図4 競合するテンプレートを適用させた結果 |
図4を見ると、match="/EMPLOYEES/EMPLOYEE"のテンプレートが呼び出されていることが分かります。このように呼び出されるテンプレートの候補が複数ある場合、テンプレートの優先度に従って、最も優先度の高いどれか1つのみが呼び出され処理されます。この優先度を決定するのがxsl:templateのpriority属性です。
<xsl:template match="EMPLOYEE" priority="1.0"> |
priority属性を指定する記述 |
priority値は正の値の方が高く、負の値ほど低くなります。priorityを省略している場合には、match属性でのノードの指定パターンにより省略時解釈の値がとられます。省略時解釈の値の範囲は、−0.5〜0.5です。細かい指定をしたときほどpriority値は高く、ワイルドカードを使っているような場合には低いpriority値が設定されます。
この例で使われているテンプレートのpriority値は
テンプレート名 | priority値 |
match="EMPLOYEE" | 0 |
match="/EMPLOYEES/EMPLOYEE" | 0.5 |
となります。
先ほどのテンプレートにpriority属性を加えてみました。
: |
リスト5 priority値1.0を追加(employeepri2.xslの一部) |
テンプレートにpriority属性を加えてemployeepri2.xmlをIEで開いた後、View XSL Outputで表示した結果は次のとおりです。
図5 priority属性の高いテンプレートが適用された |
もし、意図的に優先度を上げたいテンプレートがあるのなら、省略時にとられるpriority値よりも高い値(0.5より高い値)を指定するとよいでしょう。
■今回の問題の解答
それでは、問題の解答を解説します。
(Q1) 次のXSLT要素のうちトップレベル要素となれるものをすべて選択してください。
答えは、(a)、(b)、(c)です。
この問題に関して参考になる解説は、「XSLTの基本構造(基本構造、トップレベル要素)」です。参考までに、選択肢に出ているXSLT要素命令を紹介しておきます。
XSLT要素命令 | 意味 |
xsl:attribute-set | 属性グループを定義する。xsl:elementを使用して要素を作成するときに、これで定義しておいた属性グループ名を指定できる |
xsl:param | XSLTスタイルシートの中で扱うパラメータ(変数)を定義する |
xsl:copy | 変換元XMLからカレントノードをコピーする |
(Q2) 次のXSLTスタイルシートが処理されるとき、最初に実行されるテンプレートはどれでしょう。
答えは、(a)です。
この問題に関して参考になる解説は、「XSLTの基本構造(テンプレートの処理順序)」です。
(b)<xsl:template match="*">で使用されている"*"はすべての要素を指します。従って、このテンプレートはすべての要素を処理するために使用できます。
(c)<xsl:template match="text()">で使用されている"text()"はすべてのテキストノードを指します。テキストノードに当たるのは、要素の値です。XSLTで使用されるノードモデルでは、「要素の値」は要素の子ノードであるテキストノードが持つようになっています。いままで要素の値を取得するために使用していた<xsl:value-of select="Name" />は、<xsl:value-of select="Name/text()" />としても同じ結果が得られます。
問題で使用されているスタイルシートのフローは次のようになります。
<xsl:stylesheet |
リスト6 解析対象外とする外部ファイルとその記法宣言の記述例 |
- /(ルート)用のテンプレートが最初に呼び出され処理されます。
- xsl:for-each 要素は、select属性で指定されているノードを取り出しながらループします。終了タグである</xsl:for-each>までがループ内の処理です。
- id属性の値を取得します。
- Name要素を処理するためにテンプレートを呼び出します。
- ここで呼び出されるのは、match="*"のテンプレートとなります。
- xsl:apply-templates要素でテンプレートを呼び出しますが、select属性が記述されていません。この場合、カレントノード(この場合、Name要素がカレントになっています)の子ノードすべてに対してテンプレート呼び出しを行います。Name要素が値を持っているとすると、この子ノードとして考えられるのは、テキストノードです。従って、テキストノード用のテンプレートを呼び出します。
- ここで呼び出されるのが、match="text()"のテンプレートです。
- カレントノード(.)の値を取り出します。xsl:apply-templates要素命令では、テンプレートを呼び出したときに、カレントノードを移動させますので、この時点では、カレントはテキストノードにあります。従って、カレントであるName要素の値が取得されます。
■次回の予習問題
次回のための予習問題を掲載します。
次回も引き続きXSLTです。XSLTにはプログラム言語にあるような基本制御命令が用意されています。その中でも押さえておきたいいくつかの命令について解説していきます。
予習問題 | ||||||||||
(Q1) 次のような学生一覧のXML文書があるときに、学年・クラス・出席番号の順でソートを行い処理したい。このときの、ソートの記述方法として正しいのはどれでしょう。
|
||||||||||
(Q2) 組み込みテンプレートとして正しいものをすべて選択してください。
|
○今回の試験対策のポイント
- XSLTの概要
- XSLTの基本構造
- 基本構造、トップレベル要素
- テンプレート
- テンプレートの処理順序
- テンプレートの競合
○今回の学習内容で出題範囲となる仕様
○今回の学習内容で実機確認を行うときに役立つフリーツール
- Internet Explorer 6.0 SP1 以上
- Microsoft
XML Parser (MSXML) 3.0 Service Pack 4 (SP4) - 日本語
※ 別途、Xmlinst.exe Replace Mode Toolが必要になる場合あり(詳細はMicrosoft XML Parser Version 3.0 Releaseの新機能をご参照ください)
○今回の学習内容で参考になる@ITの記事
- XSLTスタイルシート書き方講座(1):XSLTスタイルシートの基礎の基礎
- サンプルで覚えるXSLTプログラミング
- XMLテクニック集
- いまさら聞けない、技術者のためのXML再入門 第7回 XML文書の構造を変えるXSLT
- VBScriptでXMLプログラミング(3) XSL/XSLTを利用したデータの変換と整列
○今回の学習内容で参考になるXML用語集 (@IT XML用語事典より)
(11)XSLTで必須の制御命令を覚える |
連載:XMLマスターへの道 |
- QAフレームワーク:仕様ガイドラインが勧告に昇格 (2005/10/21)
データベースの急速なXML対応に後押しされてか、9月に入って「XQuery」や「XPath」に関係したドラフトが一気に11本も更新された - XML勧告を記述するXMLspecとは何か (2005/10/12)
「XML 1.0勧告」はXMLspec DTDで記述され、XSLTによって生成されている。これはXMLが本当に役立っている具体的な証である - 文字符号化方式にまつわるジレンマ (2005/9/13)
文字符号化方式(UTF-8、シフトJISなど)を自動検出するには、ニワトリと卵の関係にあるジレンマを解消する仕組みが必要となる - XMLキー管理仕様(XKMS 2.0)が勧告に昇格 (2005/8/16)
セキュリティ関連のXML仕様に進展あり。また、日本発の新しいXMLソフトウェアアーキテクチャ「xfy technology」の詳細も紹介する
|
|