记住for -each循环中最后一次递归调用模板的计数

时间:2012-07-03 09:46:02

标签: xslt xslt-1.0

我有一个XSLT地图,我用它进行一些转换。我的问题是我怎么能记住伯爵1.e;循环运行的次数。例如

<xsl: for each>  // This runs some 3 times

<xsl: call-template > // This call template recursively runs 10 times
<xsl: with- param >
</xsl: call-template >

<xsl: for each>

在上面的示例中,外部for循环运行3次,内部调用模板反复调用自身打印一些东西,假设10次。所以我总共有3 * 10 = 30个周期。

我需要的是假设我有一个初始数字001,当第一次循环运行时,它将调用模板,该模板将递归调用自身10次。所以我从001 - 010

开始打印数字

下次我运行循环时,我第三次再次打印001-010 ans中的数字。但我想要的是记住最后的计数。假设在第一次迭代中我达到了010.所以在第二次迭代中,我将从011开始计数并打印到021。 第三次,我将从022-032开始打印。

但任何人都可以建议我怎么做?我怎么能记住打印已经完成的最后一个值?

还有一件事我实际上仅限于XSLT1.0。这就是我必须像上面的例子一样循环的原因。

这将是一个很好的帮助

我想做的是这样的, 假设我有一个输入xml,

<A>

<B from="123456781" to="123456782">
........
</B>
<B from="123456781" to="123456785">
........
</B>
<B from="123456788" to="123456788">
........
</B>

</A>

在上面的xml中,每个节点B与范围“从 - 到”相关联。我需要创建尽可能多的ouputB节点,因为在给定范围内有数字。我还必须获得创建的每个outputB节点的唯一计数。例如,输出xml可以是,

<root>

<outputB value="123456781" id="001"> // from first B node from="123456781" to="123456782"
<outputB value="123456782" id="002">

<outputB value="123456781" id="003">
<outputB value="123456782" id="004">// from second B node from="123456781" to="123456785"
<outputB value="123456783" id="005">
<outputB value="123456784" id="006">
<outputB value="123456785" id="007">

<outputB value="123456788" id="008">// from third B node from="123456788" to="123456788"

</root>

所以在上面的xsl中,我已经在from和to参数的范围值的基础上递归填充了,而我在每个输入B节点上已经为每个都填充了bu。从而创建确切数量的outputB节点。但这里的问题是在生成的xml中维护唯一计数或id。

谢谢:)

4 个答案:

答案 0 :(得分:1)

XSLT是一种功能语言。你不能用功能语言“记住”事物:没有时间概念,没有过去的事物记忆。您需要根据输入中的某些内容计算输出中的所有内容。

答案 1 :(得分:0)

除非在非常具体的情况下,否则您不会记住XSLT中的值,甚至不会加起来。但是,一般情况下,您不需要。

所以如果你有:

<xsl:for-each select="conditiona">  // This runs some 3 times

然后你就拥有了提供计数所需的一切:

<xsl:value-of select="count(conditiona)"/> // this displays 3

答案 2 :(得分:0)

当您调用模板时,您只需传入“深度”参数。

 <xsl:template Name="x">
   <xsl:param name="depth">

   <xsl:call-template name="x">
     <xsl:with param name="depth" select=="depth+1" />
   </xsl:call-template>
 </xsl:template>

然后你为你的外循环做类似的事情。目前尚不清楚你是如何做这个循环的,但你可以使用position()。然后你想要的数字是position()* 10 +深度。

答案 3 :(得分:0)

这是怎么回事?您可以在this XMLPlayground运行它(请参阅输出源)。它完全避免了for-each(在XSLT中总是最好避免)。

这里有两个关键概念:

  1. 在同一节点上重复模板匹配,只要其范围需要
  2. 让节点启动其后续兄弟的进程,而不是让根匹配模板适用于所有B节点。这样,“你在哪里开始?”通过params可以保持关系。这是非正统的,但有效。
  3. <强>代码:

    <!-- root - kick things off, for each B node -->
    <xsl:template match="/">
        <xsl:apply-templates select='//B[1]' />
    </xsl:template>
    
    <!-- iteration content - B nodes -->
    <xsl:template match='B'>
    
        <!-- recursion params -->
        <xsl:param name='index' select='@from' />
        <xsl:param name='id' select='position()' />
        <xsl:param name='pos' select='position()' />
    
        <!-- output node -->
        <outputB value='{$index}' id='{$id}' />
    
        <!-- now recurse for... -->
        <xsl:choose>
    
            <!-- ...as range requires -->
            <xsl:when test='(@from and @to) and (not($index) or $index &lt; @to)'>
                <xsl:apply-templates select='.'>
                    <xsl:with-param name='index' select='$index + 1' />
                    <xsl:with-param name='id' select='$id + 1' />
                </xsl:apply-templates>
            </xsl:when>
    
            <!-- ...next B node, if there is one -->
            <xsl:when test='following-sibling::B'>
                <xsl:apply-templates select='following-sibling::B[1]'>
                    <xsl:with-param name='id' select='$id + 1' />
                </xsl:apply-templates>
            </xsl:when>
        </xsl:choose>
    
    </xsl:template>
    

    <强>输出:

    <outputBs value="123456781" id="1"/>
    <outputBs value="123456782" id="2"/>
    <outputBs value="123456783" id="3"/>
    <outputBs value="123456781" id="4"/>
    <outputBs value="123456782" id="5"/>
    <outputBs value="123456783" id="6"/>
    <outputBs value="123456784" id="7"/>
    <outputBs value="123456785" id="8"/>
    <outputBs value="123456788" id="9"/>