お仕事モード。めもバージョン。
xsltproc コマンドで XML ファイルの処理をしようと、XSLT を作っていた。(作っているのは FreeBSD 5.5-RELEASE-p15 上だけど、完成したら Red Hat ES 4 に持って行く(;_;))
でその中で、処理結果以外に処理した件数を別のファイルへ出力したくなったが、XSLT 1.0 ではそんなものはサポートしていない。しかし世の中には拡張(extention) XSLT というのがあり、その拡張の中に document という別ファイルへ出力するコマンドが含まれている。そして、xsltproc はそれをサポートしているらしい。(リンク先の下の方を参照)
ということで、
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common" ...
と書いて、xsl:~ は通常の xslt のコマンド。exsl:~ は exslt のコマンドと定義。
そしていざ、exsl:document ...動かない。悩むこと 4時間。
このページをみると、なんと通常の xslt のコマンドとして document が入っている(exsl:document)ではないですか。
...名前空間区別してくれ~。
xsltproc --dumpextensions の結果も、「{http://exslt.org/common}document」と exslt に定義されている document であると言っているのに。
名前空間。
入力ファイルの名前空間が何個かある。
xmlns:nice="http://1yen.cx/foo/nice"
xmlns:bad="http://1yen.cx/foo/bad"
xmlns:so-bad="http://1yen.cx/foo/so-bad"
...
でも、これらは同じ XSLT ファイルで処理できる。ところが名前空間が違うため
<xsl:namespace-alias stylesheet-prefix="bad" result-prefix="nice" />
<xsl:namespace-alias stylesheet-prefix="so-bad" result-prefix="nice" />
と書いて、bad, so-bad... を nice と読み替えて処理しようとした。
だがしかし、入力ファイル上では <nice:tag> とか <bad:tag> なので XPath 上は違う物となり、同じ XSLT で扱えない。そういう時は
入力ファイル → XSLT(名前空間を変換) → XSLT(実際の処理) → 結果
としなくてはいけないらしい。
入力ファイルが数メガあって処理にメモリーを食うので、できればまとめて 1回で処理したかったなぁ。(今回の目的ではパイプで繋いで 2つの XSLT が同時に起動するため)
実際には、#default 名前空間変換へ変換して、URL には結びつけないようにしようかなと思っている。
<xsl:namespace-alias stylesheet-prefix="bad" result-prefix="#default" />
<xsl:namespace-alias stylesheet-prefix="so-bad" result-prefix="#default" />
ちなみに xsltproc と同じく xslt を処理できる Sablot-1.0.2 は、exsl:document で実行できるが、exslt サイトにある関数追加用の xsl ファイル(zip で固めてあるやつ)を一部解釈できない模様で、今回の用途に使えなかった。
xsltproc の方が、実装として上なんだろうけど、正しくないのは悲しいなぁ。
xsltproc コマンドで XML ファイルの処理をしようと、XSLT を作っていた。(作っているのは FreeBSD 5.5-RELEASE-p15 上だけど、完成したら Red Hat ES 4 に持って行く(;_;))
でその中で、処理結果以外に処理した件数を別のファイルへ出力したくなったが、XSLT 1.0 ではそんなものはサポートしていない。しかし世の中には拡張(extention) XSLT というのがあり、その拡張の中に document という別ファイルへ出力するコマンドが含まれている。そして、xsltproc はそれをサポートしているらしい。(リンク先の下の方を参照)
ということで、
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common" ...
と書いて、xsl:~ は通常の xslt のコマンド。exsl:~ は exslt のコマンドと定義。
そしていざ、exsl:document ...動かない。悩むこと 4時間。
このページをみると、なんと通常の xslt のコマンドとして document が入っている(exsl:document)ではないですか。
...名前空間区別してくれ~。
xsltproc --dumpextensions の結果も、「{http://exslt.org/common}document」と exslt に定義されている document であると言っているのに。
名前空間。
入力ファイルの名前空間が何個かある。
xmlns:nice="http://1yen.cx/foo/nice"
xmlns:bad="http://1yen.cx/foo/bad"
xmlns:so-bad="http://1yen.cx/foo/so-bad"
...
でも、これらは同じ XSLT ファイルで処理できる。ところが名前空間が違うため
<xsl:namespace-alias stylesheet-prefix="bad" result-prefix="nice" />
<xsl:namespace-alias stylesheet-prefix="so-bad" result-prefix="nice" />
と書いて、bad, so-bad... を nice と読み替えて処理しようとした。
だがしかし、入力ファイル上では <nice:tag> とか <bad:tag> なので XPath 上は違う物となり、同じ XSLT で扱えない。そういう時は
入力ファイル → XSLT(名前空間を変換) → XSLT(実際の処理) → 結果
としなくてはいけないらしい。
入力ファイルが数メガあって処理にメモリーを食うので、できればまとめて 1回で処理したかったなぁ。(今回の目的ではパイプで繋いで 2つの XSLT が同時に起動するため)
実際には、#default 名前空間変換へ変換して、URL には結びつけないようにしようかなと思っている。
<xsl:namespace-alias stylesheet-prefix="bad" result-prefix="#default" />
<xsl:namespace-alias stylesheet-prefix="so-bad" result-prefix="#default" />
ちなみに xsltproc と同じく xslt を処理できる Sablot-1.0.2 は、exsl:document で実行できるが、exslt サイトにある関数追加用の xsl ファイル(zip で固めてあるやつ)を一部解釈できない模様で、今回の用途に使えなかった。
xsltproc の方が、実装として上なんだろうけど、正しくないのは悲しいなぁ。