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,当 for 循环第一次运行时,它将调用模板,该模板将递归调用自身 10 次。所以我打印了从 001 - 010 开始的数字

下次我运行循环时,我再次打印了 001-010 中的数字,第三次以此类推。但我想要的是记住最后一次计数。假设在第一次迭代中我达到了 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 for-each。从而创建确切数量的 outputB 节点。但这里的问题是在生成的 xml 中维护唯一计数或 id。

谢谢 :)

4

4 回答 4

1

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

于 2012-07-03T12:05:13.357 回答
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 + depth。

于 2012-07-03T10:10:55.443 回答
0

您不会记住 XSLT 中的值,甚至不会在进行过程中累加,除非在非常特殊的情况下。但是,一般情况下,您不需要这样做。

因此,如果您有:

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

那么您就拥有了提供计数所需的一切:

<xsl:value-of select="count(conditiona)"/> // this displays 3
于 2012-07-03T10:00:23.107 回答
0

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

这里有两个关键概念:

  1. 只要其范围需要,就在同一节点上重复模板匹配
  2. 让节点为其下一个兄弟节点启动进程,而不是将根匹配模板应用于所有 B 节点。这样一来,“你在哪里起床?” 关系可以通过传递的参数来维护。这是非正统的,但有效。

代码:

<!-- 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"/>
于 2012-07-03T11:05:51.103 回答