Search code examples
xmlxsltxslt-grouping

XSLT grouping sum


Currently, I am working with an XML file that has the following structure:

<TA_CREDITO>
    <item>
        <VTWEG/>
        <LIMITE_CREDITO>2.00</LIMITE_CREDITO>
        <MONTO_CONSUMIDO>400.00</MONTO_CONSUMIDO>
        <MONTO_COMPROMETIDO>600.00</MONTO_COMPROMETIDO>
        <DISPONIBLE>3000.00</DISPONIBLE>
         <TIPO_CREDITO>E</TIPO_CREDITO>
    </item>
    <item>
        <VTWEG>11</VTWEG>
        <LIMITE_CREDITO>964251.00</LIMITE_CREDITO>
        <MONTO_CONSUMIDO>184176.44</MONTO_CONSUMIDO>
        <MONTO_COMPROMETIDO>0.00</MONTO_COMPROMETIDO>
        <DISPONIBLE>780074.56</DISPONIBLE>
        <TIPO_CREDITO>C</TIPO_CREDITO>
    </item>
    <item>
        <VTWEG>12</VTWEG>
        <LIMITE_CREDITO>300000.00</LIMITE_CREDITO>
        <MONTO_CONSUMIDO>0.00</MONTO_CONSUMIDO>
        <MONTO_COMPROMETIDO>0.00</MONTO_COMPROMETIDO>
        <DISPONIBLE>300000.00</DISPONIBLE>
        <TIPO_CREDITO>C</TIPO_CREDITO>
    </item>
</TA_CREDITO>

As you can see, there are several "item", each of which has a "tipo_credito", which can have 2 different values. What I need is to generate a new file, with a similar structure, but add up to the attributes of the common "tipo_credito" methods. And I return for example:

<item>
        <VTWEG/>
        <LIMITE_CREDITO>2.00</LIMITE_CREDITO>
        <MONTO_CONSUMIDO>400.00</MONTO_CONSUMIDO>
        <MONTO_COMPROMETIDO>600.00</MONTO_COMPROMETIDO>
        <DISPONIBLE>3000.00</DISPONIBLE>
         <TIPO_CREDITO>E</TIPO_CREDITO>
    </item>
    <item>
        <VTWEG>11</VTWEG>
        <LIMITE_CREDITO>1.264.251</LIMITE_CREDITO>
        <MONTO_CONSUMIDO>184176.44</MONTO_CONSUMIDO>
        <MONTO_COMPROMETIDO>0.00</MONTO_COMPROMETIDO>
        <DISPONIBLE>1.080.074.56</DISPONIBLE>
        <TIPO_CREDITO>C</TIPO_CREDITO>
    </item>

I have these, but the if is not working

    <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <!-- Tomar Informaciòn XML Retornado -->
    <xsl:template match="/">
            <EX_BLOQUEO>
                   <xsl:value-of select="//EX_BLOQUEO"/>
            </EX_BLOQUEO>
             <EX_MOROSIDAD>
                   <xsl:value-of select="//EX_MOROSIDAD"/>
             </EX_MOROSIDAD>
             <xsl:for-each select="//item">
                 <items>
                     <xsl:if test="TIPO_CREDITO = C">
                     <LIMITE_CREDITO>
                        <xsl:value-of select="sum(//LIMITE_CREDITO)"/>
                    </LIMITE_CREDITO>
                    </xsl:if>
                
                    <xsl:if test="TIPO_CREDITO = ">
                     <LIMITE_CREDITO>
                        <xsl:value-of select="sum(//LIMITE_CREDITO)"/>
                    </LIMITE_CREDITO>
                    </xsl:if>
                 </items>
            </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Solution

  • Please try the following XSLT.

    It is using grouping to sum up all relevant elements in the group.

    XSLT

    <?xml version="1.0"?>
    <xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" expand-text="yes">
        <xsl:output indent="yes" method="xml"/>
    
        <xsl:template match="/TA_CREDITO">
            <xsl:copy>
                <xsl:for-each-group select="item" group-by="TIPO_CREDITO">
                    <item>
                        <VTWEG>{sum(current-group()/VTWEG/number())}</VTWEG>
                        <LIMITE_CREDITO>{format-number(sum(current-group()/LIMITE_CREDITO), '#,##0.00')}</LIMITE_CREDITO>
                        <MONTO_CONSUMIDO>{format-number(sum(current-group()/MONTO_CONSUMIDO), '#,##0.00')}</MONTO_CONSUMIDO>
                        <MONTO_COMPROMETIDO>{format-number(sum(current-group()/MONTO_COMPROMETIDO), '#,##0.00')}</MONTO_COMPROMETIDO>
                        <DISPONIBLE>{format-number(sum(current-group()/DISPONIBLE), '#,##0.00')}</DISPONIBLE>
                        <TIPO_CREDITO>{current-grouping-key()}</TIPO_CREDITO>
                    </item>
                </xsl:for-each-group>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>