我有一个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功能或我可以设置的其他全局对象?
如果您对我想要这样做的原因感兴趣,请在下面更详细地解释我的问题和我使用的解决方案:
这是我最终使用的解决方案:
...
<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语句很复杂,难以阅读。也许你有一个更好的解决方案,不需要可变变量?
答案 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所说的完全功能的效果 - (除非你做了奇怪的扩展工作)你可以通过将逻辑应用于输入来决定第一次是否合适。此外,您可以访问模板中的上下文节点,以便了解它的调用位置。