如何计算XSLT中模板的调用次数?
我有一个XSLT脚本,每次调用模板时,我都希望按顺序对内容进行编号。所以它的一个非常简短的版本看起来有点像:如何计算XSLT中模板的调用次数?,xslt,Xslt,我有一个XSLT脚本,每次调用模板时,我都希望按顺序对内容进行编号。所以它的一个非常简短的版本看起来有点像: <xsl:call-template name="insertHeader" /> <xsl:for-each ...> <xsl:call-template name="insertHeader" /> ... </xsl:for-each> <xsl:call-template name="insertHead
<xsl:call-template name="insertHeader" />
<xsl:for-each ...>
<xsl:call-template name="insertHeader" />
...
</xsl:for-each>
<xsl:call-template name="insertHeader" />
<xsl:template name="insertHeader>
This is item number <xsl:value-of select="$numberOfInvocations />
</xsl:template>
...
显然,$numberOfInvocations这个东西不起作用,在XSLT中,您不能增加一个全局计数器变量,这在过程语言中似乎是一种明显的方法。我想第一次调用模板时打印出1,第二次打印出2,等等。我应该怎么做?这在XSLT中甚至可以实现吗
谢谢:)
编辑:所以有一些评论认为这还不够明确。我要做的是在(HTML)输出中标记一系列表。我看到的最明显的方法是调用一个函数(您可能知道我在这里不是XSLT向导),该函数每次都会自动递增数字。我认为这看起来如此困难的原因是XSLT本身定义了这些表出现的位置,而不是输入
这些额外的信息可能没有多大用处,因为Dimitre的回答让人觉得这是行不通的。谢谢:)您是否尝试了
position()
功能
以下是我的一个项目中的一个片段,可能会有所帮助:
<xsl:variable name="count" select="count(../ownedParameter[@name])" />
$<xsl:value-of select="@name" />=null
<xsl:if test="$count > 1 and position()!=last()">,</xsl:if>
$=null
,
您应该能够执行以下操作:
<xsl:template name="insertHeader>
This is item number <xsl:value-of select="position()" />
</xsl:template>
您可以在XSLT1.0中使用递归模板来实现这一点
但是,这是一个很大的但是,模板的名称,insertHeader
,让我认为您正在尝试做一些事情,这些事情应该以完全不同的方式在XSLT中解决
你的意图是什么?也许我们可以为您提供一个更为XSLTish的解决方案。我相信您可以通过使用xsl:number
和在@count
属性中使用适当的模式来解决您的问题(如果我认为是…)
XSLT1.0:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:call-template name="insertHeader"/>
</xsl:template>
<xsl:template name="insertHeader">
<xsl:param name="num" select="1"/>
<xsl:value-of select="concat('This is item number ', $num, '
')"/>
<xsl:if test="$num < 10">
<xsl:call-template name="insertHeader">
<xsl:with-param name="num" select="$num + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
This is item number 1
This is item number 2
This is item number 3
This is item number 4
This is item number 5
This is item number 6
This is item number 7
This is item number 8
This is item number 9
This is item number 10
在XSLT等函数式语言中,没有定义“计算顺序”
因此,试图按“及时”的顺序对“计算”进行编号是没有意义的,如果尝试,往往会产生令人惊讶的结果
例如,没有任何东西限制
以与所选节点列表中节点的文档顺序相同的时间顺序应用模板。这些工作可以并行进行,也就是说可以按任何顺序进行
许多XSLT处理器执行延迟求值
,这意味着某条XSLT指令只有在真正需要时才进行求值,而不是根据其在XSLT样式表中的文本顺序进行求值。通常有些指令根本没有执行
有时优化器会执行给定的XSLT指令两次,因为它决定放弃第一个结果以优化空间利用率
可以使用递归(通常)和连续传递样式CP或单子(更具体地说)生成请求的编号
FXSL库(对于XSLT 1.0版本1和XSLT 2.0版本2)包含可用于组织此类编号的模板:foldl、foldr、iter、iterUntil、scanl、scanr等
只要精确定义了问题(不是当前情况),就可以生成这样的编号,但要注意结果必须在模板之外计算numberOfInvocations
,并将其作为参数给出。
在每个
的内,可以使用position()
检索迭代编号
在下面的样式表中,我向insertHeader
添加了一个pos
参数
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:s="uri:sample">
<xsl:output type="text"/>
<s:sample>
<table>Table A</table>
<table>Table B</table>
</s:sample>
<xsl:template match="/">
<xsl:apply-templates select="document('')//s:sample"/>
</xsl:template>
<xsl:template match="s:sample">
<xsl:call-template name="insertHeader">
<xsl:with-param name="pos" select="1"/>
</xsl:call-template>
<xsl:variable name="node-set" select="table"/>
<xsl:variable name="node-set-count" select="count($node-set)"/>
<xsl:for-each select="$node-set">
<xsl:call-template name="insertHeader">
<xsl:with-param name="pos" select="1+position()"/>
</xsl:call-template>
<xsl:value-of select="."/>
<xsl:text>
</xsl:text>
</xsl:for-each>
<xsl:call-template name="insertHeader">
<xsl:with-param name="pos" select="2+$node-set-count"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="insertHeader">
<xsl:param name="pos"/>
<xsl:text>This is item number </xsl:text><xsl:value-of select="$pos" />
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
查看树结构并从上到下对其进行编号
xslt:
来自xml:
e
ex
exa
示例
变成:
1。e
2。ex
3。exa
4。示例
更多信息:我认为(我可能错了,我不是xslt方面的专家)position()只给出了for-each循环中的位置;它不会一直在循环之外计数吗?我想你是对的;只是在我的回答中加上了这个。您仍然可以使用position()作为参数调用模板。@彼得:没错。请参阅我的答案,它也使用position()
,但作为模板的参数提供。正如您所写的,变量在声明性范例中的含义不同。你需要(而且大多数情况下你可以)声明这个数字背后的逻辑。如果您被锁定,请提供输入示例和所需输出以帮助您。好问题(+1)。详细解释见我的答案。@Dimitre:+1很好的解释。此外,还可以使用xsl:number
或fn:count
声明相对于上下文节点文档顺序的数字。感谢您的回答,我认为这非常清楚地表明,我想做的事情无法正常工作(即,如果不能完全从输入确定它们在输出中的位置,则无法根据它们在输出中的位置自动编号)@Peter:你的问题是关于“计算模板调用次数”。这与“根据输出中的位置自动编号”非常不同。实际上,可以根据节点在输出中的位置对节点进行编号。您将需要两步转换,其中第二步将进行编号。如果你对此感兴趣,请问一个新问题。@Peter:首先,一切都是由输入源决定的,无论是只有一个、多个、内联到样式表中,还是伪随机性(如果你考虑到seed)(关于幺半群,我必须三思)。你不愿意,只是因为你不能。最后,两步变换是否具有扩展性
$ xsltproc 3663349.xslt 3663349.xslt
This is item number 1
This is item number 2
Table A
This is item number 3
Table B
This is item number 4