我必须进行递归才能添加一些值并返回总数。我有一个XML文件,对于每个coloc_id,我需要返回“montant”里面的内容。例如,对于我下面的XML,我需要返回:
Balthazar : 732
Gaspard : 172 (87+87)
Melchior : 1239 (1236+3)
Jesus : 104
我不能使用foreach,这在我的运动中是禁止的。我搜索了3个小时,但我无法弄清楚我需要做什么。下面是我的xsl文件,显示:
Balthazar:732.
Gaspard:87.
Gaspard:87.
Melchior:1236.
Melchior:3.
Jesus:104.
但我想要一个总数,而且我不知道如何在同一时间将几个元素与同一个coloc_id匹配。
<comptes>
<actions>
<depense coloc_id="Melchior" categorie="loyer" date="2016-12-12">
<montant>1236
</montant>
<pour coloc_id="Melchior"/>
<pour coloc_id="Balthazar"/>
</depense>
<depense coloc_id="Melchior" categorie="loyer" date="2016-12-12">
<montant>3
</montant>
<pour coloc_id="Melchior"/>
<pour coloc_id="Balthazar"/>
</depense>
<depense coloc_id="Balthazar" categorie="meuble">
<montant>732
</montant>
<pour coloc_id="Gaspard"/>
<pour coloc_id="Balthazar"/>
</depense>
<depense coloc_id="Gaspard" categorie="alimentation">
<montant>87
</montant>
<pour coloc_id="Balthazar"/>
<pour coloc_id="Gaspard"/>
</depense>
<depense coloc_id="Gaspard" categorie="alimentation" >
<montant>87
</montant>
<pour coloc_id="Balthazar"/>
<pour coloc_id="Gaspard"/>
<pour coloc_id="Melchior"/>
<pour coloc_id="Jesus"/>
</depense>
<depense coloc_id="Jesus" categorie="alimentation" >
<montant>104
</montant>
<pour coloc_id="Balthazar"/>
<pour coloc_id="Gaspard"/>
<pour coloc_id="Melchior"/>
<pour coloc_id="Jesus"/>
</depense>
</actions>
<colocataires>
<coloc id="Melchior">Melchior</coloc>
<coloc id ="Balthazar">Balthazar</coloc>
<coloc id="Gaspard">Gaspard</coloc>
</colocataires>
</comptes>
我的xsl文件:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="*/*">
<xsl:apply-templates select=".//depense[@coloc_id='Balthazar']" mode="ok">
<xsl:with-param name="personne">Balthazar</xsl:with-param>
</xsl:apply-templates>
<xsl:apply-templates select=".//depense[@coloc_id='Gaspard']" mode="ok">
<xsl:with-param name="personne">Gaspard</xsl:with-param>
</xsl:apply-templates>
<xsl:apply-templates select=".//depense[@coloc_id='Melchior']" mode="ok">
<xsl:with-param name="personne">Melchior</xsl:with-param>
</xsl:apply-templates>
<xsl:apply-templates select=".//depense[@coloc_id='Jesus']" mode="ok">
<xsl:with-param name="personne">Jesus</xsl:with-param>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*" mode="ok">
<xsl:param name="personne"/>
<xsl:value-of select="$personne"/>
<xsl:text>:</xsl:text>
<xsl:call-template name="DepenseMelchior">
<xsl:with-param name="coloc"><xsl:value-of select="$personne"/></xsl:with-param>
<xsl:with-param name="total">0</xsl:with-param>
<xsl:with-param name="index_courant">1</xsl:with-param>
</xsl:call-template>
<xsl:text>.
</xsl:text>
</xsl:template>
<xsl:template name="DepenseMelchior">
<xsl:param name="coloc"/>
<xsl:param name="total"/>
<xsl:param name="index_courant"/>
<xsl:choose>
<xsl:when test="$index_courant = count(*)+ 1">
<xsl:value-of select="$total"/>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="self::node()[@coloc_id=$coloc]">
<xsl:variable name="un_nombre"><xsl:value-of select="montant"/></xsl:variable>
<xsl:call-template name="DepenseMelchior">
<xsl:with-param name="total"><xsl:value-of select="$total + $un_nombre"/></xsl:with-param>
<xsl:with-param name="index_courant"><xsl:value-of select="$index_courant + 1"/></xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="DepenseMelchior">
<xsl:with-param name="total"><xsl:value-of select="$total"/></xsl:with-param>
<xsl:with-param name="index_courant"><xsl:value-of select="$index_courant + 1"/></xsl:with-param>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:1)
您可以使用key
对节点进行分组。此示例对coloc
元素进行模板设置,使用键将coloc_id
匹配的金额相加。
请注意,这并不打印所有coloc
的总和,因为colocataires
列表中缺少其中一个( Jesus )。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<!-- Map of depense by coloc_id -->
<xsl:key name="depense-coloc" match="/comptes/actions/depense" use="@coloc_id"/>
<!-- Template each coloc in the colocataires list -->
<xsl:template match="/">
<xsl:apply-templates select="/comptes/colocataires/coloc"/>
</xsl:template>
<!-- Template a coloc -->
<xsl:template match="coloc">
<!-- Name --> <!-- Sum of depense/montant for matching coloc_id -->
<xsl:value-of select="."/>: <xsl:value-of select="sum(key('depense-coloc', @id)/montant)"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
你可以使用递归,但它会更笨拙:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<!-- Template each coloc in the colocataires list -->
<xsl:template match="/">
<xsl:apply-templates select="/comptes/colocataires/coloc"/>
</xsl:template>
<!-- Template a coloc -->
<xsl:template match="coloc">
<!-- Name --> <!-- Template the first depense for matching coloc_id -->
<xsl:value-of select="."/>: <xsl:apply-templates select="/comptes/actions/depense[@coloc_id=current()/@id][1]"/>
<xsl:text>
</xsl:text>
</xsl:template>
<!-- Sum the montant of a depense and all following depense elements -->
<xsl:template match="depense">
<xsl:variable name="next">
<xsl:apply-templates select="following-sibling::depense[@coloc_id=current()/@coloc_id][1]"/>
</xsl:variable>
<xsl:value-of select="concat(0, $next) + montant"/>
</xsl:template>
</xsl:stylesheet>
最后,一个直接的总和更清晰,更紧凑:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<!-- Template each coloc in the colocataires list -->
<xsl:template match="/">
<xsl:apply-templates select="/comptes/colocataires/coloc"/>
</xsl:template>
<!-- Template a coloc -->
<xsl:template match="coloc">
<!-- Name --> <!-- Sum of depense/montant for matching coloc_id -->
<xsl:value-of select="."/>: <xsl:value-of select="sum(/comptes/actions/depense[@coloc_id=current()/@id]/montant)"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>