2
votes

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>

3

3 Answers

1
votes
<?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

0
votes

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.

-1
votes

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)"/>