revised: Nov./16th/2003
ソース・ツリーであるリスト1と、結果ツリーであるリスト5を見比べながら、XSLT文書であるリスト2の中身を見ていきましょう。
XSLT文書はXMLベースのマークアップ言語として定義されているので、XML宣言で始まる整形式のXML文書である必要があります。
XSLT文書のルート要素はstylesheet
要素であり、その属性には表1に挙げるものを指定する。
属性 | 値 |
---|---|
version | 現時点では1.0のみ(必須) |
exclude-result-prefixes | 結果ツリーに含めない名前空間 |
xmlns:接頭辞 | 名前空間URI |
xmlns | デフォルト名前空間URI |
表1の属性で、必ず指定するのが、version
属性と、XSLT自身の名前空間URIを指定するxmlns
属性です。リスト2で挙げたXSLT文書では、version="1.0"
と、XSLT自身の名前空間である "http://www.w3.org/1999/XSL/Transform
" を接頭辞 xsl
で定義してあります。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
例えば、ソース・ツリーで名前空間 "http://www.hoge.foo.demo/ScehmaDemo
" を使っている場合は、XSLT文書でもこの名前空間URIを指定しておく必要があります。この名前空間をデフォルト名前空間にして、結果ツリーにはこの名前空間を含めたくないという場合は、次のように指定します。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.hoge.foo.demo/ScehmaDemo" exclude-result-prefixes="#default">
接頭辞にpreを指定する場合は、名前空間URIの指定に xmlns:pre
を使い、exclude-result-prefixes
属性の値にpre
を指定します。
stylesheet
要素の直接の子要素に、リスト2では、出力方法を指定するoutput
要素と、変換規則を記述するtemplate
要素を記述しました。他にも、リスト6に挙げる要素が記述可能です。これらの要素は、XSLT仕様書ではトップ・レベル要素と呼ばれています。本稿では、全てのトップ・レベル要素を紹介することはできません。詳細は、W3CのXSLT 1.0仕様書を参照してください。
リスト6. XSLT文書のトップレベル要素
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 外部XSLT文書のインポート 本スタイルシートの規則よりも優先する --> <xsl:import href="..."/> <!-- 外部XSLT文書のインクルード 本スタイルシートの規則の方が優先する --> <xsl:include href="..."/> <!-- スペース区切りの要素名を指定して、 当該要素のテキスト・ノードから空白を除去する --> <xsl:strip-space elements="..."/> <!-- デフォルトでは全ての要素名が指定されており、 当該要素の空白をそのまま維持する --> <xsl:preserve-space elements="..."/> <!-- method属性に"xml" | "html" | "text"を指定して、 対応する出力形式を指定する --> <xsl:output method="..."/> <!-- 関数key()で利用する、ノードを参照するキーとその値を定義する --> <xsl:key name="..." match="..." use="..."/> <!-- 関数format-number()で利用する、数値を文字列かするパターンを定義する --> <xsl:decimal-format name="..."/> <!-- 名前空間URIが別の名前空間URIに関する別名であることを宣言する --> <xsl:namespace-alias stylesheet-prefix="..." result-prefix="..."/> <!-- 名前つき属性集合を定義する --> <xsl:attribute-set name="..."> ... </xsl:attribute-set> <!-- 変数名とその値を定義する --> <xsl:variable name="...">...</xsl:variable> <!-- 変数名とそのデフォルト値を定義する --> <xsl:param name="...">...</xsl:param> <!-- パターンにマッチするノードの変換規則を記述する --> <xsl:template match="..."> ... </xsl:template> <!-- 名前つき変換規則を定義する --> <xsl:template name="..."> ... </xsl:template> </xsl:stylesheet>
XSLT文書で最も重要なものは、変換規則を記述するtemplate
要素です。ここで、xsl:template
要素について、詳しく紹介しましょう。
xsl:template
要素は、内容に結果ツリーを記述します。match
属性とname
属性の何れかが必須の属性であり、name
属性が指定されている場合は、属性値を使って、xsl:call-template
要素から明示的に参照可能となります。一方、match
属性が指定されている場合は、属性値のXPathにマッチしたノードを、結果ツリーに変換する規則として機能します。
リスト2のXSLT文書では、三つのテンプレートが定義されています。最初のものは、match
属性値にルート・ノードが指定されており、文書全体を内容のツリー構造に変換するテンプレートです。リスト2では、結果ツリーのルート要素がnamelist
要素であり、その子要素にmale
要素とfemale
要素を記述しました。何れの要素の場合も、内容にはxsl:apply-templates
要素が現れています。
xsl:apply-templates
は、select
属性を持ち、値に対応するノード集合に対応するテンプレートが当該箇所に挿入される。
male
要素の子要素であるxsl:apply-templates
要素の場合は、select="/address/item[@sex='male']"
が指定されており、マッチする全てのノードに対して、再帰的にテンプレート2が適用され、その結果が挿入されることになります。同様に、female
要素の子要素には、テンプレート3の結果が挿入されます。
テンプレート2は、ソースツリーのsex
属性の値がmale
であるitem
要素にマッチするテンプレートです。内容はcust
要素で、その内容にはxsl:value-of
要素が指定されています。xsl:value-of
要素はselect
属性を持ち、マッチするパターンに対応するテキストを結果ツリーのテキスト・ノードに挿入します。すなわち、select
属性に要素ノードの集合が指定されれば、その子孫のテキストノードであり、属性ノードが指定されれば、その値が結果ツリーのテキスト・ノードに挿入されることになります。
xsl:template
要素の子要素として、xsl:value-of
要素を紹介したが、他にも多くの要素が定義されています。それら全てを説明する余裕はありませんが、一部の要素については本稿でも紹介します。最初に紹介するのは、繰り返し構造を記述するxsl:for-each
要素です。
xsl:for-each
要素は、select
属性の値にマッチするノードが存在する限り、内容を繰り返します。リスト7は、リスト1を、XHTML 1.1文書のテーブルに変換するものです。
リスト7. xsl:value-of
の例(XSLTDemo2.xsl
)
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"> <!-- 結果ツリーの出力方法 --> <xsl:output method="xml" encoding="UTF-8" indent="yes" doctype-public="-//W3C//DTD XHTML 1.1//EN" doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" /> <!-- テンプレート --> <xsl:template match="/"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" > <head> <meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" /> <title>顧客リスト</title> </head> <body> <table border="1"> <!-- 繰り返し --> <xsl:for-each select="address/item"> <tr> <th><xsl:apply-templates select="name"/></th> <!-- 繰り返し --> <xsl:for-each select="access"> <td><xsl:apply-templates/></td> </xsl:for-each> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet>
リスト7では、xsl:output
要素に、XHTML 1.1の文書型の、公開識別子とシステム識別子を指定しいます。この情報に基づいて、DTD宣言が結果ツリーに挿入されます。
尚、XHTMLもXML文書であるので、HTML 4向けのoutput method="html"
は指定していません。また、文字符号化方法にはUTF-8を明示的に指定し、結果ツリーの出力でインデントをとるように指定しました。このスタイルシートを指定してリスト3を実行すると、結果ツリーはリスト8のようになります。実際は改行されるのみでインデントはとられませんが、見やすくするために適宜スペースを挿入してあります。
リスト8. リスト7による結果ツリー
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja"> <head> <meta content="text/html; charset=UTF-8" http-equiv="content-type" /> <title>顧客リスト</title> </head> <body> <table border="1"> <tr> <th>菅井 学</th> <td></td> <td>http://www.nextindex.net/java/</td> </tr><tr> <th>鈴木 竜広</th> <td>tsuzuki@hoge.foo.bar</td> </tr><tr> <th>栃原 宏枝</th> <td>090-xxxx-xxxx</td> </tr> </table> </body> </html>
xsl:if
要素とxsl:choose
要素XSTLには、条件によって処理を変更する要素も用意されています。IF-THEN型の場合はxsl:if
要素を用い、スイッチ型の条件分岐はxsl:choose
要素を用いることになります。
xsl:if
要素は、test
属性に指定された式を評価して、真であれば内容のテンプレートを実行し、偽であればなにもしません。リスト9は、リスト7に性別のカラムを追加したものです。sex
属性の値が"male
"であれば「男性」、"female
"でれば「女性」と出力します。
xsl:choose
要素は、子要素にxsl:when
要素を持ち、そのtest
属性の値を評価して、実行するテンプレートを選択します。全てのxsl:when
要素のtest
属性値が真でなければ、xsl:otherwise
要素の内容が実行されます。xsl:when
要素が真でなく、xsl:otherwise
要素が存在しない場合は、なにもしません。リスト9では、xsl:variable
要素を用いて変数$kind
を定義して、その値に応じて対応する文字列を付加しています。
XSLTで定義されている要素には、他にもいろいろありますが、最後にソート要素を紹介します。xsl:sort
要素は、xsl:apply-templates
要素又はxsl:for-each
要素の子供として定義され、複数記述することで、一時ソートキー、二次ソートキーとして働きます。属性には、表8に挙げるもものが定義されています。
属性 | 概要 |
---|---|
select | ソートキー |
lang | 言語 |
data-type |
|
order |
|
case-order |
|
リスト9では、name
要素の文字コードの降順にソートしています。
リスト9. 条件分岐とソートの例(XSLTDemo3.xsl
)
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"> <!-- 結果ツリーの出力方法 --> <xsl:output method="xml" encoding="UTF-8" indent="yes" doctype-public="-//W3C//DTD XHTML 1.1//EN" doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" /> <!-- テンプレート --> <xsl:template match="/"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" > <head> <meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" /> <title>顧客リスト</title> </head> <body> <table border="1"> <!-- 繰り返し --> <xsl:for-each select="address/item"> <!-- ソート指定 --> <xsl:sort select="./name" order="descending"/> <tr> <th><xsl:apply-templates select="name"/></th> <!-- 条件分岐 --> <xsl:if test="@sex='male'"> <td>男性</td> </xsl:if> <xsl:if test="@sex='female'"> <td>女性</td> </xsl:if> <!-- 繰り返し --> <xsl:for-each select="access"> <td> <!-- 変数定義 --> <xsl:variable name="kind" select="@kind"/> <!-- 条件分岐 --> <xsl:choose> <xsl:when test="$kind='email'">email: </xsl:when> <xsl:when test="$kind='tel'">tel: </xsl:when> <xsl:otherwise>others: </xsl:otherwise> </xsl:choose> <xsl:apply-templates/> </td> </xsl:for-each> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet>
リスト9 の XSLT 文書で、リスト1 の XML 文書を処理すると、リスト10のようになります。使ったアプリケーションはリスト3のものです。
リスト10. XSLTDemo3.xsl
の処理結果
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja"> <head> <meta content="text/html; charset=UTF-8" http-equiv="content-type" /> <title>顧客リスト</title> </head> <body> <table border="1"> <tr> <th>鈴木 竜広</th> <td>男性</td> <td>email: tsuzuki@hoge.foo.bar</td> </tr> <tr> <th>栃原 宏枝</th> <td>女性</td> <td>tel: 090-xxxx-xxxx</td> </tr> <tr> <th>菅井 学</th> <td>男性</td> <td>email: </td> <td>others: http://www.nextindex.net/java/</td> </tr> </table> </body> </html>
XSLT 1.0では、以上で挙げた要素や属性のほかにも、多くのものが定義されています。より詳細な定義は、W3CのXSLT 1.0仕様書を参照ください。