テンプレートと変数(3)

テンプレートの例ですが、変数の方はありきたりでしたのでちょっと極端なものを書いてみました.

次のテンプレートは、戻り値がitem()*で、いろいろな型のインスタンスを返します.

    <xsl:template name="generateSeq" as="item()*">
        <xsl:sequence select="'ABC'"/>
        <xsl:sequence select="1"/>
        <xsl:sequence select="3.141567"/>
        <xsl:sequence select="true()"/>
        <xsl:element name="element">
            <xsl:attribute name="att" select="'some value'"/>
            <xsl:comment select="'Comment example'"/>
            <xsl:processing-instruction name="PI" select="'Processing instruction example'"/>
            <xsl:text>Text node</xsl:text>
        </xsl:element>
    </xsl:template>

これを出力に書き込んでみます.

    <xsl:template match="/" as="item()*">
        <root>
            <xsl:call-template name="generateSeq"/>
        </root>
    </xsl:template>

すると次のようなXMLが出来上がります.

<?xml version="1.0" encoding="UTF-8"?>
<root>ABC 1 3.141567 true<element att="some value"><!--Comment example--><?PI Processing instruction example?>Text node</element>
</root>

なんだみんなノードになるじゃないか?と思われたかもしれません.そのとおりです.いくら様々な型のインスタンスをgenerateSeqテンプレートが返していても、出力はXMLですからそれなりにシリアライズされてしまうのです.

次のようにすると本当にgenerateSeqテンプレートが様々な型のインスタンスを返しているか確認できます.

    <xsl:template match="/" as="item()*">
        <xsl:variable name="seq" as="item()*">
            <xsl:call-template name="generateSeq"/>
        </xsl:variable>
        <root>
            <xsl:for-each select="$seq">
                <xsl:sequence select="ahf:dispItem(.)"/>
                <xsl:if test=". instance of element()">
                    <xsl:for-each select="node()|attribute()">
                        <xsl:sequence select="ahf:dispItem(.)"/>
                    </xsl:for-each>
                </xsl:if>
            </xsl:for-each>
        </root>
    </xsl:template>

    <xsl:function name="ahf:dispItem" as="text()*">
        <xsl:param name="item" as="item()"/>
        <xsl:choose>
            <xsl:when test="$item instance of xs:string">
                <xsl:value-of select="'Instace of xs:string =',xs:string($item)"/>
            </xsl:when>
            <xsl:when test="$item instance of xs:integer">
                <xsl:value-of select="'Instace of xs:integer =',xs:integer($item)"/>
            </xsl:when>
            <xsl:when test="$item instance of xs:decimal">
                <xsl:value-of select="'Instace of xs:decimal =',xs:decimal($item)"/>
            </xsl:when>
            <xsl:when test="$item instance of xs:boolean">
                <xsl:value-of select="'Instace of xs:boolean =',xs:boolean($item)"/>
            </xsl:when>
            <xsl:when test="$item instance of element()">
                <xsl:value-of select="'Instace of element() name=',name($item)"/>
            </xsl:when>
            <xsl:when test="$item instance of attribute()">
                <xsl:value-of select="'Instace of attribute() name=',name($item),'value=',string($item)"/>
            </xsl:when>
            <xsl:when test="$item instance of comment()">
                <xsl:value-of select="'Instace of comment() value=',string($item)"/>
            </xsl:when>
            <xsl:when test="$item instance of processing-instruction()">
                <xsl:value-of select="'Instace of processing-instruction() name=',name($item), 'value=',string($item)"/>
            </xsl:when>
            <xsl:when test="$item instance of text()">
                <xsl:value-of select="'Instace of text() value=',string($item)"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="'Other stuff!'"/>
            </xsl:otherwise>
        </xsl:choose>
        <xsl:text>&#x0A;</xsl:text>
    </xsl:function>

"$x instance of Y"は、$xがYの型のインスタンスである場合true()を返してくれます.これで生成されたシーケンスの個々の型を調べることができます.

3.10.1 Instance Of

The boolean operator instance of returns true if the value of its first operand matches the SequenceType in its second operand, according to the rules for SequenceType matching; otherwise it returns false.

このテンプレートは次のようなXMLを生成します.

<?xml version="1.0" encoding="UTF-8"?>
<root>Instace of xs:string = ABC
Instace of xs:integer = 1
Instace of xs:decimal = 3.141567
Instace of xs:boolean = true
Instace of element() name= element
Instace of attribute() name= att value= some value
Instace of comment() value= Comment example
Instace of processing-instruction() name= PI value= Processing instruction example
Instace of text() value= Text node
</root>

実際のテンプレートでこのようないろいろな型のインスタンスを生成することはまずないでしょう.しかしXSLT 1.0とはまったく異なり、XSLT 2.0のテンプレートはノードだけでなく様々な型のインスタンスを返せることを知っていただきたいと思います.