如何计算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

我有一个XSLT脚本,每次调用模板时,我都希望按顺序对内容进行编号。所以它的一个非常简短的版本看起来有点像:

<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, '&#x0a;')"/>
    <xsl:if test="$num &lt; 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