需要在递归xsl函数中使用xpath按xml节点子集的顺序进行过滤
我有一组xml节点,它们具有相同的节点名称,但有一个区分它们的属性,还有一个amount属性:需要在递归xsl函数中使用xpath按xml节点子集的顺序进行过滤,xml,xslt,xpath,Xml,Xslt,Xpath,我有一组xml节点,它们具有相同的节点名称,但有一个区分它们的属性,还有一个amount属性: <exampleNode typeOfnode="1" amount="100"/> <exampleNode typeOfnode="1" amount="540"/> <exampleNode typeOfnode="2" amount="200"/> <exampleNode typeOfnode="2" amount="200"/> <ex
<exampleNode typeOfnode="1" amount="100"/>
<exampleNode typeOfnode="1" amount="540"/>
<exampleNode typeOfnode="2" amount="200"/>
<exampleNode typeOfnode="2" amount="200"/>
<exampleNode typeOfnode="3" amount="10"/>
<exampleNode typeOfnode="3" amount="1"/>
<exampleNode typeOfnode="3" amount="110"/>
<exampleNode typeOfnode="3" amount="110"/>
<exampleNode typeOfnode="4" amount="110"/>
我使用一个递归模板来计算数量之和,但只想对特定类型的节点进行计算。下面是我用来调用模板的代码:
<xsl:call-template name="addition">
<xsl:with-param name="currentValue">0</xsl:with-param>
<xsl:with-param name="counter"><xsl:value-of select="count(//exampleNode[@typeOfnode= '1'])"/></xsl:with-param>
<xsl:with-param name="typeOfnode">1</xsl:with-param>
</xsl:call-template>
<xsl:template name="addition">
<xsl:param name="currentValue"/>
<xsl:param name="counter"/>
<xsl:param name="typeOfNode"/>
<xsl:variable name="amount" select="//exampleNode[@typeOfNode = '$typeOfnode' and $counter]/@amount"/>
<xsl:variable name="recursiveValue" select="number($recursiveValue + $amount)"/>
<xsl:choose>
<xsl:when test="number($counter - 1) > 0">
<xsl:call-template name="addition">
<xsl:with-param name="currentValue">
<xsl:value-of select="$recursiveValue"/>
</xsl:with-param>
<xsl:with-param name="counter">
<xsl:value-of select="number($counter - 1)"/>
</xsl:with-param>
<xsl:with-param name="agreementType">
<xsl:value-of select="$agreementType"/>
</xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$recursiveValue"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
0
1.
使用XMLspy进行调试后,未设置amount变量,我认为这是因为我把查询搞砸了。有人知道我做错了什么吗?我还没有查看代码的详细信息,为什么不简单地定义一个键呢
<xsl:key name="k1" match="exampleNode" use="@typeOfNode"/>
然后计算“1”类型节点的总和,例如
<xsl:value-of select="sum(key('k1', '1')/@amount)"/>
有关快速答案,请参阅最后一个代码块。有关代码的一些注释,请阅读此处
<xsl:variable name="recursiveValue" select="number($currentValue + $amount)"/>
<xsl:variable name="amount" select="//exampleNode[@typeOfNode = '$typeOfnode' and $counter]/@amount"/>
如果您的意思是说“amount是@typeOfNode=$typeOfNode的$counter th/exampleNode的@amount,那么不是这样的
- “转义”变量将不起作用,它将与文本值“$typeOfnode”进行比较
- “和$counter”的计算结果始终为true,除非未设置$counter。请尝试“position()=$typeOfnode”“但请注意,位置将是当前exampleNode在整个exampleNode同级集合中的位置。可以通过使用中间变量“复制”通过过滤器的exampleNodes(使用$counter变量测试索引)来解决这一问题
<xsl:with-param name="agreementType">
<xsl:value-of select="$agreementType"/>
</xsl:with-param>
可能遗漏了一些混淆,您是指节点iso agreementType的类型吗D<xsl:value-of select="sum(exampleNode[@typeOfnode='1']/@amount)"/>
如果您真的非常想要递归解决方案
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/">
<xsl:call-template name="recurse">
<xsl:with-param name="nodes_to_sum" select="//exampleNode[@typeOfnode='1']"/>
<xsl:with-param name="sum" select="0"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="recurse">
<xsl:param name="nodes_to_sum"/>
<xsl:param name="sum"/>
<xsl:choose>
<xsl:when test="count($nodes_to_sum)=0">
<sum>
<xsl:value-of select="$sum"/>
</sum>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="recurse">
<xsl:with-param name="nodes_to_sum" select="$nodes_to_sum[position()>1]"/>
<xsl:with-param name="sum" select="$sum + $nodes_to_sum[1]/@amount"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
关于递归
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/">
<xsl:call-template name="recurse">
<xsl:with-param name="nodes_to_sum" select="//exampleNode[@typeOfnode='1']"/>
<xsl:with-param name="sum" select="0"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="recurse">
<xsl:param name="nodes_to_sum"/>
<xsl:param name="sum"/>
<xsl:choose>
<xsl:when test="count($nodes_to_sum)=0">
<sum>
<xsl:value-of select="$sum"/>
</sum>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="recurse">
<xsl:with-param name="nodes_to_sum" select="$nodes_to_sum[position()>1]"/>
<xsl:with-param name="sum" select="$sum + $nodes_to_sum[1]/@amount"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
在第一次调用中,我们初始化数据;整个集合-已过滤-用于计算的和,以及初始和(0)
在递归“函数”中,我们首先测试终端条件,在我们的例子中,“没有什么可加的了”。如果是这种情况,返回结果
…否则,也就是说,如果有更多的工作要做,用更小的todo列表和更高的累加器调用递归部分,这保证了递归将在某个点停止
但请参阅我的另一个答案,以获得更简单的解决方案…这里不需要递归 事实上,所需的总和可以由一个单行XPath表达式返回:
sum(/*/*[@typeOfnode = $pType]/@amount)
231
这里是一个完整的转换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pType" select="3"/>
<xsl:template match="/">
<xsl:value-of select="sum(/*/*[@typeOfnode = $pType]/@amount)"/>
</xsl:template>
</xsl:stylesheet>
是的,我在回家的路上意识到了这一点,打了自己一巴掌。不过谢谢你的评论。这篇文章总体上很有帮助,让我对递归函数有了更多的思考。我希望我能给代表,但我的帐户是太noob:)@user1428971笑,无论如何谢谢(说刚出noob家伙)。在你重复了一点之后再回来:D递归确实很强大,但有时有些过分了。我很高兴听到你从中获得了学习的经验。谢谢你走过这段路。