XMLメモ

XHTMLを書く
XMLからXSLT変換を行ってHTML文書を生成させるためには、 XSLTスタイルシートにはHTML文書を一歩厳格にした「XHTML」 の体裁で書かなくてはいけません。 これはそんなにムズカシイことではないのですが、 ついついうっかり間違えてしまいがちなので、ここで超基本をまとめておきます。

  • 属性はダブルクォートで囲む
      × <table width=100% cellpadding=0> ... </table>
      ○ <table width="100%" cellpadding="0"> ... </table>
      
  • タグは開いたら閉じる
      × <img src="a.gif">
      ○ <img src="a.gif"></img>
      ○ <img src="a.gif" />
      
  • タグ名は小文字が標準
    これは必須ではありませんが、既にそのような標準になっていると思います。 また、XHTMLではタグの大文字・小文字は区別されるので、 小文字に統一するのがよいでしょう。

リンクの半角波線(チルダ)がXSLTを行うと文字化け
リンクの半角波線は%7eとエスケープします。

XMLとXSLのテンプレート

<?xml version="1.0" encoding="Shift_JIS"?>
<?xml-stylesheet type="text/xsl" href="oramemo.xsl" ?>
<document>
...
</document>

<?xml version="1.0" encoding="Shift_JIS"?>
<!-- <xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl"> -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="html" encoding="Shift_JIS" version="1.0"
   doctype-public="-//W3C/DTD XHTML 1.0 Strict/EN"
   doctype-system="DTD/xhtml1-strict.dtd" />

<xsl:template match="/document">
...
</xsl:template>
<xsl:stylesheet>

HTMLタグの属性にXMLの値を使うには
XLSTで、XMLタグの値をA HREF=タグの値に使いたいときは、

<a href="<xsl:value-of select="url" />">リンク</a>

とすると、エラーになってしまいます。この場合の正解は

<a href="{url}">リンク</a>

です。

XSLTでの変数の使用
xsl:variableタグを使い、 XSL変数を定義します。{$変数名}という形で参照できます。

<xsl:variable name="url">
  <xsl:value-of select="url" />
</xsl:variable>
<a href="{$url}">リンク</a>

xsl:for-eachと番号づけ
xsl:for-eachタグで複数のエントリを表形式などに繰り返し処理するとき、 各行を1番から順に番号づけしたい場合、 xsl:numberタグを使います。 下の例のように、2種類の使い方があります。 format=には、「(1)」「1. 」「1」のような感じで書式を指定します。

<xsl:for-each select="customer">
  <tr>
    <td bgcolor="#e0ccdc">
    <!-- <xsl:number value="position()" format="1. "/> -->
    <xsl:number level="single" count="customer" format="1. " />
    </td>
    <td><xsl:value-of select="name" /></td>
    <td bgcolor="#e0ccdc"><xsl:value-of select="address" /></td>
  </tr>
</xsl:for-each>

HTMLタグを含む文章をXMLに埋め込む
よくある例ですが、日記の本文のようなXML要素の中で、 改行などのためにHTMLタグを使ったとき、 そのHTMLタグも含めてXLSTでHTML文書に変換したい、 ということがあります。この場合は、そのXML要素をvalue-ofの代わりに copy-ofで参照すればOKです。以下はXSLスタイルシートの一部です。

<xsl:template match="entry">
<p><xsl:copy-of select="description" /></p>
</xsl:template>

これで、*/entry/descriptionという要素がHTMLタグを含む文章である場合、 その内容がHTML構造も含めてpタグの間に挿入されます。

テンプレートにパラメータを渡す
 テンプレートを呼び出すとき、パラメータを一緒に渡して、 それによってテンプレートの処理を変えたりすることができます。 テンプレート側でパラメータを定義するには、xsl:param タグを使います。

<xsl:template name="example">
<xsl:param name="dumparam"/>
...
<xsl:if test="$dumparam = ''">
  ...
</xsl:if>
</xsl:template>

初期値(デフォルト値)も設定できます。これは、 テンプレートがパラメータを渡されずに呼ばれたときに使われる値です。

<xsl:template name="example">
<xsl:param name="dumparam">99</xsl:param>
...
<xsl:if test="$dumparam = ''">
  ...
</xsl:if>
</xsl:template>

呼び出す側は、xsl:call-templateタグの中に、 xsl:with-paramタグをパラメータの数だけ列挙します。

<xsl:call-template name="example">
<xsl:with-param name="dumparam">10</xsl:with-param>
</xsl:call-template>

XSLに外部からパラメータを渡す
 あるXSLを適用する際に、XSLT実行を指示するアプリケーション側から、 何かパラメータを渡してやって、それで動作を制御することもできます。

