1

我正在使用 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 模板,我猜我将不得不像这样遍历 num 元素:-

<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”元素作为兄弟姐妹或其他东西,这会容易得多,但不幸的是我没有。其中任何两个之间的树关系可能是任意的。我唯一知道的是,他们都有相同的名字。

4

1 回答 1

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参数传递。

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

于 2012-09-25T16:36:10.110 回答