このページで示している XSLT のサンプルコードについては、 そのままであろうと変更なさろうと、ご自由に利用いただいてかまいません。 ただし、内容の正しさや運用の結果については何も保証しませんので、 ご利用の際には充分なテストを行われることをおすすめいたします。
このページで取り上げる XML 文書の大部分は、UA での表示を前提としたものである。
XML → (XSLT でデータ構造を変換) → XHTML → (CSS で書式を設定) → 表示
このページでは上記の流れ中、XML 文書を XHTML 文書に変換するための XSLT を題材とする。 が、初心者用の入門ページであることは意図しない。 ( ここには自分が悩んで、解決した事しか書かないので、話題が偏ってます。 もっと系統立った解説ページへは、[リンク] からどうぞ。 ) 既に XSLT を使い始めていて、具体的な疑問点を持っている方へのヒントぐらいなら有るかも。
UA で直接 XML 文書をブラウズできる場合、変換結果の XHTML 文書を目にすることは無いと思われる。 ここでは変換結果を示すために XSLT プロセッサとして、msxsl.exe を使用した。
サンプルの表示確認には以下の UA を使用している。
ついで。 メイクには Borland MAKE Version 5.2 ( たしか BC++ 5.5 に付属してたやつ ) を、XML/XSLT 編集にはテキストエディタ ( 秀丸 ) を使用している。
このページで変換結果として表示している例は、生の変換結果に改行/インデントを追加したものである。 生の変換結果はリンク先の HTML ファイル ( ソース ) を参照のこと。
(注) 以下は自分が使ってるものしか書いていない不完全なものである。
( 逆に、このページ程度の XHTML を自動生成するならこれぐらいで充分かと思われる。 )
(注) 完全な構造は、 「Extensible Markup Language (XML) 1.0 (Third Edition) W3C 勧告 (2004-02-04)」 の、 「2 Documents」 を参照のこと。
<?xml version="1.0" encoding="Shift_JIS"?> <?xml-stylesheet type="application/xml" href="[XSL ファイル名]"?> <[要素名] [属性名="属性値"]> <!-- : --> </[要素名]>
IE6 ではスタイルシートの MIME タイプを text/xsl と指定しなければ XHTML への変換が行われなず、 ソース(XML) が表示されてしまう。 ( MS の独自仕様なのか? text/xsl がどこでどう定義されたものなのか、調査不足でよく判らない。 )
「XMLクイックリファレンス 第2版」 によると、text/xsl というのは、Microsoftの想像の産物
だそうである。 この情報は千葉氏より教えていただきました。感謝します。
MS の msxsl では application/xml のままでちゃんと変換できるので、 IE でもそのうち application/xml で変換できるようになるんだろう。 ( 希望的観測 )
と思ってたら、 今後のIEの改善には、その根底にあるOSの強化が必要になる
(→ CNET Japan : マイクロソフト、IEスタンドアローン版廃止へ ) って、本気かしらん。あー。IE はもういいや。
(注) 完全な構造は、 「XSL Transformations (XSLT) Version 1.0 W3C 勧告 (1999-11-16)」 の、 「2.2 Stylesheet Element」 を参照のこと。
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
>
<!-- インポートするファイルの指定 -->
<xsl:import href="[ファイル名]" />
<!-- 出力ファイルの形式の指定 (この例では XHTML 1.1) -->
<xsl:output
method="xml"
encoding="Shift_JIS"
omit-xml-declaration="no"
doctype-public="-//W3C//DTD XHTML 1.1//EN"
doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
indent="yes"
/>
<!-- コマンドラインで指定されるパラメタの定義 (無ければ略) -->
<!-- (参) msxsl のコマンドラインでのパラメタの渡し方 -->
<xsl:param name="[パラメタ名]">[デフォルト値]</xsl:param>
<!-- : 他のパラメタ定義 -->
<!-- グローバル変数の定義 (無ければ略) -->
<xsl:variable name="[変数名]">[値]</xsl:variable>
<!-- : 他の変数定義 -->
<!-- テンプレート -->
<xsl:template match="[要素名]">
<!-- : -->
</xsl:template>
<!-- : 他のテンプレート定義 -->
<!-- 名前付きテンプレート (無ければ略) -->
<xsl:template name="[テンプレート名]">
<xsl:param name="[パラメタ名]">[デフォルト値]</xsl:param>
<!-- : -->
<!-- : -->
</xsl:template>
<!-- : 他の名前付きテンプレート定義 -->
</xsl:stylesheet><?xml version="1.0" encoding="Shift_JIS"?> <?xml-stylesheet type="application/xml" href="simple.xsl"?> <ra:sample xmlns:ra = "http://www5a.biglobe.ne.jp/~rarin/xml/ra" title = "XSLT Sample simple" />
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet
version="1.0"
xmlns:ra = "http://www5a.biglobe.ne.jp/~rarin/xml/ra"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns = "http://www.w3.org/1999/xhtml"
exclude-result-prefixes="ra"
>
<xsl:output
method="xml"
encoding="Shift_JIS"
omit-xml-declaration="no"
doctype-public="-//W3C//DTD XHTML 1.1//EN"
doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
indent="yes"
/>
<xsl:template match="/ra:sample">
<html xml:lang="ja" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=Shift_JIS" />
<title><xsl:value-of select="@title" /></title>
</head>
<body>
<h1><xsl:value-of select="@title" /></h1>
</body>
</html>
</xsl:template>
</xsl:stylesheet><?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
>
<html xml:lang="ja" dir="ltr" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta
http-equiv="Content-Type"
content="application/xhtml+xml; charset=Shift_JIS"
/>
<title>XSLT Sample simple</title>
</head>
<body>
<h1>XSLT Sample simple</h1>
</body>
</html>XSLT では XML 文書を XHTML 文書にしか変換できないというわけでは無い。 先の XML 文書 (→ sample/simple.xml ) から LaTeX ソースファイルを出力する XSLT の例。
( 手元に LaTeX の処理系を持っていないので、 正しい LaTeX ソースファイルになってるのか確認できてません。 )
XML/HTML 文書以外を出力する時は、 xsl:output の method を text にしておくこと。 ( そうしないと、 '<'、 '>'、 '&'、 等がそれぞれ、 '<'、 '>'、 '&'、 等にエスケープされてしまうので。 )
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet
version="1.0"
xmlns:ra = "http://www5a.biglobe.ne.jp/~rarin/xml/ra"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
>
<xsl:import href="const.xsl" />
<xsl:output
method="text"
encoding="Shift_JIS"
omit-xml-declaration="yes"
indent="yes"
/>
<!--
$br は改行コード。 const.xsl 中で、
<xsl:variable name="br" select="'
'" />
と定義してある。
変換結果中に改行を明示的に追加したい場合、
 を出力してやれば良い
