This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Adjusting sorted list


> I have the following XML:
> <a>
>     <b>4</b>
>     <b>9</b>
>     <b>6</b>
>     <b>1</b>
>     <b>8</b>
>     <b>6</b>
>     <b>4</b>
>     <b>7</b>
> </a>
> 
> I am trying to generate the following ouput:
> <a>
>     <b rank="1">1</b>
>     <b rank="2">4</b>
>     <b rank="2">4</b>
>     <b rank="3">6</b>
>     <b rank="3">6</b>
>     <b rank="4">7</b>
>     <b rank="5">8</b>
>     <b rank="6">9</b>
> </a>
> 
> Using xsl:for-each with a sort on b and then using position() I can 
> get a ranking from 1 to 8 but I have no idea how to achieve the
above.
> 
> I have dug around in the archives for some ideas but to no avail.
> I see that I can't use a variable and adjust it's value with each
> iteration (as it's not actually iterating).
> I have also looked into using a recursive named template but am not 
> sure how to achieve the above and sort the output???

This is a grouping problem. You have to take just the elements with
distinct values -- their positions in the node-list will determine the
rank. Then for each such distinct element you have to produce all other
elements with the same value -- and to assign to them the same rank.

Bellow is the stylesheet that does this:

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
 
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 
 <xsl:key name="kRanking" match="b" use="."/>
 
  <xsl:template match="/">
    <a>
     <xsl:for-each select="/a/b[generate-id() 
                              = 
                               generate-id(key('kRanking',.)[1])
                               ]">
       <xsl:sort select="." data-type="number"/>
       
       <xsl:variable name="vPos" select="position()"/>
       
       <xsl:for-each select="key('kRanking',.)">
         <b rank="{$vPos}">
           <xsl:value-of select="."/>
         </b>
       
       </xsl:for-each>
     </xsl:for-each>
    </a>
  </xsl:template>
</xsl:stylesheet>

With your source xml it produces exactly the desires result:

<a>
   <b rank="1">1</b>
   <b rank="2">4</b>
   <b rank="2">4</b>
   <b rank="3">6</b>
   <b rank="3">6</b>
   <b rank="4">7</b>
   <b rank="5">8</b>
   <b rank="6">9</b>
</a>

Hope this helped.

Cheers,
Dimitre Novatchev.




__________________________________________________
Do You Yahoo!?
LAUNCH - Your Yahoo! Music Experience
http://launch.yahoo.com

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]