ノードセットと結果ツリーフラグメント

| コメント(0) | トラックバック(0)

概要: Opera 9もXSLTプロセッサが実装されたようですが、Mozilla Firefoxでも実装されているんですね。Netscapeの日本法人が撤退してバージョンアップが止まっているということを(今更...

Opera 9もXSLTプロセッサが実装されたようですが、Mozilla Firefoxでも実装されているんですね。Netscapeの日本法人が撤退してバージョンアップが止まっているということを(今更)知ったので、Firefox 2.0を入れてみましたが、…うん、これはなかなか。フォント周りも強くなってるし。

Firefox 2のXSLTプロセッサはXSLT 1.0のdocument関数が使えるのはいいんですが、結果ツリーフラグメント(Result Tree Fragment)をノードセットとして評価することができないようです。

そもそも結果ツリーフラグメントって何かというと、大雑把に言えばxsl:variable要素やxsl:param要素の内容としての値です。例えば、

<xsl:variable name="result">
  <level>3</level>
  <number>1-1</number>
</xsl:variable>

上記のような変数resultがあった場合、$resultはlevelとnumberの二つのノードを持つノードセットのように見えますが、これはノードセットにはなりません。結果ツリーフラグメントと呼ばれます。結果ツリーフラグメントに対しては文字列操作しか許されず、勿論/や//、[]などのノードセットに対してのみ使える演算子は使えません。ただ、xsl:copy-of要素のselect属性で結果ツリーフラグメントを値に持つ変数を指定すると(<xsl:copy-of select="$result"/>のようにすると)、あたかもそれがノードセットであるかのように振る舞います。

別の例を見てみましょう。対象とするXML文書の子孫にbodyという要素があって、body要素は幾つかのsection要素を子に持っているとします(うちのXML文書のスタイルです)。この時、次のXSLTコード(断片というべき?)は許されます:

<xsl:variable name="body" select="//body"/>
<xsl:for-each select="$body/section">
  <!-- 何らかの処理 -->
</xsl:for-each>

しかし、次のようにすると誤りです。

<xsl:variable name="body">
  <xsl:copy-of select="//body">
</xsl:variable>
<xsl:for-each select="$body/section">
  <!-- 何らかの処理 -->
</xsl:for-each>

先程も言った通り、xsl:variable要素などの内容にしてしまうと、それがなんであれ結果ツリーフラグメントになるのです。数値を書いても文字列を書いても何でもかんでも結果ツリーフラグメントに。一方で、select属性で値を与えると、式の型と同じになります。ノードセットならノードセットに、数値なら数値に、文字列なら文字列に、ブーリアンならブーリアンに。そんな訳で、前者の$bodyはノードセットで、後者の$bodyは結果ツリーフラグメントなのです。ああ無情。

しかしながら、xsl:variableの内容として書いてもノードセットとしてみてもらいたいことは少なくないわけで、──例えば変数の値にa要素を幾つか書いておいて、あとでそれをxsl:for-eachで処理するとか、テンプレートの戻り値(戻り結果ツリーフラグメント?)が複雑になる場合、さっきのlevelやnumberのように要素で区切って返すとか(Cで言うと構造体を返す感じ)。そんな時のために、IEやSablotron(PHPとかでも使える、何かの素粒子か加速器みたいな名前のXSLTプロセッサ)などでは次のような技巧が使えます:

<xsl:variable name="result">
  <level>3</level>
  <number>1-1</number>
</xsl:variable>
<xsl:variable name="result-node" select="$result"/>

これで、$resultは結果ツリーフラグメントですが、$result-nodeは(select属性で値を与えているので)ノードセットになります。……って、こんなんでいいなら最初っからxsl:variableの内容でもノードセットにしろッ! と叫びたくなりますが、まぁXSLT 1.0の仕様書に「内容だったら結果ツリーフラグメントと見なせ」って書いてあるので、なんとも……。ちなみに独自拡張のnode-set関数でもいいようです。

IE 6でもこの技巧が使えたので、数年前からずっとこの方法を愛用しているのですが、どーもFirefoxのXSLTプロセッサはこれが駄目らしい。仕様書に書いてないからバグではないんだけど、悲しい。Opera 9はこの方法が使えるけど、document関数がまだ実装されてないし…(近々実装されるという噂だけはあるけども)。うーん。結局IE6以降でなければサーバーサイドで変換するしかないようで。はぁ、がっくし……

トラックバック(0)

トラックバックURL: http://w4ard.s26.xrea.com/program/mt/mt-tb.cgi/15

コメントする

このブログ記事について

このページは、E+Xが2006年12月16日 16:36に書いたブログ記事です。

ひとつ前のブログ記事は「最近気付いた些細なこと」です。

次のブログ記事は「Windows Vistaのシステム要件」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。