RE: [xsl] sorting a table based on first column which contains both numbers and words

Subject: RE: [xsl] sorting a table based on first column which contains both numbers and words
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Fri, 18 Dec 2009 14:40:18 -0000
Well, if you're using Saxon there's another solution which is to use the
alphanumeric collation

<xsl:sort collation="http://saxon.sf.net/collation?alphanumeric=yes"/>

But if you want to pursue the original idea of using two sort keys, you
could achieve the "numbers first" by adding a boolean sort key (in the first
position) <xsl:sort select="number(number(.)=number(.))"
data=type="number"/> (This gives a sort key of 0 if the numeric value is
NaN, 1 otherwise).

Regards,

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

> -----Original Message-----
> From: Robby Pelssers [mailto:robby.pelssers@xxxxxxxxx]
> Sent: 18 December 2009 13:33
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: RE: [xsl] sorting a table based on first column
> which contains both numbers and words
>
> Ok...
>
> I created a more usefull table this time to really show what I want:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <table>
>   <tr>
>     <td>5</td>
>   </tr>
>   <tr>
>     <td>111</td>
>   </tr>
>   <tr>
>     <td>3</td>
>   </tr>
>   <tr>
>     <td>Banana</td>
>   </tr>
>   <tr>
>     <td>12</td>
>   </tr>
>   <tr>
>     <td>Apple</td>
>   </tr>
> </table>
>
> Using 2 sort keys like below
>   <xsl:template match="table">
>     <table>
>       <xsl:apply-templates select="tr">
>         <xsl:sort select="td" data-type="number"/>
>         <xsl:sort select="td" data-type="text"/>
>       </xsl:apply-templates>
>     </table>
>   </xsl:template>
> Results in
>
> <?xml version="1.0" encoding="UTF-8"?>
> <table>
>   <tr>
>     <td>Apple</td>
>   </tr>
>   <tr>
>     <td>Banana</td>
>   </tr>
>   <tr>
>     <td>3</td>
>   </tr>
>   <tr>
>     <td>5</td>
>   </tr>
>   <tr>
>     <td>12</td>
>   </tr>
>   <tr>
>     <td>111</td>
>   </tr>
> </table>
>
> But I wanted numbers first and then strings.
>
> So uptill now I still see my solution (see below) as the only
> correct one?  Unless you have yet another idea ;-)
>
> Robby Pelssers
>
> -----Original Message-----
> From: Michael Kay [mailto:mike@xxxxxxxxxxxx]
> Sent: Thursday, December 17, 2009 5:31 PM
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: RE: [xsl] sorting a table based on first column
> which contains both numbers and words
>
> But the default sort will put 10 before 2. If you don't want
> that you could do
>
> <xsl:sort select="td" data-type="number"/> <xsl:sort
> select="td" data-type="text"/>
>
> i.e. two apparently separate sort keys - if they aren't
> distinguishable as numbers (both convert to NaN) then they
> will be sorted as strings.
>
> Regards,
>
> Michael Kay
> http://www.saxonica.com/
> http://twitter.com/michaelhkay
>
> > -----Original Message-----
> > From: Robby Pelssers [mailto:robby.pelssers@xxxxxxxxx]
> > Sent: 17 December 2009 15:53
> > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > Subject: RE: [xsl] sorting a table based on first column which
> > contains both numbers and words
> >
> > Mm... damn.... I thought I needed to specify the data-type ;-(
> >
> > So I just came up with following solution:
> >
> >   <xsl:template match="table">
> >     <table>
> >       <xsl:variable name="numericRows"
> > select="tr[string(number(td)) !='NaN']"/>
> >       <xsl:variable name="alphabeticRows"
> > select="tr[string(number(td))='NaN']"/>
> >       <xsl:apply-templates select="$numericRows">
> >         <xsl:sort select="td" data-type="number"/>
> >       </xsl:apply-templates>
> >       <xsl:apply-templates select="$alphabeticRows">
> >         <xsl:sort select="td" data-type="text"/>
> >       </xsl:apply-templates>
> >     </table>
> >   </xsl:template>
> >
> > But I also tested without specifying any data-type and you're right
> > ...aaargh..
> >
> >   <xsl:template match="table">
> >     <table>
> >       <xsl:apply-templates select="tr">
> >         <xsl:sort select="td"/>
> >       </xsl:apply-templates>
> >     </table>
> >   </xsl:template>
> >
> > Thx,
> > You made life a lot easier ;-)
> >
> > Robby
> >
> > -----Original Message-----
> > From: Andrew Welch [mailto:andrew.j.welch@xxxxxxxxx]
> > Sent: Thursday, December 17, 2009 4:28 PM
> > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > Subject: Re: [xsl] sorting a table based on first column which
> > contains both numbers and words
> >
> > 2009/12/17 Robby Pelssers <robby.pelssers@xxxxxxxxx>:
> > > Hi all,
> > >
> > > I have the use case where I need to sort a table based on
> > it's first column.  This column can contain only numbers but also a
> > mix of words and numbers. See example below.
> > >
> > > <table>
> > >   <tr>
> > >     <td>5</td>
> > >   </tr>
> > >   <tr>
> > >     <td>3</td>
> > >   </tr>
> > >   <tr>
> > >     <td>Banana</td>
> > >   </tr>
> > >   <tr>
> > >     <td>Apple</td>
> > >   </tr>
> > > </table>
> > >
> > >
> > > I want following output (first sorted numerical  and then
> > > alphabetically)
> > >
> > > <table>
> > >   <tr>
> > >     <td>3</td>
> > >   </tr>
> > >   <tr>
> > >     <td>5</td>
> > >   </tr>
> > >   <tr>
> > >     <td>Apple</td>
> > >   </tr>
> > >   <tr>
> > >     <td>Banana</td>
> > >   </tr>
> > > </table>
> > >
> > > How can I accomplish this with xslt?
> >
> >
> > The default sort will do that, read about xsl:sort
> >
> >
> > --
> > Andrew Welch
> > http://andrewjwelch.com
> > Kernow: http://kernowforsaxon.sf.net/

Current Thread