我正在使用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”元素作为兄弟姐妹或其他东西,我想这会容易得多,但遗憾的是我没有。任何两个之间的树关系可能是任意的。我唯一知道的是,它们都有相同的名字。
答案 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
参数传递。
但是如果您可以选择编写扩展功能并将其插入,那可能会更有效。