XSLT:テンプレートが基本構造なのだ

ざっとおさらい

 前々回に、XMLにXSLT呼び出しの<?xml-stylesheet type="text/xsl" href="test.xslt"?>を記述し、ブラウザでそのXMLファイルを表示すると、test.xsltファイルに記述したXSLTが適用される、と書いた。
 で、XSLTファイルの一番基礎的な作りは以下のようなものだった。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
	<html><body>ここに書いたものが、そのまま出力される。</body></html>
</xsl:template>
</xsl:stylesheet>

 これなんだけど、<xsl:template match="/">ブロックは省略できるような仕様にした方が分かりやすかったんじゃないか、という気もする。
 そうすれば、とにかくルートの下に出力する文書をそのまま記述すればいいのだから。
 とはいえ、現状そういう仕様になってないんだからしょうがない、もしかしたら新しい仕様ではそうなってたりするのかもしれないけど、ブラウザだと2015年11月現在XSLT1.0しか使えないみたいなので、無い物ねだりだ。

 んで、前回は、XMLから要素や属性などを取り出すための記述方法であるXPathについて書いた。
 要するに、URLと似たような感じでXMLのツリーを書けば良いということだ。

やっとまともな使い方の話

 省略できるようにしてもいいんじゃないの、と思うくらいなので<xsl:template match="/">ブロックはまず間違いなく書くものだと思ってます。
 で、このルートノードから始まって、その中に追加する要素を<xsl:apply-templates select="XPath"/>でさらに呼び出す。
 それに適合する<xsl:template match="XPath">ブロックが実行される。
 という流れで出力されるデータが作られるというのが基本的な作りと思っていいかなと。

 注意するのはtemplateとapply-templatesが1対1に対応しているわけじゃなくて、条件に適合すれば別の書き方をしていても呼び出されるということ。
 複数の条件に適合するtemplateブロックがある場合は、より高い優先度のものが呼び出され、他のものは無視される(競合が解消される)。
 この優先度はわりと直感的に理解できる法則があるので、きっちり知ってないとXSLT作れないというわけではないけど、複雑になるとやっぱりきっちり知ってないと、思うように動いてくれない。

 あと、templateブロックを作ってない場合のデフォルトの動作というのがあって、それを理解しておけば出力用のtemplateブロックを全部書かなくてもよくて楽チン。
 しかしちゃんと理解していないと、期待と全然違う出力がされて「???」ということになる。

単独templateのXSLT

 元データの中から必要なデータを抽出して表組みで出力するなんてのは、templateをひとつ書けばできあがる場合も多い…と思う。
 例えば人物データがXMLに記録されていて、それを適当にフォーマットされたHTMLとかCSVとかJSONやvCardとして出力したいというパターン。
 テストが簡単なように、ブラウザで表示することを前提に以下のXMLを用意。sample02_01.xmlとでも名前を付けて保存。

<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="sample02_01.xslt"?>
<data>
	<name>大串 敏史</name>
	<url>
		<site>http://tonbi.jp/</site>
		<twitter>https://twitter.com/tobishima</twitter>
	</url>
</data>

 以下のようなXSLTを用意。sample02_01.xsltとファイル名をつけて保存。

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" encoding="UTF-8" indent="yes"/>
 
<xsl:template match="/">
    <p>
    名前 : <xsl:value-of select="data/name"/><br />
    サイト : <xsl:value-of select="data/url/site"/> ( 
	<xsl:element name="a">
		<xsl:attribute name="href"><xsl:value-of select="data/url/twitter"/></xsl:attribute>
		ツイッターへのリンク
	</xsl:element>
	)
    </p>
</xsl:template>
</xsl:stylesheet>

 xsl:outputは出力に関するもろもろの設定を書いておく要素。
 encodingは文字のエンコーディングの種類、methodは出力形式でxml、html、textが選べる。
 indentは出力にインデントを加えて整形するかどうかの指定をyesかnoで指定。などいろいろオプションがある。
 書いてなくてもだいたいいい感じに出力してくれる。デフォルトで出力してみて、どうも予定と違う場合に指定するぐらいでいいかもしれない。

 xsl:elementはXML(またはHTML)の要素を作り、その中に書いたxml:attributeは、属性を作る。
 まーだいたい見ての通り。

 で、XMLをブラウザに放り込んでみると、見事HTMLとして出力された。
 ミソはselectにXPathを書くところですかね。
 実際のところ、ここまでわかっていれば、データのトランスフォームが必要な案件のほとんどに片がつくんじゃないかと思う。
 XSLTはこれに加えて、関数の(再帰)呼び出し的にフォーマットしていくことができたり、ifを使った条件分岐とかいろいろと充実した機能をもってたりする。

 なお、このページもXML+XSLTで作っている。ファイル名はindex.xml+index.xsltだ。
 index.xmlがほぼhtmlなので、XSLT変換の一手間が入っている分冗長なだけで、なんらXSLTのメリットとかないのがアレ。
 今回はここまで。