XSLT2.0から取り入れられたsequenceの概念、xsl:templateもxsl:variableもXSLT2.0では、そのコンテンツは、sequence-constructorとして定義されます.
<xsl:variable name="..." as="...">
<!-- sequence-constructor -->
</xsl:variable>
<!-- sequence-constructor -->
</xsl:variable>
<xsl:template name="..." as="...">
<!-- sequence-constructor -->
</xsl:template>
<!-- sequence-constructor -->
</xsl:template>
sequenceを記述するときは"(",")"を使う.例えばxs:integer*として(1,2,3)と書ける.
いや、そうは言っても、xsl:templateなんてほとんど今までどおり使えます.xsl:variableだって、いちいちxsl:sequenceを使わなくたってかける場合があります.sequenceの恩恵ってなんなのか?そう思ったときがありました.
的確な答えを持っているわけではありませんが、sequenceは非常に便利に使えるときがあります.
例えばスタイルシートからのメッセージの出力.みなさんはどのようにコーディングされておられるでしょうか?なんらかの理由で、エラーメッセージを出して終了するとき、私はテンプレートの該当箇所にそのまま<xsl:message>を書くのが普通でした.例えば以下のようなコードです.しかしこれでは、仕様書にメッセージ一覧を書くとき大変です.メッセージ番号の管理もメッセージ本体の記述を集中させないと困ります.
<xsl:message>
<xsl:text>[Document Check 100W] The part level element contains attribute toc='no'. Reference file='</xsl:text>
<xsl:value-of select="@ohref"/>
<xsl:text>' navtitle='</xsl:text>
<xsl:value-of select="@navtitle"/>
<xsl:text>' file='</xsl:text>
<xsl:value-of select="@xtrf"/>
<xsl:text>'.</xsl:text>
</xsl:message>
<xsl:text>[Document Check 100W] The part level element contains attribute toc='no'. Reference file='</xsl:text>
<xsl:value-of select="@ohref"/>
<xsl:text>' navtitle='</xsl:text>
<xsl:value-of select="@navtitle"/>
<xsl:text>' file='</xsl:text>
<xsl:value-of select="@xtrf"/>
<xsl:text>'.</xsl:text>
</xsl:message>
私はこんなふうにsequenceをつかってやってみました.メッセージは次のように集中して1つのファイルにまとめて書きます.
<xsl:variable name="mes100" as="xs:string">
<xsl:text>[Document Check 100W] The part level element contains attribute toc='no'. Reference file='%ohref' navtitle='%navtitle' file="%xtrf'.</xsl:text>
</xsl:variable>
<xsl:text>[Document Check 100W] The part level element contains attribute toc='no'. Reference file='%ohref' navtitle='%navtitle' file="%xtrf'.</xsl:text>
</xsl:variable>
すこし手間ですが、次のようなtemplateとfunctionを準備します.
<!-- メッセージを出力して処理継続 -->
<xsl:template name="warningContinue">
<xsl:param name="prmMes" required="yes" as="xs:string"/>
<xsl:message terminate="no"><xsl:value-of select="$prmMes"/></xsl:message>
</xsl:template>
<xsl:template name="warningContinue">
<xsl:param name="prmMes" required="yes" as="xs:string"/>
<xsl:message terminate="no"><xsl:value-of select="$prmMes"/></xsl:message>
</xsl:template>
<!-- backslashをslashに変換 -->
<xsl:function name="tmf:bsToSlash" as="xs:string">
<xsl:param name="prmStr" as="xs:string"/>
<xsl:sequence select="translate($prmStr,'\','/')"/>
</xsl:function>
<xsl:function name="tmf:bsToSlash" as="xs:string">
<xsl:param name="prmStr" as="xs:string"/>
<xsl:sequence select="translate($prmStr,'\','/')"/>
</xsl:function>
<!-- 正規表現のエスケープ文字back-slashを避けて文字列を置換 -->
<xsl:function name="tmf:safeReplace" as="xs:string">
<xsl:param name="prmStr" as="xs:string"/>
<xsl:param name="prmSrc" as="xs:string"/>
<xsl:param name="prmDst" as="xs:string"/>
<xsl:sequence select="replace($prmStr,$prmSrc,tmf:bsToSlash($prmDst))"/>
</xsl:function>
<xsl:function name="tmf:safeReplace" as="xs:string">
<xsl:param name="prmStr" as="xs:string"/>
<xsl:param name="prmSrc" as="xs:string"/>
<xsl:param name="prmDst" as="xs:string"/>
<xsl:sequence select="replace($prmStr,$prmSrc,tmf:bsToSlash($prmDst))"/>
</xsl:function>
<!-- sequenceを使って文字列を置換 -->
<xsl:function name="tmf:replace" as="xs:string">
<xsl:param name="prmStr" as="xs:string"/>
<xsl:param name="prmSrc" as="xs:string+"/>
<xsl:param name="prmDst" as="xs:string+"/>
<xsl:function name="tmf:replace" as="xs:string">
<xsl:param name="prmStr" as="xs:string"/>
<xsl:param name="prmSrc" as="xs:string+"/>
<xsl:param name="prmDst" as="xs:string+"/>
<xsl:variable name="firstResult" select="tmf:safeReplace($prmStr,$prmSrc[1],$prmDst[1])" as="xs:string"/>
<xsl:choose>
<xsl:when test="exists($prmSrc[2]) and exists($prmDst[2])">
<xsl:sequence select="tmf:replace($firstResult,subsequence($prmSrc,2),subsequence($prmDst,2))"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="$firstResult"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:choose>
<xsl:when test="exists($prmSrc[2]) and exists($prmDst[2])">
<xsl:sequence select="tmf:replace($firstResult,subsequence($prmSrc,2),subsequence($prmDst,2))"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="$firstResult"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
ここまで準備すると先ほどの<xsl:message>は次のように書くことができます.
<xsl:call-template name="warningContinue">
<xsl:with-param name="prmMes"
select="tmf:replace($mes100,
('%ohref','%navtitle','%xtrf'),
(@ohref,@navtitle,@xtrf))"/>
</xsl:call-template>
<xsl:with-param name="prmMes"
select="tmf:replace($mes100,
('%ohref','%navtitle','%xtrf'),
(@ohref,@navtitle,@xtrf))"/>
</xsl:call-template>
結構sequenceを使ってスマートにかけると思いませんか?
私は今ではこの記法に統一してコーディングするようにしています.なおtmf:replaceの第3パラメータは、xs:string+ですが、XSLTプロセッサがattribute()+をxs:string+にキャストしてくれます.
また、sequenceは可変長の1次元の表のようにも使えます.例えば、月の番号から英語の月の綴りを求めるテンプレート.XSLT1.0なら.次のように書いたでしょう.
<xsl:template name="numberToMonth">
<xsl:param name="prmMonth" select="0"/>
<xsl:choose>
<xsl:when test="$prmMonth=1">
<xsl:value-of select="'Jan'"/>
</xsl:when>
...
<xsl:param name="prmMonth" select="0"/>
<xsl:choose>
<xsl:when test="$prmMonth=1">
<xsl:value-of select="'Jan'"/>
</xsl:when>
...
<xsl:when test="$prmMonth=12">
<xsl:value-of select="'Dec'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'???'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:value-of select="'Dec'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'???'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
でもXSLT2.0ならもっと簡単にいけますよ.次を御覧ください.
<xsl:variable name="monthEn" as="xs:string+" select="('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')"/>
<xsl:function name="tmf:numberToMonth" as="xs:string">
<xsl:param name="prmMonth" as="xs:integer"/>
<xsl:choose>
<xsl:when test="($prmMonth ge 1) and ($prmMonth le count($monthEn))">
<xsl:sequence select="$monthEn[$prmMonth]"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="'???'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:param name="prmMonth" as="xs:integer"/>
<xsl:choose>
<xsl:when test="($prmMonth ge 1) and ($prmMonth le count($monthEn))">
<xsl:sequence select="$monthEn[$prmMonth]"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="'???'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
いかがでしょうか?私の使っているのはこれくらいですが、もっといろいろと使えると思います.応用を考えると楽しくなりますね.