[xsl] Fw: [xml-dev] XLST 'DISTINCT' Equivalent

Subject: [xsl] Fw: [xml-dev] XLST 'DISTINCT' Equivalent
From: "Steve Muench" <Steve.Muench@xxxxxxxxxx>
Date: Thu, 31 Jan 2002 00:58:39 -0800
Thought this might be useful for folks on the xsl list, too as
examples to ponder...

| > I was wondering if there was a way of using XSLT to return a
| > distinct set of
| > values from an XML document?
| >
| > e.g.
| >
| > <TAG1>
| >   <TAG2>John</TAG2>
| >   <TAG2>Fred</TAG2>
| >   <TAG2>John</TAG2>
| > </TAG>

Using the new features for Grouping from the XSLT 2.0 working draft 
(together with the SAXON 7.0 processor [3] that lets you experiment
with them), you could take a document like:

<TAG1>
  <TAG2>John</TAG2>
  <TAG2>Fred</TAG2>
  <TAG2>John</TAG2>
  <TAG2>Fred</TAG2>
  <TAG2>Abigail</TAG2>
  <TAG2>John</TAG2>
  <TAG2>Steve</TAG2>
</TAG1>


And produce an output like:

Distinct TAG2 values in alphabetical order are
1. Abigail (1)
2. Fred (2)
3. John (3)
4. Steve (1)

Using a stylesheet like in [1] below.

By slightly changing the stylesheet, you could
have the distinct elements listed by the number
of times they appear in the document, then by
alphabetical order using a stylesheet like in [2] below
to produce output like:

Distinct TAG2 values in order of most appearance are
1. John (3)
2. Fred (2)
3. Abigail (1)
4. Steve (1)


Here are the stylesheets:

=========== [1] ===========
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  <xsl:output method="text"/>
  <xsl:template match="/">
    <xsl:text>Distinct TAG2 values in alphabetical order are&#xa;</xsl:text>
    <!-- Works with Saxon 7.0 implementing XSLT 2.0 Draft -->
    <xsl:for-each-group select="/TAG1/TAG2" group-by=".">
      <xsl:sort select="."/>
      <xsl:value-of select="position()"/>
      <xsl:text>. </xsl:text>
      <xsl:value-of select="current-group()[1]"/>
      <xsl:text> (</xsl:text>
        <xsl:value-of select="count(current-group())"/>
      <xsl:text>)</xsl:text>    
      <xsl:if test="position() != last()"><xsl:text>&#xa;</xsl:text></xsl:if>
    </xsl:for-each-group>
  </xsl:template>
</xsl:stylesheet>


=========== [2] ===========
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  <xsl:output method="text"/>
  <xsl:template match="/">
    <xsl:text>Distinct TAG2 values in order of most appearance are&#xa;</xsl:text>
    <!-- Works with Saxon 7.0 implementing XSLT 2.0 Draft -->
    <xsl:for-each-group select="/TAG1/TAG2" group-by=".">
      <xsl:sort data-type="number" select="count(current-group())" order="descending"/>
      <xsl:sort select="."/>
      <xsl:value-of select="position()"/>
      <xsl:text>. </xsl:text>
      <xsl:value-of select="current-group()[1]"/>
      <xsl:text> (</xsl:text>
        <xsl:value-of select="count(current-group())"/>
      <xsl:text>)</xsl:text>    
      <xsl:if test="position() != last()"><xsl:text>&#xa;</xsl:text></xsl:if>
    </xsl:for-each-group>
  </xsl:template>
</xsl:stylesheet>

=========== [3] ===========
SAXON 7.0 http://saxon.sourceforge.net/#F7.0


_____________________________________________________________________
Steve Muench - Developer, Product Manager, XML Evangelist, Author
"Simplifying J2EE and EJB Development with BC4J"
http://otn.oracle.com/products/jdev/htdocs/j2ee_with_bc4j/j2ee_with_bc4j.html
"Building Oracle XML Applications" - www.oreilly.com/catalog/orxmlapp



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread