如何计算XSLT中模板的调用?

时间:2010-09-07 22:57:53

标签: xslt

我有一个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,第二次打印出来,等等。我应该怎样做呢?这在XSLT中是否可以远程实现?

谢谢:)

编辑:所以有一些评论说明这​​个问题没有明确定义。我想要做的是在(HTML)输出中标记一系列表。我看到这样做的最明显的方法是调用一个函数(你可能会告诉我这里不是一个XSLT向导),每次都会自动增加数字。我认为这看起来很难的原因是因为XSLT本身定义了这些表的出现而不是输入。

这个额外的信息可能没那么多用,因为Dimitre的回答让它听起来更像是永远不会起作用。无论如何,谢谢:)

5 个答案:

答案 0 :(得分:6)

在XSLT等函数式语言中,没有定义“计算顺序”

因此,试图通过“及时”排序对“计算”进行编号是没有意义的,如果尝试通常会产生令人惊讶的结果。

例如,没有任何限制<xsl:apply-templates>按照与所选节点列表中节点的文档顺序相同的顺序应用模板。这些可以并行完成,意味着以任何顺序

许多XSLT处理器执行 lazy evaluation,这意味着某些XSLT指令只会在真正需要时进行评估,而不是根据XSLT样式表中的文本顺序进行评估。通常一些指令根本不会被执行。

有时优化器会执行给定的XSLT指令 两次,因为它决定放弃第一个结果以优化空间利用率。

使用递归(通常)和延续传递样式 CPS或<<生成 em> Monads (更具体地说)。

FXSL库(版本1 - 适用于XSLT 1.0和版本2 - 适用于XSLT 2.0)包含可用于组织此类编号的模板:foldl,foldr,iter,iterUntil, scanl,scanr,...等等。

无论何时精确定义问题(当前情况不是这样),都可以产生这样的编号,但会对结果发出警告

答案 1 :(得分:4)

您是否尝试过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>

您应该可以执行以下操作:

<xsl:template name="insertHeader>
    This is item number <xsl:value-of select="position()" />
</xsl:template>

......至少我认为这会奏效。如果没有,您可能需要将count()调用for-each块。

答案 2 :(得分:2)

您可以使用递归模板在XSLT 1.0中执行此操作。

但是,这是一个很大但是,模板的名称insertHeader让我觉得你正在尝试做一些应该完全解决的问题XSLT中的不同方式。

你对此有何意图?也许我们可以为您提供更多XSLTish解决方案。我相信你可以通过使用xsl:number并在@count属性中使用适当的模式来解决你的问题(如果它是我认为的那个......)。

XSLT 1.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

答案 3 :(得分:2)

numberOfInvocations必须在模板外计算并作为参数给出。 在for-each内,您可以使用position()检索迭代编号。

在以下样式表中,我向pos添加了insertHeader参数。

<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>

注意:示例文档嵌入在样式表中,因此请将样式表应用于自身以查看结果。

$ 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

答案 4 :(得分:0)

<xsl:number />查看树形结构并从上到下对其进行编号

XSLT:<h2><xsl:number />.<xsl:value-of select="/t/tittel" /></h2>

来自xml:
<tittel>e</tittel>
<tittel>ex</tittel>
<tittel>exa</tittel>
<tittel>example</tittel>

变成:

<h2>1. e</h2>
<h2>2. ex</h2>
<h2>3. exa</h2>
<h2>4. example</h2>

更多信息:http://www.xml.com/pub/a/2002/12/11/autocount.html