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

Subject: RE: [xsl] Trying to identify the 3 highest sales results
From: "Ian Blair" <iblair@xxxxxxxxxxxxxxx>
Date: Mon, 7 Jan 2008 10:21:30 -0000
Would it be easier just to do something this, or is this bad for
performance aswell?


<xsl:template match="/table">
  <xsl:apply-templates select="row">
    <xsl:sort select="sales" order="descending" data-type="number"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="row">
  <tr>
    ...
    <td>
      <xsl:choose>
        <xsl:when test="position() = 1">First:</xsl:when>
        <xsl:when test="position() = 2">Second:</xsl:when>
        <xsl:when test="position() = 3">Third:</xsl:when>
        <xsl:otherwise/>
      </xsl:choose>
      <xsl:value-of select="sales"/>
    </td>
  </tr>
</xsl:template>

-----Original Message-----
From: Michael Kay [mailto:mike@xxxxxxxxxxxx]
Sent: 07 January 2008 10:15
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: RE: [xsl] Trying to identify the 3 highest sales results

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


______________________________________________________________________
This email has been scanned by the MessageLabs Email Security System.
For more information please visit http://www.messagelabs.com/email
______________________________________________________________________

______________________________________________________________________
This email has been scanned by the MessageLabs Email Security System.
For more information please visit http://www.messagelabs.com/email
______________________________________________________________________

Current Thread