XML文書にXSLスタイルシートを適用する際の注意事項。

テーマ

XML文書にXSLスタイルシートを適用する際の注意事項をメモしております。

はじめに。

制作者は、サイトで配信しているRSSについて、XSLで書いたスタイルシートを適用する事で、現行のXML対応ウェブブラウザではクライアント側でHTML文書化して閲覧出来るようにしております。

過日、下手なイラスト関連のコンテンツに関する情報を配信するRSSの仕様を変更し、使用しているXSLスタイルシートも差し換えました。

その際に気付いた点を挙げておきます。

XML文書にXSLスタイルシートを併用する際の考え方。

XML文書にXSLスタイルシートを適用する事で、他のXMLフォーマットやHTML文書に変換して利用する事が可能になります。

  • サーヴァ側でXSLT(XSLスタイルシートを利用したコンテンツ変換)を用いる事で、XML非対応の環境でもHTML文書として利用する事が可能になりますが、そのような使い方は余りされず、

    • 予めXSLTでHTML化したものをサーヴァに置いて配信するか、
    • XSLスタイルシートを関連付けたXML文書を配信して、ウェブブラウザではクライアント側でHTML化してもらうようにする

    使い方が主流のようです。

XSLに対応しているウェブブラウザであれば、取得したXML文書に対し<?xml-stylesheet ?>処理命令でXSLスタイルシートの併用が命じられていれば、内部で当該スタイルシートを適用したXSLTでHTMLに変換してそれをレンダリングする形になります。

このため、実際のウェブブラウザでのレンダリングのフォーマットについては、変換後のHTMLにCSSに依るスタイルシートを適用する形になります。

XSLスタイルシートで記述するには、

  • 出力されるHTML文書のテンプレート内のHTMLに適切にid属性やclass属性を与え、
  • 且つ<head>要素内に適切な<link>要素を記述する事でスタイルシートをリンク出来るように

すれば良い事になります。

注意したい事は、配信するXML文書に<?xml-stylesheet ?>処理命令で変換後のHTML文書に対するCSSに依るスタイルシートの併用を命じてはいけないと言う事です。

<?xml-stylesheet ?>処理命令は当該XML文書の取扱いに対してなされる命令であり、XSLTでの変換後のフォーマットの処理に際し適用される命令ではないからです。

  • XSLが取扱える多くのウェブブラウザでは、CSSを取扱うよう命じた<?xml-stylesheet ?>処理命令とXSLを取扱うよう命じた<?xml-stylesheet ?>処理命令でが併記されている場合、XSLを優先するようになっているようです。

現行のウェブブラウザでの問題点。

有名な話ですが、ファイヤーフォックス等の現行のウェブブラウザの場合、RSSを独自のフォーマットでレンダリングするようになっております。

そのため、折角XSLスタイルシートを作っても意味がなくなってしまう場合が多くなってしまいます。

ファイヤーフォックスやインターネットエクスプローラの場合、ルート要素開始タグの直前に128個以上のホワイトスペースを入れると、指定のXSLスタイルシートを使ってくれるようになりますが、オペラではどうしてもやってくれないみたいです。

XSLスタイルシートで広告や関連リンクなどを埋め込みたい方は注意した方が良いでしょう。

ホワイトスペースの扱いについて。

XMLを使っている方にとっては常識だと思いますが、XMLでのホワイトスペースの扱いは、HTMLでのそれと大きく異なっております。

HTMLでは、タグの前後のスペースについて、開始タグ直後と終了タグ直前を除いて認識されます。

このため、単純にXSLを適用した場合、HTMLと違って改行や水平タブなどが無視され、結果レンダリングに影響が出る場合もあります。