<xsl:param name="targetStr" select="aaa" />

<xsl:template match="/document/file">
  <xsl:for-each select="$doc//document/category/entry">
    <xsl:if test="contains(qq, $targetStr) or contains(aa, $targetStr)">
(後略)

これも上記と同様xsl:paramを使います。 ただし、そのタグの位置が違っていて、どのxsl:template等にも囲まれていない、 最上位に書く必要があります。 パラメータが渡されると、後はどのテンプレート内でも、「$パラメータ名」 の形で自由に参照することができます。
 パラメータの渡し方は、外部アプリケーション次第です。 例えばlibXSLTに含まれるコマンドラインXSLTプロセッサ、xsltprocでは、 --paramオプションで指定できます。

% xsltproc --param targetStr 'NEW_VALUE' abc.xml

パラメータの「値」はXPath式として解釈されるので、 文字列はシングルクォートで囲むのを忘れずに!とFAQに載っています。
 またJavaのXSLTプロセッサであるApache Xalanには、 XSLにパラメータを設定するAPIが公開されています。 この例がとても実用的で、 分かりやすいと思います。

テンプレートを別ファイルからインポートする
 テンプレートを別ファイルから取り込む方法は、 テンプレートの再利用性という意味で大きな効果があります。 まず、インポート「される」別ファイルを次のように作ります。

<?xml version="1.0" encoding="euc-jp"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template name="example">
  ...
</xsl:template>
</xsl:stylesheet>

上記のファイルをsample.xslを名づけます。 今度はこのテンプレートをインポートするXSL文書です。 冒頭のxsl:stylesheetタグとxsl:outputタグの間に

<xsl:import href="./sample.xsl" />

と書くとテンプレートがインポートされます。 実際に使うには?もちろん、テンプレートを呼び出したい位置で xsl:call-templateタグを使えばOKです。
 なお、xsl:includeというタグも同じように外部ファイルを取り込みます。 こちらは、xsl:stylesheetタグの直下の階層に書きさえすれば、 XSL文書の冒頭部以外の場所にも記述できるという特徴があります。 それ以上の詳しいことは、まだ理解していません(-_-;)

文書型定義(DTD)を書く
XML文書が想定しているタグ構造で本当に書かれているかどうかをXMLパーサがチェックするための仕組として、 文書型定義があります。 これはこんなものです。

<!ELEMENT document (title, last_updated, category*)>
<!ELEMENT category (ctitle, entry*)>
<!ELEMENT entry (id, class, qq, aa, keyword, entrydate)>

最もシンプルなサンプルですが、 これはELEMENTの右側の要素が、その中にどんな要素を含めることができるかを示したものです。 *は、その要素を複数含めることができることを指定します。
文書型定義を別のファイルにする場合、通常.dtdという拡張子をつけます。 一般のXML文書から参照する場合には、

<?xml version="1.0" encoding="euc-jp" ?>
<?xml-stylesheet type="text/xsl" href="../common/example.xsl" ?>
<!DOCTYPE document SYSTEM "example.dtd">
...

と、文書の冒頭部でDOCTYPE宣言で参照します。

XSLスタイルシートの中にCSSを書く
CSSの中に含まれる特殊文字をXSLTプロセッサに解釈させないために、CDATAセクションを使います。

<head>
  <title><xsl:value-of select="title" /></title>
  <style type="text/css"><![CDATA[
    div#title { color : #400000; background-color : #ffeeee ;
                border : 2px solid; padding : 3px; width : 50%; }
    a:link           { text-decoration:none; color:#800000; }
    a:visited        { text-decoration:none; color:#400000; }
    a:hover,a:active { text-decoration:none; color:#C00000; }
    body { color : #000060; }
  ]]></style>
</head>

1つの要素に対して、2種類以上のテンプレートをxsl:apply-templatesするには?
 この方法は分かりません。今のところ、複数のうちどれか1つだけをxsl:apply-templatesで適用し、 残りはxsl:for-eachタグのループを使って実現しています。

XSLTで&nbsp;を出力する方法
 試すと分かりますが、出力HTMLに「&nbsp;」を出力させようとすると、 XSLに「&nbsp;」や「&amp;nbsp;」と書いてもうまくいきません。正解は

<xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>

です。

XML Top

(first uploaded 2002/01/13 last updated 2006/08/06, URANO398)

テレワークならECナビ Yahoo 楽天 LINEがデータ消費ゼロで月額500円〜!
無料ホームページ 無料のクレジットカード 海外格安航空券 海外旅行保険が無料! 海外ホテル