在XSLT中,我可以只运行一次模板

时间:2009-08-27 22:38:54

标签: xslt

我有一个XSLT块,可以在整个转换过程中多次应用。但我希望它实际上只在第一次应用时运行,它应该被忽略所有的次数。我该怎么做?

作为一个例子,这是我想要做的事情: 在样式表中,我定义了一个全局变量:

<xsl:variable name="run_once" select="0"/>

然后我有一个多次调用的模板:

<xsl:template name="some_template">
    <xsl:if test="$run_once != 1">
        <xsl:variable name="run_once" select="1"/>
        <xsl:text>THIS TEXT SHOULD APPEAR ONLY ONCE</xsl:text>
    </xsl:if>
</xsl:template>

这当然不起作用,因为变量不能改变,只能重载。因此,一旦some_template退出,$ run_once再次为0,并且每次调用模板时都会应用文本。 是否有某种类型的ifdef功能或我可以设置的其他全局对象?

如果您对我想要这样做的原因感兴趣,请在下面更详细地解释我的问题和我使用的解决方案:

  • 我的输入是原始XML中的数据,我的 output是WordML格式的报告。
  • 在输入中我有一系列节点 (命名为 theNode )。一些,但不是 所有这些节点都需要 显示在输出中。节点 应该只在XPATH中显示 hairyLogic 是真的(hairyLogic显然很长而且 复合物)。
  • theNode还有一个类型(存储在 一个子节点)。在输入中,全部 相同类型的节点将 总是被组合在一起。在里面 输出,所有的节点都是一样的 类型应归入a 该类型的特定标题(那里 每个应该只有一个标题 类型)。

这是我最终使用的解决方案:

...
<xsl:apply-templates select="theNode[hairyLogic]"/>
...

<xsl:template match="theNode">
    <xsl:if test="count(preceding-sibling::theNode[type = current()/type and hairyLogic])=0">
        <xsl:choose>
            <xsl:when test="type = 'TYPE1a' or type = 'TYPE1b'">
                <xsl:call-template name="TYPE1Heading"/>
            </xsl:when>
            <xsl:when test="type = 'TYPE2'">
                <xsl:call-template name="TYPE2Heading"/>
            </xsl:when>
        </xsl:choose>
    </xsl:if>
    ...
</xsl:template>

我选择使用命名模板作为标题,因为它们包含不依赖于输入XML中任何数据的基本WordML。

我不喜欢这个解决方案,因为hairyLogic被重复,if语句很复杂,难以阅读。也许你有一个更好的解决方案,不需要可变变量?

2 个答案:

答案 0 :(得分:2)

因为XSLT是纯函数式语言,所以可以设置 no 全局变量。

您必须选择在何种情况下调用some_template模板。如果你只想打电话一次,那么只打一次电话。

答案 1 :(得分:2)

我建议在命名模板上使用匹配模板,因为它更像是pythonic的XSLT等价物? XSLT-Y?我想你会发现你可以通过这种处理方法更容易地解决问题。

如果由于某些未知要求而坚持使用命名模板,您可能会发现,如果您重构逻辑以便于检测第一个实例,那么您将完全简化逻辑。

您能否澄清为何无法检测何时需要第一个实例?我们可以帮助制作一个可以让你想要的xpath表达式。 E.g。

<xsl:template name="some_template">
    <xsl:variable name="EXPRESSION" select=".[somelogic='true']"/>
    <xsl:if test="$EXPRESSION">
        <xsl:text>THIS TEXT SHOULD APPEAR ONLY ONCE</xsl:text>
    </xsl:if>
</xsl:template>

由于XSLT是确定性的 - 这是Greg所说的完全功能的效果 - (除非你做了奇怪的扩展工作)你可以通过将逻辑应用于输入来决定第一次是否合适。此外,您可以访问模板中的上下文节点,以便了解它的调用位置。