基于输出树的XSLT条件

时间:2015-04-23 09:13:52

标签: xslt tree

我曾经在我的XSLT中拥有基于输入中节点树的条件。但我想根据输出做到这一点。有什么办法吗?

以下是一个例子。

输入:

<top>
    <a>
        <z>
            <item>
                <id>4</id>
            </item>
            <item>
                <id>5</id>
            </item>
        </z>
    </a>
</top>

期望的输出:

<thing>
    <upper>
        <a>
            <z>
                <item>
                    <id>upper-4</id>
                </item>
                <item>
                    <id>upper-5</id>
                </item>
            </z>
        </a>
    </upper>
    <lower>
        <a>
            <z>
                <item>
                    <id>lower-4</id>
                </item>
                <item>
                    <id>lower-5</id>
                </item>
            </z>
        </a>
    </lower>
</thing>

请注意,树本质上是向下复制的,唯一的变化是id节点的值已被修改,具体取决于我们是upper还是{{1}树木。

我目前的XSLT:

lower

这是一个简化示例,树中有许多节点<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xsl:template match="top"> <thing> <upper> <xsl:apply-templates /> </upper> <lower> <xsl:apply-templates /> </lower> </thing> </xsl:template> <xsl:template match="id"> <!-- I want to prepend this with "upper" or "lower" depending which block we're in --> <xsl:value-of select="text()" /> </xsl:template> <!-- identity template --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> </xsl:stylesheet> a之间,z节点可以显示item下的各种深度。< / p>

最初我的条件看起来像a,但显然不起作用,因为ancestor::upper在输出中,而不是输入。

我还考虑尝试传递一个参数来说明我们是否在upperupper,但这意味着更新每个模板(包括身份模板)拥有一个参数,并将其传递给它调用的任何模板。如果可能的话,我真的想避免这种情况。

因此,如果有一种方法可以将变量传递给被调用的模板而无需声明变量,那就行了。或者,如果我可以编写一个条件来查看调用我们的模板或我们上面的树中的输出,那就可以了。或者还有其他方法吗?

请注意,我使用的是Saxon处理器,因此我可以使用特定于此的功能(例如,如果有帮助,我可以调用某些java)。

感谢。

1 个答案:

答案 0 :(得分:0)

以下是使用带有XSLT 2.0的隧道参数的解决方案:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs">

    <!-- identity template -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="top">
        <thing>
            <upper>
                <xsl:apply-templates>
                  <xsl:with-param name="tree-id" tunnel="yes" select="'upper-'"/>
                </xsl:apply-templates>
            </upper>
            <lower>
                <xsl:apply-templates>
                  <xsl:with-param name="tree-id" tunnel="yes" select="'lower-'"/>
                </xsl:apply-templates>
            </lower>
        </thing>
    </xsl:template>

    <xsl:template match="id">
        <xsl:param name="tree-id" tunnel="yes"/>
        <xsl:copy>
          <!-- I want to prepend this with "upper" or "lower" depending which block we're in -->
          <xsl:value-of select="concat($tree-id, .)" />
        </xsl:copy>
    </xsl:template>


</xsl:stylesheet>