Search code examples
xmlxpathxslt

XSLT - Count only duplicate values, and count them only once


How do I get XSLT or XPath to return a count of 3 for the below data?

Kelly Watson
Andrew Lee
Andrew Lee
Susan Smith
Susan Smith
Susan Smith
Derin Gill
Derin Gill
William Jones

So only count the duplicates: Andrew, Susan, and Derin, and only count them once.

I've got the below which returns the data as a row. But how to return the count has me stumped.

<xsl:variable name="MyValues" select="tokenize('~Kelly Watson~Andrew Lee~Andrew Lee~Susan Smith~Susan Smith~Susan Smith~Derin Gill~Derin Gill~William Jones', '~')"/>

<xsl:for-each select="$MyValues">
    <xsl:value-of select="."/>
</xsl:for-each>

<xsl:value-of select="$DuplicateCnt"/>



Solution

  • Apparently you can use XSLT 2.0 or higher, so you could do something like:

    <xsl:variable name="data">~Kelly Watson~Andrew Lee~Andrew Lee~Susan Smith~Susan Smith~Susan Smith~Derin Gill~Derin Gill~William Jones</xsl:variable>
    <xsl:variable name="groups">
        <xsl:for-each-group  select="tokenize($data, '~')" group-by=".">
            <group>
                <xsl:value-of select="count(current-group())" />    
            </group>
        </xsl:for-each-group>
    </xsl:variable>
    <result>
        <xsl:value-of select="count($groups/group[. > 1])"/>
    </result>
    

    Or perhaps just:

    <xsl:variable name="MyValues" select="tokenize('~Kelly Watson~Andrew Lee~Andrew Lee~Susan Smith~Susan Smith~Susan Smith~Derin Gill~Derin Gill~William Jones', '~')"/>
    <result>
        <xsl:value-of select="count(distinct-values($MyValues)[count(index-of($MyValues, .)) > 1])"/>
    </result>