tohokuaikiのチラシの裏

技術的ネタとか。

「XSLT実践ガイド」を読んでて気になった雑多なメモ

[www.amazon.co.jp/dp/4756140653:title=XSLT実践ガイド]

  • p.94 xsltプロセッサは文書で最初にルートノードを読み取る

apply-templates

<?xml version="1.0"?>
<PLANETS>

    <PLANET>
        <NAME>Mercury</NAME>
        <MASS UNITS="(Earth = 1)">.0553</MASS>
        <DAY UNITS="days">58.65</DAY>
        <RADIUS UNITS="miles">1516</RADIUS>
        <DENSITY UNITS="(Earth = 1)">.983</DENSITY>
        <DISTANCE UNITS="million miles">43.4</DISTANCE><!--At perihelion-->
    </PLANET>

    <PLANET>
        <NAME>Venus</NAME>
        <MASS UNITS="(Earth = 1)">.815</MASS>
        <DAY UNITS="days">116.75</DAY>
        <RADIUS UNITS="miles">3716</RADIUS>
        <DENSITY UNITS="(Earth = 1)">.943</DENSITY>
        <DISTANCE UNITS="million miles">66.8</DISTANCE><!--At perihelion-->
    </PLANET>

    <PLANET>
        <NAME>Earth</NAME>
        <MASS UNITS="(Earth = 1)">1</MASS>
        <DAY UNITS="days">1</DAY>
        <RADIUS UNITS="miles">2107</RADIUS>
        <DENSITY UNITS="(Earth = 1)">1</DENSITY>
        <DISTANCE UNITS="million miles">128.4</DISTANCE><!--At perihelion-->
    </PLANET>

</PLANETS>

を変換する時、

	<xsl:template match="/">
		<html>
			<xsl:apply-templates/>
		</html>
	</xsl:template>
	
	<xsl:template match="PLANET">
            <p>planet</p>
	</xsl:template>

のapply-templatesの意味するところは、

  1. matchの「/」に適応したものに対して(つまりルートノード)テンプレートを適用。つまり再帰が掛かる。
  2. 適用するテンプレートはこのスタイルシートに存在するもの全て。ただし、matchで適用条件を決める
  3. テンプレートに引き渡されるのは、
  4. 適用されるは、ルートノードの内の更にPLANETに一致するものだけを処理の対象としていることになる。
  5. もし、同じmatch表現があった場合、最後に表れただけが有効になる。
  6. というようにSELECTオプションを与えた場合、現在のでマッチした対象の中で更ににマッチするもののみをFILTERする。ここでは「/」で既にルートノードのみになっているので以外のselectの値は無効であり、このapply-templates自体を意味のないものにしてしまう。
受け取る要素、受け渡す要素

のSELECTの対象になっているものは現在の要素であり、受け渡すにはその子要素のみが渡されることに注意したい。その孫を処理してとなるとさらにapply-templatesが必要になって来てその受け皿も必要になってくるわけである。

また、SELECTが無かった場合、カレントの子要素のみが処理される。

受け渡すテンプレートが存在しない場合

SELECTにマッチするものが無い場合はタダパスされるだけ。
SELECTにマッチするものがある場合で、その処理要素が他の

  1. マッチするものがある場合は、そのテンプレートが適用される。
  2. マッチするものが無い場合は、テキストデータが露出する。ただし、その場合ループは行われなくて最初の1個のみが表示される。みたいな感じ。"$this"が有効かどうかは知らない

なるほど。結構面倒。

たとえば、さっきのPLANET.XMLで、

	<xsl:template match="/">
		<html>
			<xsl:apply-templates select="PLANETS/PLANET/NAME"/>
		</html>
	</xsl:template>
	
	
	<xsl:template match="PLANET/NAME">
		<p>planet name</p>
	</xsl:template>

だと、

<?xml version="1.0" encoding="UTF-8"?>
<html>
  <p>planet name</p>
  <p>planet name</p>
  <p>planet name</p>
</html>

となるけど、

	<xsl:template match="/">
		<html>
			<xsl:apply-templates select="PLANETS/PLANET/NAME"/>
		</html>
	</xsl:template>
	
	
	<xsl:template match="PLANET/NAMEXXXXXXXXXXXXXXXXXXXX">
		<p>planet name</p>
	</xsl:template>

だと、

<?xml version="1.0" encoding="UTF-8"?>
<html>MercuryVenusEarth</html>

となる。

つまり、StyleSheetの書き方は次のようになるのではないか?

  • でルートが当たる要素を1つだけ書く。
  • selectでルートの中身をびしっと指定。そしてテンプレート側も というようにして1対1で組み合わせる。