前回の「XMLデータの埋め込みと相互参照」では、複数のXMLデータを操作する方法と、相互参照機能を使って必要なデータのみを抽出する方法を考えました。本連載の最後となる今回は、結果ツリーをファイルに出力する方法、およびXSLTの規格にない命令や関数を拡張して使用する方法を説明します。XSLTでは命令や関数の拡張を許可しています。今回は、いくつかのXSLTプロセッサとその拡張機能も紹介します。
本連載では、これまで読者がXSLTの変換結果をすぐに確かめられるよう、Internet Explorer 5(以下IE 5)を使って、HTMLの結果ツリーをWebブラウザに直接表示させてきました。しかしXSLTは、XMLデータを、XML形式やHTML形式、テキスト形式などのファイルへのバッチ的な変換の際にも使用されます。そうした用途のためのXSLT命令が、結果ツリーのファイル出力を制御するxsl:output要素です。
XSLTでは、結果ツリーを書き出すファイルの出力形式の指定などを、xsl:output要素によって行います。xsl:output要素は、トップレベル要素であるxsl:stylesheet要素の子要素です。xsl:output要素の書き方を以下に示します。
<xsl:output method = "xml" | "html" | "text" | "他の出力形式" version = "バージョン番号" encoding = "符号化方式" omit-xml-declaration = "yes" | "no" standalone = "yes" | "no" doctype-system = "公開識別子" cdata-section-elements = "要素名のリスト" indnent = "yes" | "no" media-type = "MIMEタイプ" />
属性 | 機能 | |
---|---|---|
method | 出力されるデータ形式を指定(HTML、XML、テキスト、ほかの出力形式) | |
version | XML形式またはHTML形式の出力データのバージョンを指定 | |
encoding | 符号化方式を指定 | |
omit-xml-declaration | XML宣言を出力するかどうかを指定。属性値が“yes”の場合、XML宣言は出力されない | |
standalone | スタンドアロン宣言を出力 | |
doctype-system | DOCTYPE宣言を出力 | |
cdata-section-elements | 内容のテキストデータをCDATAセクションとして出力したい要素の名前のリストを指定 | |
indent | 字下げのための空白を出力するかどうかを指定 | |
media-type | 出力データのMIMEタイプを指定 | |
表1 xsl:output要素の属性 |
これからxsl:output要素の使い方を、サンプルプログラムを使って説明します。ただし、このサンプルプログラムはバッチ式にXSLT変換をさせるものですので、まずコマンドラインから打ち込めるXSLT変換ユーティリティ“msxsl.exe”をインストールしておきます。msxsl.exeは、マイクロソフトのMSDN Libraryから無償でダウンロードできます。
ではサンプルを見ながらxsl:output要素の使い方を学びましょう。リスト2のXMLデータを見てください。
<?xml version="1.0" encoding="shift_jis"?> <customer> <name>秋本太郎</name> </customer>
このXMLデータの“customer”要素と“name”要素を、それぞれ“顧客”要素と“氏名”要素に変換し、別のXMLファイルにしてみましょう。この場合の変換ルールを記述したXSLTスタイルシートをリスト3に示します。
<?xml version="1.0" encoding="shift_jis"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="shift_jis"/> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="customer"> <顧客> <xsl:apply-templates/> </顧客> </xsl:template> <xsl:template match="name"> <氏名> <xsl:value-of select="."/> </氏名> </xsl:template> </xsl:stylesheet>
リスト3のxsl:output要素の部分をもう一度ご覧ください。XML形式のデータを出力しますので、method属性値に“xml”を指定しています。またencoding属性によって、出力ファイルの文字コードとして“shift_jis”を指定しています。
<xsl:output method="xml" encoding="shift_jis"/>
では、MS-DOSのコマンドウィンドウでMSXSLを実行させてみましょう。XMLデータやスタイルシートを同じディレクトリに置いてから画面1のように入力してください。
MSXSLの第1パラメータとして、入力XMLファイル名(customer.xml)を、第2パラメータとして、適用するスタイルシートファイル名(output.xsl)を指定します。オプション機能のファイル出力を指示するキーワード“-o”に続いて、出力ファイル名(customerj.xml)を指定します。出力されたファイルをIE 5で開くと画面2のとおりになります。
XSLTには、XSLTの規格以外の命令や関数をベンダやユーザーが独自に追加して機能を拡張する仕組みが備わっています。
XSLTの規格では変換処理を制御する命令が要素として定義されています。それらに加えてベンダやユーザーは、必要とする命令を新しい要素として定義することができます。こうした要素を拡張要素(extension element)といいます。
代表的なXSLTプロセッサが実装している拡張要素を以下に示します。
プロセッサ | 開発 | 拡張要素 | |
---|---|---|---|
SAXON | Michael H. Kay | saxon:assign(変数へ値の割り当て) saxon:doctype(DTDの生成) saxon:entity-ref(エンティティの生成) saxon:functionとsaxon:scriptとsaxon:return(拡張関数の定義) saxon:groupとsaxon:item(グループ化) saxon:handler(テンプレート) saxon:output(複数ファイルの処理) saxon:preview(大きなXMLデータの分割) saxon:while(繰返し) |
|
Xalan | Apache XML Project | redirect:openとredirect:write、 redirect:close(複数ファイルの処理) |
|
XT | James Clark | xt:document(複数のファイル処理) | |
表1 XSLTプロセッサとその拡張要素 |
上記の拡張要素の表記方法から分かるとおり、拡張要素は、拡張要素が属する名前空間とその名前空間と関連付けられた接頭辞を使って定義します。拡張要素の定義は次の二通りの方法で行えます。
例えば、SAXONプロセッサの拡張要素saxon:entity-refを使って、エンティティ“ ”を生成するとします。この拡張要素は、xsl:stylesheet要素においてリスト4のように定義できます。
<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://icl.com/saxon" extension-element-prefixes="saxon"> …… <saxon:entity-ref name="nbsp"/> …… </xsl:stylesheet>
リスト4において“saxon”は、extension-element-prefixes属性によって拡張要素のための名前空間接頭辞として宣言されています。従って、XSLTプロセッサは、saxonという接頭辞で修飾された要素であるsaxon:entity-ref要素を、拡張要素と見なして処理します(注1)。
(注1)もちろん、saxon:entity-ref要素自体にextension-element-prefixes属性を付加して拡張要素として定義することもできます。
XSLTのスタイルシートで使用される関数の名前で名前空間接頭辞がないものは、XSLTまたはXPathのビルトイン関数です。一方、名前空間接頭辞が付加された名前の関数は、ベンダやユーザーが新たに追加した拡張関数と見なされます。従って次のように記述した場合、名前空間接頭辞(この場合はdx)が関数MyDateに付加されていますので、XSLTプロセッサは、MyDate()を拡張関数と見なします。
dx:MyDate()
なお、XSLT1.0は、要素や関数の拡張機能の実装を定義するメカニズムを定めていません。従って拡張機能を定義する場合、用いるXSLTプロセッサの仕様を調べる必要があります。例えばMSXML3プロセッサでは、msxsl:script要素によって拡張機能を定義します。
MSXML3プロセッサを例にして拡張関数の定義の仕方を示しましょう。リスト2と同様なXMLデータを読み込み、それに日付を付加した後、Webブラウザ表示させるスタイルシートを書いてみます(リスト5)。
<?xml version="1.0" encoding="shift_jis"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dx="http://www.utj.co.jp/dx"> <msxsl:script xmlns:msxsl="urn:schemas-microsoft-com:xslt" language="JavaScript" implements-prefix="dx"> function MyDate() { dt = new Date(); m = dt.getMonth()+1; d = dt.getDate(); return m+"月"+d+"日"} </msxsl:script> <xsl:output method="xml" encoding="shift_jis" indent="yes"/> <xsl:template match="/"> <html> <body> <p> <xsl:value-of select="dx:MyDate()"/> のお客様は、 <xsl:value-of select="."/>様です。 </p> </body> </html> </xsl:template></xsl:stylesheet>
まず、xsl:stylesheet要素で、ユーザーが定義する拡張関数のための名前空間を宣言します。例では、宣言された名前空間の接頭辞を“dx”としています。
xmlns:dx="http://www.utj.co.jp/dx"
次にMSXMLによる拡張要素であるmsxsl:script要素で、拡張関数MyDate()を定義します。msxsl:script要素の詳しい説明は省略しますが、リスト5から分かるとおり、例ではJavaScriptで拡張関数が記述されていること、拡張関数が属する名前空間の接頭辞が“dx”であることが宣言されています(注2)。
(注2)msxsl:script要素はマイクロソフトが独自に拡張した要素です。従って、msxsl:script要素は、前項で述べたようにextension-element-prefixes属性を使って拡張名前空間として宣言する必要があると思われるかもしれませんが、そうなってはいません。これは、XSLT規格によると「XSLTの名前空間ではない、何らかの名前空間に属する要素は無視する」と定められており、トップレベル要素(xsl:stylesheet要素直下の子要素)はこの仕様に該当するからです。詳しくはW3CによるXSLTの仕様書、またはXSLTの解説書を見てください。
<msxsl:script xmlns:msxsl="urn:schemas-microsoft-com:xslt" language="JavaScript" implements-prefix="dx"> function MyDate() { dt = new Date(); m = dt.getMonth()+1; d = dt.getDate(); return m+"月"+d+"日"} </msxsl:script>
msxsl:script要素の内容を見ると分かるとおり、拡張関数MyDate()は、まずシステム日付を取得し、それを「○月△日」の書式に直してから関数値として返却します。JavaScript言語の記述の仕方は、スクリプト言語の解説書を見てください。
リスト5のスタイルシートをリスト2のXMLデータに関連付けて構造変換し、それをWebブラウザ表示させると、画面3のとおりになります。本稿を執筆している日付が表示結果に含められました。
全7回の連載で、XSLTの概要からプログラミング、拡張機能まで解説しました。今回の連載で取り上げたのはそのほんの一部でしたが、ノード生成や文字列の操作など、このほかにも便利な関数や命令がまだまだたくさんあります。強力な機能満載のXSLTは、今後さらに利用されてゆくことでしょう。
本記事は、日本ユニテック発行のXMLテクノロジー総合情報誌「Digital Xpress」に掲載された、XSLT特集「XSLTの実力を探る!」の内容をもとに、加筆修正したものです。
Copyright © ITmedia, Inc. All Rights Reserved.