使用临时值循环遍历xsl中的一组元素

时间:2012-09-25 16:01:43

标签: xml xslt loops

我正在使用XSLT 1.0

假设我有一个xml,它有某些“num”元素,可以在XML文档中的任何位置: -

<elem1>
  <num>24</num>
</elem1>
<elem2>
  <description>
    <num>18</num>
  </description>
</elem2>
<elem3>
  <elem1>
    <num>36</num>
  </elem1>
</elem3>

我想将其转换为: -

<elem1>
  <gcd multiple="4">6</gcd>
</elem1>
<elem2>
  <description>
    <gcd multiple="3">6</gcd>
  </description>
</elem2>
<elem3>
  <elem1>
    <gcd multiple="6">6</gcd>
  </elem1>
</elem3>

现在我有一个模板可以计算两个元素的gcd,如下所示: -

<xsl:template name="gcd">
  <xsl:param name="x"/>
  <xsl:param name="y"/>
  <!-- snipping code to compute gcd that goes here -->
</xsl:template>

鉴于gcd的这个模板,我猜我将不得不做像这样的数字循环: -

<xsl:variable name="global_gcd">
  <xsl:for-each select="//ns0:num">
    <!-- something probably goes here --> 
    <!-- say a temporary value x=0 initially -->
    <!-- and then x = gcd (x, value of current node) -->
  </xsl:for-each>
</xsl:variable>

然后我可以声称在我的模板中使用这个变量“num”来生成所需的“gcd”元素以及属性。我也能这样做。

上面的循环应该是什么样的?如果不是for-each,假设我已经有两个元素的工作gcd模板,我将如何实际计算XML文档中所有“num”元素的gcd?

如果我将所有“num”元素作为兄弟姐妹或其他东西,我想这会容易得多,但遗憾的是我没有。任何两个之间的树关系可能是任意的。我唯一知道的是,它们都有相同的名字。

1 个答案:

答案 0 :(得分:3)

XSLT是一种函数式语言,因此没有可更新变量的概念 - 变量在创建时具有其值,并且该值不能随后更改。如果你必须在纯XSLT中执行此操作,则需要将问题重新表述为递归模板而不是循环

<xsl:template name="gcd">
  <xsl:param name="nodes" />
  <xsl:choose>
    <xsl:when test="count($nodes) = 0">0</xsl:when>
    <xsl:otherwise>
      <xsl:variable name="gcdOfRest">
        <xsl:call-template name="gcd">
          <xsl:with-param name="nodes" select="$nodes[position() > 1]" />
        </xsl:call-template>
      </xsl:variable>
      <!-- existing logic goes here, calculating GCD between number($nodes[1])
           and number($gcdOfRest) -->
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

并调用此模板,将//ns0:num作为nodes参数传递。

但是如果您可以选择编写扩展功能并将其插入,那可能会更有效。