Re: [xsl] Count of unique elements [XSLT 1.0]

Subject: Re: [xsl] Count of unique elements [XSLT 1.0]
From: "Mukul Gandhi" <gandhi.mukul@xxxxxxxxx>
Date: Fri, 24 Nov 2006 23:01:50 +0100
If you don't want to use Muenchian method, here is an alternative way:

XML file:

<products>
 <product>
   <prodid>V667320</prodid>
   <name>Battery Pack</name>
   <price>$20</price>
   <quantity>178</quantity>
   <region>SouthWest</region>
 </product>
 <product>
   <prodid>M382932</prodid>
   <name>CD Visor Organizer</name>
   <price>$19</price>
   <quantity>129</quantity>
   <region>NorthWest</region>
 </product>
 <product>
   <prodid>U3923839</prodid>
   <name>Rock n Roll Supercart</name>
   <price>$150</price>
   <quantity>200</quantity>
   <region>SouthWest</region>
 </product>
 <product>
   <prodid>Q3929302</prodid>
   <name>Digital Tire Guage</name>
   <price>$40</price>
   <quantity>623</quantity>
   <region>NorthWest</region>
 </product>
</products>

XSLT file:

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

<xsl:output method="text" />

 <xsl:template match="/products">
   <xsl:variable name="result">
     <xsl:call-template name="findResult">
       <xsl:with-param name="x" select="product[1]" />
       <xsl:with-param name="count" select="0" />
     </xsl:call-template>
   </xsl:variable>
   <xsl:value-of select="$result" />
 </xsl:template>

 <xsl:template name="findResult">
   <xsl:param name="x" />
   <xsl:param name="count" />

   <xsl:choose>
     <xsl:when test="$x">
       <xsl:choose>
         <xsl:when test="not($x/region =
$x/preceding-sibling::product/region)">
           <xsl:call-template name="findResult">
	      <xsl:with-param name="x" select="$x/following-sibling::product[1]" />
	      <xsl:with-param name="count" select="$count + 1" />
           </xsl:call-template>
         </xsl:when>
         <xsl:otherwise>
           <xsl:call-template name="findResult">
	      <xsl:with-param name="x" select="$x/following-sibling::product[1]" />
	      <xsl:with-param name="count" select="$count" />
           </xsl:call-template>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:when>
     <xsl:otherwise>
       <xsl:value-of select="$count" />
     </xsl:otherwise>
   </xsl:choose>
 </xsl:template>

</xsl:stylesheet>

The output is 2.

I believe, you can easily add HTML annotations.

On 11/24/06, Kirov Plamen <pkirov@xxxxxxxxx> wrote:
I want to count unique elements without using the Muenchian method.
My XSL is:

<?xml version='1.0' encoding='utf-8' ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="1.0">
<xsl:output method="html"/>
<xsl:variable name="products" select="//product"/>
<!-- Template for our root rule -->
<xsl:template match="/">
       <xsl:apply-templates/>
</xsl:template>
<!-- Template for our "products" rule -->
<xsl:template match="products">
       <xsl:call-template name="Style1"/>
       <h2>Grouping of Products by Region, then by Product Name </h2>
       <xsl:for-each select="$products">
               <xsl:sort select="name" order="ascending"/>
               <xsl:variable name="region" select="region"/>
       <xsl:if
test="generate-id(.)=generate-id($products[region=$region])">
                       <h3><xsl:value-of select="region"/> region</h3>
                       <table border="1">
                               <tr>
                                       <th>Product Name</th>
                                       <th>Price</th>
                                       <th>Region</th>
                               </tr>
                       <xsl:for-each
select="$products[region=$region]">
                       <xsl:sort select="name"/>
                               <tr>
                                       <td><xsl:value-of
select="name"/></td>
                                       <td><xsl:value-of
select="price"/></td>
                                       <td><xsl:value-of
select="region"/></td>
                               </tr>
                       </xsl:for-each>
                       </table>
                       <br/><br/>
      </xsl:if>
       </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

> -----Original Message-----
> From: Michael Kay [mailto:mike@xxxxxxxxxxxx]
> Sent: Friday, November 24, 2006 11:16 AM
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: RE: [xsl] Count of unique elements [XSLT 1.0]
>
> Counting unique elements is a simple example of the grouping problem.
Read
> about grouping in XSLT 1.0 at
http://www.jenitennison.com/xslt/grouping
>
> Michael Kay
> http://www.saxonica.com/
>
> > -----Original Message-----
> > From: Kirov Plamen [mailto:pkirov@xxxxxxxxx]
> > Sent: 24 November 2006 09:05
> > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > Subject: [xsl] Count of unique elements [XSLT 1.0]
> >
> > Hi all,
> >
> > The XML:
> >
> >     <product>
> >             <prodid>V667320</prodid>
> >             <name>Battery Pack</name>
> >             <price>$20</price>
> >             <quantity>178</quantity>
> >             <region>SouthWest</region>
> >     </product>
> >     <product>
> >             <prodid>M382932</prodid>
> >             <name>CD Visor Organizer</name>
> >             <price>$19</price>
> >             <quantity>129</quantity>
> >             <region>NorthWest</region>
> >     </product>
> >     <product>
> >             <prodid>U3923839</prodid>
> >             <name>Rock n Roll Supercart</name>
> >             <price>$150</price>
> >             <quantity>200</quantity>
> >             <region>SouthWest</region>
> >     </product>
> >     <product>
> >             <prodid>Q3929302</prodid>
> >             <name>Digital Tire Guage</name>
> >             <price>$40</price>
> >             <quantity>623</quantity>
> >             <region>NorthWest</region>
> >     </product>
> >
> > I want to count the unique elements 'region' into XML. In
> > this example the count result must be "2" - there's two
> > unique 'region': NorthWest and SouthWest.
> >
> > Any help is appreciated.
> >
> > BR
> > Plamen

-- Regards, Mukul Gandhi

Current Thread