-->
<xsl:template match="/ra:sample">
<xsl:value-of select="concat(
'\documentstyle{jarticle}', $br,
'\title{', @title, '}', $br,
'\author{ら <simple_latex.xsl>}', $br,
'\date{\today}', $br,
'\begin{document}', $br,
'\maketitle', $br,
'\end{document}', $br
)" />
</xsl:template>
</xsl:stylesheet>\documentstyle{jarticle}
\title{XSLT Sample simple}
\author{ら <simple_latex.xsl>}
\date{\today}
\begin{document}
\maketitle
\end{document}(注) この項は、Mozilla 1.3 と msxsl ではこうなったというだけで、仕様書上で確認できていない。
( 「XML Path Language (XPath) Version 1.0 W3C 勧告 (1999-11-16)」 の 「3.4 Booleans」 あたりがそれっぽいんだけど、確信が持てない。 )
実装依存の可能性があるため、適用時にはちゃんとテストすること。
( テストにはこの項のサンプルを使用すると良い。 )
属性が省略された場合、空文字列との比較 ――
test = "@attr = ''" test = "@attr != ''"
は共に "偽" となってしまうため、これでは属性が省略されていることを判定できない。
属性が省略された場合、 test = "@attr" のように、 @attr を直接 bool 値として扱うと "偽" と判定できる。 よって、属性が省略されたことを判定したい場合は、
test = "not(@attr)"
とすれば良い。
属性の省略と空文字列の指定を同列に扱いたい場合は、 string() 関数で @attr を文字列に変換した後で空文字列と比較すると良い。 例えば、
test = "string(@attr) = ''"
は、 属性が省略されている場合でも、 属性に空文字列が指定されている場合でも、 どちらでも "真" と判定される。
| XML | : sample/default.xml |
| XSLT | : sample/default.xsl |
| 変換結果 | : sample/default.html |
(注) この項は、msxsl ではこうなったというだけで、仕様書上で確認できていない。
実装依存の可能性があるため、適用時にはちゃんとテストすること。
なんかもっと 「まとも」 な方法があるような気がするけど思いつかないので公開してみるテスト。
XML 文書を変換せずそのまま出力する場合、以下のテンプレートが使用できる。
<xsl:template match="* | @* | text()">
<xsl:copy>
<xsl:apply-templates select="* | @* | text()" />
</xsl:copy>
</xsl:template>ところが上記テンプレートは、例えば <br /> のような空要素を <br></br> のように展開する副作用も持つ。 ( 理由が不明。 msxsl の実装依存かも。 )
XML として見れば両者は全く同等の意味を持つが、 UA の実装 ( 特に XML以前の古い UA ) によっては、上記を <br /><br /> と誤解釈し、期待した表示を得られない場合がある。 ( 実験できた範囲では mozilla 1.3 は正しく解釈したが、IE6、Opera 7.11 は誤解釈した。 )
空要素について、 要素 ( * ) と 内容 ( text() ) を xsl:copy の対象から外すことで展開を避けられる。 ( ツリーがこれ以上伸びない訳で、分かるような気もするけど、ちゃんとした理由が不明。 msxsl の実装依存かも。 ) 上記テンプレートと併せて例えば以下のようなテンプレートを使えば良い。
<xsl:template match="br | hr | img">
<xsl:copy>
<xsl:apply-templates select="@*" />
</xsl:copy>
</xsl:template>上記は br, hr, img について、 属性 ( @* ) のみをコピーするよう指定した例である。
xsl:element と xsl:copy-of を使う以下のテンプレートでも XML 文書を変換せずそのまま出力できる。 だがこのテンプレートも前項の xsl:copy 版と同様に空要素を展開する副作用を持っている。 ( 理由が不明。 msxsl の実装依存かも。 )
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:element>
</xsl:template>空要素について、 xsl:apply-templates を止めれば展開を避けられる。 ( これもツリーがこれ以上伸びない訳で、分かるような気もするけど、ちゃんとした理由が不明。 msxsl の実装依存かも。 ) 上記テンプレートと併せて、例えば以下のようなテンプレートを使えば良い。
<xsl:template match="br | hr | img">
<xsl:element name="{name()}">
<xsl:copy-of select="@*" />
<!-- <xsl:apply-templates /> -->
</xsl:element>
</xsl:template>xsl:variable は、variable といいつつ、 定義時に設定した値を生存期間中に変更できない定数である。 例えば、
<xsl:variable name="n" select="16" />
と書くと、$n の値は生存期間中そのスコープ内ではずっと 16 のままである。
条件に応じて初期値を変えたい場合は select を使わずに、 xsl:if あるいは xsl:choose と組み合わせる。 例えば、
<xsl:variable name="n">
<xsl:choose>
<xsl:when test = "[条件 1]">[条件 1 が成立した時の値]</xsl:when>
<!-- : -->
<xsl:when test = "[条件 n]">[条件 n が成立した時の値]</xsl:when>
<xsl:otherwise>[どの条件にも当てはまらなかった場合の値]</xsl:otherwise>
</xsl:choose>
</xsl:variable>のように書く。
| XML | : sample/variable.xml |
| XSLT | : sample/variable.xsl |
| 変換結果 | : sample/variable.html |
フラットな構造から階層構造への変換例。
<diary> <topic date="2003-12-05T11:25:16+09:00">1</topic> <topic date="2003-12-05T12:26:57+09:00">2</topic> <topic date="2004-01-01T15:27:56+09:00">3</topic> <topic date="2004-01-01T16:28:16+09:00">4</topic> </diary>
のようなベタな構造を、
<diary>
<year n="2003">
<topic date="2003-12-05T11:25:16+09:00">1</topic>
<topic date="2003-12-05T12:26:57+09:00">2</topic>
</year>
<year n="2004">
<topic date="2004-01-01T15:27:56+09:00">3</topic>
<topic date="2004-01-01T16:28:16+09:00">4</topic>
</year>
</diary>のように、年ごとに階層化する。 ( 詳細はサンプル参照のこと。気が向いたら解説書きます。 )
| XML | : sample/pttp.xml |
| XSLT | : sample/pttp.xsl |
| 変換結果 | : sample/pttp_.xml |
XSLT 中で、自分自身の要素や属性を参照したい場合、document("") を使う。
例えば xsl:output 要素の encoding 属性を参照したい場合は、
<xsl:variable name="charset" select="document('')/xsl:stylesheet/xsl:output/@encoding" />のようにすれば良い。
| XML | : sample/css.xml |
| XSLT | : css/css.xsl |
| DTD | : css/css.dtd |
| 変換結果 | : sample/css.css |
名前付きテンプレートを再帰呼び出しすることで処理を繰り返す。 その際、引数をループ制御変数として使う。
<xsl:template match="/">
<xsl:call-template name="loop">
<xsl:with-param name="ct" select="10" />
</xsl:call-template>
</xsl:template><xsl:template name="loop">
<xsl:param name="ct">0</xsl:param> <!-- パラメタ : ループ制御用カウンタ -->
<xsl:if test="0 < $ct"> <!-- カウンタが 0 より大きい時だけ -->
<!--
:
ループ中にやりたい処理
:
-->
<!-- 引数の値を 1減らして再帰呼び出し -->
<xsl:call-template name="loop">
<xsl:with-param name="ct" select="$ct -1" />
</xsl:call-template>
</xsl:if>
</xsl:template>| XML | : sample/loop.xml |
| XSLT | : sample/loop.xsl |
| 変換結果 | : sample/loop.html |
関数のリターン値を名前付きテンプレートで実現するには、 xsl:value-of を生で使うと良い。
以下、C言語からの移植例。
int inc(int x) {
return x+1 ;
}
int ans = inc(0) ;
<xsl:template name="inc"> <xsl:param name="x" /> <xsl:value-of select="$x+1" /> </xsl:template>
<xsl:variable name="ans">
<xsl:call-template name="inc">
<xsl:with-param name="x" select="0" />
</xsl:call-template>
</xsl:variable>| XSLT (曜日計算テンプレート) | : ../ra/calendar.xsl |
| XSLT (呼び出し側) | : ../ra/diary.xsl |
XSLT の制限から、移植にあたって元のソースでは不要だった一時変数が必要になる場合がある。
例えば以下の C コードのように、関数呼び出しだけで代入文が終わらない場合、
int x = foo() +1 ;
xsl:call-template は xsl:variable の select 中で使えないので、 xsl:call-template の戻り値を保存するための一時変数が必要になる。
<xsl:variable name="ret"> <xsl:call-template name="foo" /> </xsl:variable> <xsl:variable name="x" select="$ret +1" />
ところが上の書き方では、規模が大きくなった場合、一時変数の命名と管理に悩まされることになる。 ( XSLT では変数への再代入ができないせいもあり、一時変数の数が増えるため。 )
int x = foo() +1 ; int y = bar() +1 ;
<xsl:variable name="ret"> <xsl:call-template name="foo" /> </xsl:variable> <xsl:variable name="x" select="$ret +1" /> <!-- これ以降、 ret の値は誰も使わないのだが…… --> <xsl:variable name="ret_2"> <!-- 変数 ret に再代入できないので、新たな一時変数が必要になってしまう --> <xsl:call-template name="bar" /> </xsl:variable> <xsl:variable name="y" select="$ret_2 +1" />
一時変数が必要な範囲でローカルに宣言すれば、名前の重複を気にする必要が無くなり、変数名の管理が楽になる。
<xsl:variable name="x">
<!-- 変数 ret をローカルに宣言する。 -->
<xsl:variable name="ret">
<xsl:call-template name="foo" />
</xsl:variable>
<xsl:value-of select="$ret +1" />
<!-- 変数 ret のスコープはここまで。 -->
</xsl:variable>
<xsl:variable name="y">
<!-- 前に宣言した 変数 ret のスコープ外なので、名前が同じでも二重宣言エラーにならない。 -->
<xsl:variable name="ret">
<xsl:call-template name="bar" />
</xsl:variable>
<xsl:value-of select="$ret +1" />
<!-- 変数 ret のスコープはここまで。 -->
</xsl:variable>| XML | : sample/scope.xml |
| XSLT | : sample/scope.xsl |
| 変換結果 | : sample/scope.html |
変換結果には不要な名前空間の宣言が出力されてしまう例。
<?xml version="1.0" encoding="Shift_JIS"?> <?xml-stylesheet type="application/xml" href="namespace_01.xsl"?> <ra:sample xmlns:ra="http://www5a.biglobe.ne.jp/~rarin/xml/ra" xmlns="http://www.w3.org/1999/xhtml" title="XSLT Sample namespace 01" />
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet
version="1.0"
xmlns:ra="http://www5a.biglobe.ne.jp/~rarin/xml/ra"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
>
<xsl:output
method="xml"
encoding="Shift_JIS"
omit-xml-declaration="no"
doctype-public="-//W3C//DTD XHTML 1.1//EN"
doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
indent="yes"
/>
<xsl:template match="/ra:sample">
<html xml:lang="ja" dir="ltr">
<head>
<meta
http-equiv="Content-Type"
content="application/xhtml+xml; charset=Shift_JIS"
/>
<title><xsl:value-of select="@title" /></title>
</head>
<body>
<h1><xsl:value-of select="@title" /></h1>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
XML および XSLT 中では名前空間 ra を使用しているので、その名前空間宣言 xmlns:ra="http://www5a.biglobe.ne.jp/~rarin/xml/ra" が必要。
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
>
<html
xml:lang="ja" dir="ltr"
xmlns:ra="http://www5a.biglobe.ne.jp/~rarin/xml/ra"
xmlns="http://www.w3.org/1999/xhtml"
>
<head>
<meta
http-equiv="Content-Type"
content="application/xhtml+xml; charset=Shift_JIS"
/>
<title>XSLT Sample namespace 01</title>
</head>
<body>
<h1>XSLT Sample namespace 01</h1>
</body>
</html>
変換結果の XHTML では名前空間 ra を使っていないので、その名前空間宣言は不要。 にもかかわらず名前空間宣言が出力されてしまっている。
exclude-result-prefixes で不要な名前空間宣言を消せる例。
(略)
<?xml version="1.0" encoding="Shift_JIS" ?> <xsl:stylesheet version="1.0" xmlns:ra="http://www5a.biglobe.ne.jp/~rarin/xml/ra" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="ra" > (略) </xsl:stylesheet>
変換結果に不要な名前空間を xsl:stylesheet の属性 exclude-result-prefixes で指定してやる。
(略) <html xml:lang="ja" dir="ltr" xmlns="http://www.w3.org/1999/xhtml" > (略) </html>
不要な名前空間宣言が消える。
xsl:copy がらみで exclude-result-prefixes が効かなくなる例。
(略)
<ra:sample
xmlns:ra="http://www5a.biglobe.ne.jp/~rarin/xml/ra"
xmlns="http://www.w3.org/1999/xhtml"
title="XSLT Sample namespace 03"
>
<p>
xsl:copy でコピーされるノード。
<br />
(余計な名前空間宣言が付いてしまう。ソース参照のこと。)
</p>
</ra:sample><?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet
version="1.0"
xmlns:ra="http://www5a.biglobe.ne.jp/~rarin/xml/ra"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="ra"
>
(略)
<xsl:template match="/ra:sample">
<html xml:lang="ja" dir="ltr">
(略)
<body>
<h1><xsl:value-of select="@title" /></h1>
<xsl:apply-templates />
</body>
</html>
</xsl:template>
<xsl:template match="* | @* | text()">
<xsl:copy>
<xsl:apply-templates select="* | @* | text()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>変換方法が指定されていないノードは全てそのままコピーするように指定すると……。
(略)
<html
xml:lang="ja" dir="ltr"
xmlns="http://www.w3.org/1999/xhtml"
>
(略)
<body>
<h1>XSLT Sample namespace 03</h1>
<p xmlns:ra="http://www5a.biglobe.ne.jp/~rarin/xml/ra">
xsl:copy でコピーされるノード。
<br></br>
(余計な名前空間宣言が付いてしまう。ソース参照のこと。)
</p>
</body>
</html>コピーされた要素中、ルートノードに一番近いものの属性に名前空間宣言が現れてしまう。 例えば上の例で XML 文書に段落 ( <p> ) が複数あれば、段落ごとに名前空間宣言が現れ、 <html> の属性一つで済んでいた最初の例より鬱陶しいことになる。
xsl:copy が名前空間ノードまで複製するのは、XSL Transformations (XSLT) Version 1.0 で、 The namespace nodes of the current node are automatically copied
(→ 7.5 Copying ) と述べられている通り、正しい挙動である。 しかし exclude-result-prefixes で指定した名前空間の宣言が最終出力に現れて良いのかどうかは良く判らない……。
( 横道 : xsl:copy が <br /> を <br></br> に展開するのを抑制するには → xsl:copy での空要素の展開を抑える )
xsl:element で local-name() だけを出力することで名前空間の宣言を消す例。
(略)
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet
version="1.0"
xmlns:ra="http://www5a.biglobe.ne.jp/~rarin/xml/ra"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="xhtml ra"
>
(略)
<xsl:template match="/ra:sample">
(略)
</xsl:template>
<xsl:template match="xhtml:*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
元々 XHTML の要素なら、変換後の XHTML に名前空間までコピーしなくて良い。 ローカル名だけを持つ要素を作る。
ここで、XHTML の要素であることを明示するために新たな名前空間 xhtml を導入すると共に、名前空間 xhtml の宣言が変換結果に現れないようにするために、 exclude-result-prefixes="xhtml ra" と指定している。
(略)
<html
xml:lang="ja" dir="ltr"
xmlns="http://www.w3.org/1999/xhtml"
>
(略)
<body>
<h1>XSLT Sample namespace 04</h1>
<p>
local-name() だけを出力したノード。
<br></br>
(余計な名前空間宣言が無くなっている。
しかし、空要素が展開されている。ソース参照のこと。)
</p>
</body>
</html>余計な名前空間の宣言は無くなった。 しかし、 xsl:copy の時と同様に <br /> が <br></br> に展開されている。
前項までで不要な名前空間宣言の削除については解決した。 残った問題 ―空要素の展開を抑止する方法― について考える。 ( msxsl 依存かも。 )
(略)
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet
(略)
>
(略)
<xsl:template match="/ra:sample">
(略)
</xsl:template>
<xsl:template match="xhtml:*">
(略)
</xsl:template>
<xsl:template match="xhtml:br | xhtml:hr | xhtml:img">
<!--
以下のように xsl:apply-templates を抜くと展開されない。
処理系 (msxsl) 依存かも。
-->
<xsl:element name="{local-name()}">
<xsl:copy-of select="@*" />
<!-- <xsl:apply-templates /> -->
</xsl:element>
</xsl:template>
</xsl:stylesheet>展開を抑えたい要素 ( 上記の例ではとりあえず br, hr, img の三つ ) については、 xsl:apply-templates を行わない。
(略)
<html
xml:lang="ja" dir="ltr"
xmlns="http://www.w3.org/1999/xhtml"
>
(略)
<body>
<h1>XSLT Sample namespace 05</h1>
<p>
local-name() だけを出力したノード。
<br />
(余計な名前空間宣言が無くなっている。
空要素の展開が抑えられている。ソース参照のこと。)
</p>
</body>
</html>満足できる変換結果が得られた。
デバグ/学習用。 要素名、属性名の後に、[{URI}ローカル名] を出力する XSLT 。
<ra:sample [{http://www5a.biglobe.ne.jp/~rarin/xml/ra}sample]>
<e1 [{}e1]
a1 [{}a1] = ""
ra:a2 [{http://www5a.biglobe.ne.jp/~rarin/xml/ra}a2] = ""
xh:a3 [{http://www.w3.org/1999/xhtml}a3] = ""
/>
</ra:sample>| XML | : sample/show_namespace.xml |
| XSLT | : sample/show_namespace.xsl |
| 変換結果 | : sample/show_namespace.txt |
このページは XSLT によって生成されている。 XSLT は xsl:for-each による目次の自動生成や、xsl:element による XHTML のタグ利用等の実例になっている。 ( 内容無保証。参考にする際には十分試験すること。 )
| XML (本体) | : xslt_tips.xml | |
| XML (概要) | : s_abstract.xml | |
| XML (基本構造) | : s_structure.xml | |
| XML (小技) | : s_tips.xml | |
| XML (制御構造) | : s_control.xml | |
| XML (移植) | : s_transport.xml | |
| XML (名前空間) | : s_namespace.xml | |
| XML (実例) | : s_example.xml | |
| XML (未解決) | : s_unsettled.xml | |
| XML (おまけ) | : s_appendix.xml | |
| XML (リンク) | : s_link.xml | |
| XSLT (本体) | : ra.xsl | |
| XSLT (定数) | : const.xsl | |
| XSLT (MS依存) | : ms_script.xsl | |
| XSLT (デフォルト) | : default.xsl | |
| XSLT (用語集) | : glossary.xsl | |
| XSLT (確率計算) | : same_birthday.xsl | |
| 変換結果 (HTML) | : xslt_tips.html | (このページ) |
| メイクファイル | : makefile | |
日記 ( 「らの生活」 ) の HTML と RSS を XML 文書から自動生成するために使っている XSLT と メイクファイル。 XML 文書をフラットな構造に変更したため、XSLT 側が随分汚いことに……。
| XML | : ../ra/index.xml | |
| XSLT (HTML 用) | : ../ra/diary_v0200.xsl | |
| XSLT (RSS 生成用) | : ../ra/index_rdf_v0200.xsl | |
| XSLT (RSS 表示用) | : ../ra/rdf.xsl | |
| 変換結果 (HTML) | : ../ra/index.html | |
| 変換結果 (RSS) | : ../ra/index.rdf | |
| メイクファイル | : ../ra/makefile | |
| おまけ (スキーマ) | : ../ra/diary.xsd | (更新してないので、現状の XML と合ってません。) |
最初冗談のつもりで作りはじめたんだけど、ループと文字列関数関係の実例になったので公開してみる。
| XML | : sample/hk2zk.xml |
| XSLT (テンプレートのテスト用) | : sample/hk2zk.xsl |
| XSLT (テンプレート本体) | : hk2zk.xsl |
| 変換結果 (HTML) | : sample/hk2zk.html |
ループの実例。計算精度については未確認。
| XML | : ../ra/same_birthday.xml |
| XSLT | : same_birthday.xsl |
| 変換結果 (HTML) | : ../ra/same_birthday.html |
XML 文書を直接ブラウズしている際、Mozilla 1.3 ではリンクがうまく働かず、ページ先頭に戻されてしまう事がある。 例えばこのページのXML版では、目次以降のリンクが働いていない。 ( IE6 では XML のままで問題なくリンクできている。 )
これが UA側の問題なのか XML/XSLT 側の問題なのか特定できていない。 解決方法も不明。
解決したかも。 いろいろ試してみた結果、 id 属性を含む要素の前で改行しておけば良いようだ。 具体的にはこのページ生成用の XSLT ( 中のそれっぽいコメントの付いた付近 ) を参照のこと。 改行なしの XHTML 版で問題が無かったことから、 UA 側の問題っぽい気がするけど良く判らない。
さらにいろいろ試してみた結果、↑ の改行は本当の原因では無くて、
| XSLT | : sample/link_good.xsl |
| XML | : sample/link_good.xml |
| XSLT | : sample/link_bad.xsl |
| XML | : sample/link_bad.xml |
のように、代替スタイルシートを指定するだけで飛べなくなってしまった。 もう、さっぱり理由が判らない。
(2004-02-13 追記)別のバージョンでも試してみた結果、
さしあたって ( 自分では ) 困ってはいないペンディング事項。
Shift_JIS の .xml と .xsl から UTF-8 の .html を出力する。
| XML | : sample/encoding.xml |
| XSLT | : sample/encoding.xsl |
| 変換結果 (HTML) | : sample/encoding.html |
XSLT 中のパラメタ ( <xsl:param name="パラメタ名">デフォルト値</xsl:param> ) の値はコマンドラインから指定する。 msxsl でのパラメタの渡し方は以下のようになる。
以下の変換結果は、コマンドラインで、
msxsl param.xml param.xsl -o param.html param_1=value_1 param_2="value '2'" param3='value "3"'
と指定した時のもの。 ( sample/makefile も参照のこと )
| XML | : sample/param.xml |
| XSLT | : sample/param.xsl |
| 変換結果 (HTML) | : sample/param.html |
サンプルの変換結果を生成するのに使っているメイクファイル。