2012-06-08T09:12:14+09:00

XSLT で空要素のエンドタグが出力されちゃう問題と闘った話

このサイトの構築には、XSLT をちょくちょく使っている。例えば、このページのタイトルとかヘッダーとか本文以外のものは、クライアントのブラウザが XSLT を処理して付け加えてくれている。多くの場合は、サーバーサイドの CGI などで動的に HTML を処理するのが一般的だと思うけど、そういうことができない環境で静的な HTML だけでサイトを構築してきたので、クライアントサイドで HTML をガッツリ変更できる XSLT は重宝している。

最近、XSLT の出力で、ソースである XHTML から "<br />" をコピーすると "<br></br>" となって出力されてしまうことに気付いた。一見、問題なさそうだけど、多くのブラウザは、"<br></br>"は改行二つと解釈してしまう。

出力メソッドを "html" から "xml" とすれば "<br />"と出力してくれるけど、動かない JavaScript が続出するんだよね。

XSLT の仕様では、出力メソッドを html にすれば、空要素のエンドタグは出力されないことになっている。なのに </br> が登場するとは、どうしたことか。想像するに、ソースの XHTML からやってきた"<br/ >" はコピーしても、HTML ではなくXHTML の名前空間に所属しており、XHTML の要素である以上はエンドタグは必須・・・ということかと思う。

似たような問題に遭遇された方もいらっしゃるようで、空要素の展開抑制なるテクニックを紹介されているサイトを見つけた。

XSLT : http://www5a.biglobe.ne.jp/~rarin/xml/xslt_tips.html

ただ、このサイトでのっている方法では、Safari もしくは xsltproc においては解決できなかった。たぶん、出力メソッドが xml で処理系が msxml の場合に効果があるのだと思う。

結局どうしたかというと、

<xsl:template match="h:br">
<xsl:text disable-output-escaping="yes"><![CDATA[<br />]]></xsl:text>
</xsl:template>

とした。つまり、br タグがあったら、コピーするのではなく、文字列として"<br />"を出力するというもの。なんともダーティーな方法だけど、他にやり方が見つからない。 誰か、スマートな解決策を教えて下さい。