RE: [xsl] Trying to identify the 3 highest sales results

Subject: RE: [xsl] Trying to identify the 3 highest sales results
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Mon, 7 Jan 2008 10:15:25 -0000
A crude approach would be along the lines:

<xsl:attribute name="class">
  <xsl:variable name="numAbove" select="count(../row/agent[sales >
current()/sales])"/>
  <xsl:choose>
    <xsl:when test="$numAbove=0">first</xsl:when> 
    <xsl:when test="$numAbove=1">second</xsl:when> 
    <xsl:when test="$numAbove=2">third</xsl:when>
    <xsl:otherwise>...</xsl:otherwise>

That's likely to be O(n^2) in performance, so it's only viable with modest
amounts of data.

I think any more efficient solution involves first doing a sort to identify
the top three, and storing this data in some temporary data structure for
reference while you generate the output. 2-phase solutions in XSLT 1.0
invariably require the xx:node-set() extension.

A compromise would be for your first pass to return a single number, the
sales achieved by the third-highest agent, and then do the logic above only
if the sales are >= this figure. You can then do the first pass as

<xsl:variable name="third-highest">
  <xsl:for-each select="row">
    <xsl:sort select="sales" data-type="number" order="descending"/>
    <xsl:if test="position()=3"><xsl:value-of select="sales"/></xsl:if>
  </
</

or you could do the above three times to initialize three variables.

In 2.0 you can do

<xsl:variable name="sales-ranked" as="xs:integer">
  <xsl:perform-sort select="row/sales"/>
    <xsl:sort select="number(.)" order="descending"/>

Then

<xsl:for-each select="row">
  <td class="{if (sales=$sales-ranked[1]) then 'first'
                else if (sales=$sales-ranked[2]) then 'second'
etc 

Michael Kay
http://www.saxonica.com/ 

> -----Original Message-----
> From: Arthur Maloney [mailto:ArthurM@xxxxxxxxxx] 
> Sent: 07 January 2008 07:21
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] Trying to identify the 3 highest sales results
> 
> Hello xsl-list,
> 
>  I'm using Xslt(v1.0) to convert an Xml(v1.0) file to Xhtml 
> for browser display  and trying to add a visual for the top 3 
> sales result.
> 
>  i.e. trying to build
>  <td class="first">9</td>
>  <td class="second">6</td>
>  <td class="third">3</td>
>  The CSS class translates to <img src="boldGold.gif" 
> alt="first" />  I'm Ok with building the Xhtml and adding CSS classes
> 
>  When the row template is being processed.
>  How Do you Identify if it's the 1st, 2nd or 3rd highest sales figure?
>  Typically there are 200-300 salesmen results per calculation 
> and the Xml  by design,is pre sorted by salesman name.
> 
>  
> Xslt shard
>  <xsl:template match="row">
>       <tr>
>       ...
>       <td>
>         <xsl:value-of select="sales"/>
>       </td>
>       </tr>
> </xsl:template>
> 
> 
> Xml shard
> <table calculated="08W021T07:16">
>    <row>
>       <agent>Fred Smith</agent>
>       ...
>       <sales>6</sales>
>    </row>
>    <row>
>       <agent>George Jones</agent>
>       ...
>       <sales>9</sales>
>    </row>
>    <row>
>       <agent>George Jones Jr</agent>
>       ...
>       <sales>1</sales>
>    </row>
>    <row>
>       <agent>Karina Houseman</agent>
>       ...
>       <sales>3</sales>
>    </row>
> </table>
> 
> 
> --
> Best regards,
>  Arthur                          mailto:ArthurM@xxxxxxxxxx

Current Thread