我有一个 XSLT block ,可以在整个转换中多次应用。但我希望它只在第一次应用时实际运行,它应该被跳过所有后续时间。我该怎么做呢?
例如,这是我想做的事情:
在样式表中,我定义了一个全局变量:
<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 功能或其他全局对象吗?
如果您对我为什么要这样做感兴趣,下面是对我的问题和我使用的解决方案的更详细说明:
输出是 WordML 格式的报告。
(命名为 该节点 )。有些,但不是
所有这些节点都需要
显示在输出中。节点
仅当 XPATH 时才应显示
毛逻辑是真的(hairyLogic 显然很长并且
复杂的)。
一个子节点)。在输入中,所有
相同类型的节点将
总是被组合在一起。在里面
输出,所有相同的节点
类型应归入一个
该类型的特定标题(有
每个应该只有一个标题
类型)。
这是我最终使用的解决方案:
...
<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 语句复杂且难以阅读。也许您有一个不需要可变变量的更好的解决方案?
最佳答案
我建议使用匹配模板而不是命名模板,因为它更多,好吧,XSLT 等价于 pythonic ? Xslt-y?我想您会发现在该处理方法中可以更轻松地解决问题。
如果你因为一些未知的需求而坚持使用命名模板,你可能会发现如果你重构你的逻辑以便于检测第一个实例,你将完全简化你的逻辑。
您能否澄清为什么您无法检测到何时需要第一个实例?我们可能可以帮助制作一个 xpath 表达式,让您确实想要。例如。
<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 所说的那样,完全可以发挥作用——(除非你正在做奇怪的扩展工作)你可以通过对输入应用逻辑来决定第一次何时合适。此外,您可以访问模板中的上下文节点,以便知道从哪里调用它。
关于xslt - 在 XSLT 中,我可以只运行一次模板吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1344120/