XSLの変数とそのスコープについて
XSLの変数には2つある。paramとvariable
variableは変数なんだけど、どっちかというと定数に近い概念で一度設定すると上書きができない。
variable
- 上書きができない
- xsl:stylesheetの要素に記述することができて、その場合はグローバル変数になる
param
- テンプレート呼び出し時に関数のようにデフォルト値宣言できる
<xsl:apply-templates select="foo"> <xsl:with-param name="counter" select="$count+1"/> </foo> <xsl:templates match="foo"> <xsl:param name="counter"/><!-- この時点で↑から呼び出された場合は$counter = $count+1が入っている --> <xsl:value-of select="$counter"/> </xsl:templates>
種類
変数には、2つのものがある。1つはリテラル(普通の文字列)で、もう一つはXML要素セットである。
要素セット
要素として変数を格納することができる。
その結果がリテラルとして評価されることもある。たとえば属性を選んだ場合だ。
<root documenttype="html"> <PLANET> <NAME>Mercury</NAME> </PLANET> <PLANET> <NAME>Venus</NAME> </PLANET> <PLANET class="earth"> <NAME>Earth</NAME> </PLANET> </root>
というXMLに対して、
<xsl:variable name="foo" select="/root/@documenttype"/>
とした場合は、リテラル'html'が$fooに入る。
しかし、
<xsl:variable name="foo" select="/root/PLANET"/>
とした場合、3つの
使い方
単純に
<xsl:value-of select="$foo"/>
でリテラルにアクセスできる。
要素集合へのアクセスは展開して使う。
<xsl:for-each select="$foo"> <xsl:apply-templates select="."/> </xsl:for-each>
更に、おまけ。elementの引数として使いたい場合などは中カッコで囲む。
<xsl:element name="{$topictype}">foo</xsl:element>
何でもかんでも中カッコで囲うとエラーが出る。たとえば、value-ofで変数を使用する際には中カッコで囲んではいけない。
変数のスコープ
ローカル変数は、その宣言の親要素にはスコープが及ばない。
これは結構難解な問題を与えてて、普通のプログラミングのように上の方で変数をセットする際に、if分岐がほとんど使えないことを意味する。
たとえば、こういうことをしても、意味が無い。
<xsl:template match="/root"> <xsl:if test="$foo='bar'"> <xsl:variable name="FOO" select="'VAR'"/> </xsl:if>
なぜなら、$FOOはそのIFスコープ内でしか有効でないからだ。
更にいうと、xsl:ifは
そこで、こういう感じにする
<xsl:stylesheet ...> <xsl:variable name="foo" select="'bar'"/> <xsl:variable name="FOO"> <xsl:if test="$foo='bar'">BAR</xsl:if> </xsl:variable>