この前、次のようなデータから
<div>
<span>りんご</span>
<span>みかん</span>
<span>バナナ</span>
</div>
<span>りんご</span>
<span>みかん</span>
<span>バナナ</span>
</div>
次のような出力を得るのにposition()関数を使う例を紹介しました.
<fo:block>【りんご,みかん,バナナ】</fo:block>
もしspan以下に<i>や<b>などの要素がないか、あっても無視できる場合、もっと簡単にできます.それは<xsl:value-of>を使用する方法です.
<xsl:template match="div">
<fo:block>
<xsl:if test="span">
<xsl:value-of select="'【'"/>
<xsl:value-of select="span" separator=","/>
<xsl:value-of select="'】'"/>
</xsl:if>
</fo:block>
</xsl:template>
<fo:block>
<xsl:if test="span">
<xsl:value-of select="'【'"/>
<xsl:value-of select="span" separator=","/>
<xsl:value-of select="'】'"/>
</xsl:if>
</fo:block>
</xsl:template>
結果はバッチリ次のようになります.
<fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format">【りんご,みかん,ばなな】</fo:block>
ポイントはセパレータのseparator属性がxsl:value-ofに書けるようになったことです.xsl:value-ofはselectで作られたシーケンスを文字列群として評価して、それらを@separatorで指定した文字列で結合してくれます.ですから、上のxsl:value-ofは、
<xsl:value-of select="('りんご','みかん','ばなな')" separator=","/>
ということなのです.このxsl:value-ofの機能はstring-join()関数に似ています.string-joinもセパレータを指定できますが、こちらはテキストノードでなく、xs:stringを返します.xsl:value-ofに@separator属性が追加されたのはXSLT2.0からですが、注意も必要です.
<xsl:value-of select="span"/>
とすれば、"りんご みかん バナナ"がテキストノードして返ります.つまり@separarorの既定値は なのです.あまり@select属性にシーケンスを生成するXPath式を書くことはないと思いますが、覚えておいたほうが良いでしょう.
<xsl:value-of select="('りんご','みかん','ばなな')" separator=""/>
と明示的にseparatorを空文字列にすれば、
"りんごみかんバナナ"
を得ることができます.