Glenn Whiting
Glenn Whiting

Reputation: 57

XSLT 2.0 How do I Sum total of count for each unique item id

Note that some id's repeat and I only want the sum of the count of each unique id. The correct total will be 11.

Note: I had to edit the id on the first set to be 1

Sample Input File:

<?xml version="1.0" encoding="UTF-8"?>
<file>
    <item>
        <id>1</id>
         <count>4</count>
    </item>
    <item>
        <id>2</id>
        <count>7</count>
    </item>
    <item>
        <id>2</id>
        <count>7</count>
    </item>
    <item>
        <id>2</id>
        <count>7</count>
    </item>
</file>

Sample Ouput File:

<?xml version="1.0" encoding="UTF-8"?>
<output>
    <totalUniqueItemCount>11</totalUniqueItemCount>
</output>

XSLT Attempt:

Here you can see am trying to use for-each group but it is not working for me. I need to be able to get a sum of these counts but I can't figure out how to surround the output of the for-each-group to be able to sum the counts.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    
    <xsl:output indent="yes" method="xml"/>
    
    <xsl:template match="/file">
        <output>
            <totalUniqueItemCount>
            
                    <xsl:for-each-group select="item" group-by="id">
                
                        <xsl:value-of select="xs:integer(count)"/>
                
                    </xsl:for-each-group>
            
            </totalUniqueItemCount>
        </output>
    </xsl:template>
    
</xsl:stylesheet>

I also tried this approach with no luck:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xsl:output indent="yes" method="xml"/>

<xsl:template match="/file">
    <output>
        <totalUniqueItemCount>
                
                <xsl:value-of select="sum(item[id ne following-sibling::id]/count)"/>
        
        </totalUniqueItemCount>
    </output>
</xsl:template>

</xsl:stylesheet>

Upvotes: 2

Views: 832

Answers (3)

michael.hor257k
michael.hor257k

Reputation: 117102

how to surround the output of the for-each-group to be able to sum the counts.

You could have done:

<xsl:template match="/file">
    <xsl:variable name="unique-counts">
        <xsl:for-each-group select="item" group-by="id">
            <xsl:copy-of select="count"/>
        </xsl:for-each-group>   
    </xsl:variable>
    <output>
        <totalUniqueItemCount>
            <xsl:value-of select="sum($unique-counts/count)"/>
        </totalUniqueItemCount>
    </output>
</xsl:template>

But the method suggested by MartinM might be preferable for this scenario.

Upvotes: 0

Rupesh_Kr
Rupesh_Kr

Reputation: 3445

Just minor change in your second code

use

<xsl:value-of select="sum(item[not(id = following-sibling::item/id)]/count)"/>

instead of

<xsl:value-of select="sum(item[id ne following-sibling::id]/count)"/>

Upvotes: -1

user18451290
user18451290

Reputation: 67

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xsl:output indent="yes" method="xml"/>

<xsl:key name="itemById" match="file/item" use="id"/>

<xsl:template match="/file">
    <output>
        <totalUniqueItemCount>
            <xsl:value-of select="sum(//item[generate-id(.) = generate-id(key('itemById',id)[1])]/count)"/>
        </totalUniqueItemCount>
    </output>
</xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/3Mvnt44/1

Upvotes: 1

Related Questions