XSLT Sort Alphabetically and Number

I have a group of strings, i.e. g: lines = '9,1,306, LUCY, G, 38,12'

I need the output in XSLT 1.0:

1,9,12,38,306, G LUCY

This is my current code:

<xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus']"> <xsl:sort select="g:line"/> <xsl:sort select="number(g:line)" data-type="number"/> <xsl:value-of select="normalize-space(g:line)" /><xsl:text/> <xsl:if test="position()!=last()"><xsl:text>,&#160;</xsl:text></xsl:if> </xsl:for-each> 

I can make it display only "1, 12, 306, 38, 9, G, LUCY" because the second sort is not matched.

Can anybody help me?

+7
sorting xslt alphanumeric
source share
4 answers

To achieve this, using only one xsl: foreach statement, try the following:

 <xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus']"> <xsl:sort select="not(number(g:line))"/> <xsl:sort select="number(g:line)" data-type="number"/> <xsl:sort select="g:line"/> <xsl:value-of select="normalize-space(g:line)" /><xsl:text/> <xsl:if test="position()!=last()"><xsl:text>,&#160;</xsl:text></xsl:if> </xsl:for-each> 

The first xsl: sort sorts whether the string is a number or not. not () returns false if the string is a number, and true if it is not. false is sorted to true, and so numbers come out first. If you omit this view, the letters will be displayed first.

The following xsl: sort sorts numerically, and therefore sorts numbers correctly, but does not affect letters (which all return NaN when the number () is applied).

Final xsl: sort sorts letters alphabetically.

+11
source share
 <xsl:template match="/"> <xsl:for-each select="(9,1,306,'LUCY','G',89)" > <xsl:sort select="if (number()) then () else ."/> <xsl:sort select="number(.)" data-type="number" /> <xsl:value-of select="."/> <xsl:value-of select="', '" /> </xsl:for-each> </xsl:template> 

gives me

1, 9, 89, 306, G, LUCY,

I think this is what you need, right?

0
source share

In XSLT 1.0, I think you need something like this:

 <xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus']"> <xsl:sort select="g:line[number(g:line) != number(g:line)]"/> <xsl:sort select="g:line[number(g:line) = number(g:line)]" data-type="number"/> <xsl:value-of select="normalize-space(g:line)" /><xsl:text/> <xsl:if test="position()!=last()"><xsl:text>,&#160;</xsl:text></xsl:if> </xsl:for-each> 

number ($ foo)! = number ($ foo) is the XSLT 1.0 idiom for testing if the value is not a number.

Another (cleaner, I think) solution would be to select / sort the first numbers, and then the others.

0
source share

I believe that this does what you want.

I first separated the grades / types of numbers and then the text values ​​of the node.

  <xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus'][number(g:line)=number(g:line)]"> <xsl:sort select="g:line" data-type="number" order="ascending"/> <xsl:value-of select="normalize-space(g:line)" /> <xsl:text/> <xsl:if test="position()!=last() or $all_alerts[g:problem!='normal_service'][g:service='bus'][number(g:line)!=number(g:line)]"> <xsl:text>,&#160;</xsl:text> </xsl:if> </xsl:for-each> <xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus'][number(g:line)!=number(g:line)]"> <xsl:sort select="g:line[number(g:line) != number(g:line)]"/> <xsl:value-of select="normalize-space(g:line)" /> <xsl:text/> <xsl:if test="position()!=last()"> <xsl:text>,&#160;</xsl:text> </xsl:if> </xsl:for-each> 
0
source share

All Articles