HTMLと同様のレンダリングにしたい場合は、XSLスタイルシートのルート要素(通常<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">要素となると思います)に xml:space="preserve" 属性を附与する必要があります

注意:要素の生成時にはホワイトスペースの扱いを元に戻す必要があります。

ただ、この場合注意しなければならない事として、出力HTMLでの要素の属性値となる文字列を加工する場合に余計なホワイトスペースが紛れると、ファイヤーフォックス等でエラーになる場合があります。

例えば、以下のようなXSLスタイルシートがあったとします。

<xsl:element name="img">
    <xsl:attribute name="alt"><xsl:for-each select="../title"><xsl:value-of select="."/></xsl:for-each>の画像</xsl:attribute>
    <xsl:attribute name="src">
        <xsl:choose>
            <xsl:when test="@url='HORIKITA_Maki.GIF'">http://www.uso800.uso/_Horikita_TN.GIF</xsl:when>
            <xsl:otherwise><xsl:value-of select="substring-before(@url,'.GIF')"/>.JPG</xsl:otherwise>
            </xsl:choose>
        </xsl:attribute>
    </xsl:element>

これは、変換元のある要素のurl属性の値と兄弟ノードとなる<title>要素に合わせて適切な<img>要素を生成するための記述です。

具体的には、

  1. alt属性としては兄弟ノードの<title>要素の内容に の画像 を連結させた文字列を与え、
  2. src属性の値としては、

    • ある特別なURLの場合は、サムネイル専用の画像のURLに置き換え、
    • そうでない場合は、画像のURLの末尾にある拡張子を.GIFから.JPGに置き換える

と言うものです。

ここでは読み易くするため、適切に水平タブを補っておりますが、これらの文字が紛れ込む事でファイヤーフォックス等では変換エラーになる場合があります。

もっとも安易な対策は、ホワイトスペースを全部詰めてしまう事ですが、そうすると可読性を大きく損ねてしまい、却って問題になってしまうでしょう。

そこで、<xsl:element>要素の内容に水平タブや改行が含まれる場合には、当該要素に xml:space="default" 属性を附与する事で、ホワイトスペースの扱いを本来の扱い方(実装依存です)に一時的に戻すと言うのがベストでしょう。

  • <xsl:element>要素に xml:space="default" 属性を附与する方法ではダメのようです。

すなわち、件の記述は以下のように変更します。

<xsl:element name="img" xml:space="default">
    <xsl:attribute name="alt"><xsl:for-each select="../title"><xsl:value-of select="."/></xsl:for-each>の画像</xsl:attribute>
    <xsl:attribute name="src">
        <xsl:choose>
            <xsl:when test="@url='HORIKITA_Maki.GIF'">http://www.uso800.uso/_Horikita_TN.GIF</xsl:when>
            <xsl:otherwise><xsl:value-of select="substring-before(@url,'.GIF')"/>.JPG</xsl:otherwise>
            </xsl:choose>
        </xsl:attribute>
    </xsl:element>

インターネットエクスプローラでの問題点。

ウィンドウズ版のインターネットエクスプローラではXMLを処理するためにウィンドウズに装備されたMSXMLと呼ばれるモジュールを利用して、XML文書を処理します。

この処理ではXSLTも利用出来るのですが、此処に落とし穴があります。

それは、変換後のHTMLのレンダリングが標準準拠モードとならない場合があると言う事です。

ご承知の事と存じますが、インターネットエクスプローラには、ウィンドウズ版では6.0から二つのレンダリングモードを実装しております。

すなわち、

の二つです。

ウェブサイトで適用するCSSに依るスタイルシートでは、通常標準に準拠したものを用いる筈ですが、変換後のHTMLのレンダリングに非標準モードが適用されると、とんでもないレンダリング結果になってしまうかも知れません。

制作者の場合、実際にイラストの公開状況をお知らせするRSSでとんでもない目に遭いました。

望ましい標準準拠モードでのレンダリング
望ましい標準準拠モードでのレンダリングのスクリーンショット(幅1,024ピクセルズ、高さ768ピクセルズのGIF画像)
インターネットエクスプローラ 8.0でのクァークモードでのレンダリングされてしまった例
IE 8.0でクァークモードにされてしまったスクリーンショット(幅1,024ピクセルズ、高さ768ピクセルズのGIF画像)

実際のインターネットエクスプローラ対策(8.0以降のみ有効)。

実際にこの問題を解決するには、レンダリングモードの切り替えがどう行われているかを識る必要があります。

ウィンドウズ版のインターネットエクスプローラでは、6.0から文書型宣言の記述状況でレンダリングを切り替える方法を導入しておりますが、XSLTを通じて出力したHTMLにはそのような操作は出来ません。

その後、8.0でレンダリングモードの切り替えに用いる<meta>要素がサポートされ、これを用いる事で8.0以降ではレンダリングモードを自由に切り替えられるようになりました。

XSLの場合はこの方法を用いるしかないでしょう。

具体的には、XSLスタイルシート内の<head>要素のテンプレートに、以下の<meta>要素を書き加えます。

<meta http-equiv="X-UA-Compatible" content="IE=edge" />

content属性には他にも適切な値が考えられるのですが、この値でないと巧くいかない場合があるようです。

尚、くどいようですが、この方法はIE 8.0以降でのみ有効です

  • 日本国内でも流石に 6.0 のユーザは激減しておりますが、まだ 7.0 を使っている方は少なくありません。この辺が悩みの種となるでしょう。