Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT Sort Alphabetically & Numerically Problem

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

I need the output to be 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 get it to only display '1, 12, 306, 38, 9, G, LUCY' because the 2nd sort isn't being picked up.

Anyone able help me out?

like image 480
Bryan Avatar asked Apr 19 '10 19:04

Bryan


People also ask

How do I sort in XSLT?

XSLT <xsl:sort>The <xsl:sort> element is used to sort the output. Note: <xsl:sort> is always within <xsl:for-each> or <xsl:apply-templates>.

How do I sort an XML output?

The XSLT <xsl:sort> element is used to specify a sort criteria on the nodes. It displays the output in sorted form. The <xml:sort> element is added inside the <xsl:for-each> element in the XSL file, to sort the output.

How do I substring in XSLT?

Substring is primarily used to return a section of a string or truncating a string with the help of the length provided. XSLT is incorporated with XPath while manipulating strings of text when XSLT access. The Substring function takes a string as an argument with the numbers one or two and an optional length.

Can XSLT transform XML to CSV?

This post shows you how to convert a simple XML file to CSV using XSLT. The following XSL Style Sheet (compatible with XSLT 1.0) can be used to transform the XML into CSV. It is quite generic and can easily be configured to handle different xml elements by changing the list of fields defined ar the beginning.


1 Answers

To achieve this using just 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 on whether the line is a number or not. The not() returns false if the line is a number, and true if it isn't. false is sorted before true, and so the numbers come out first. If you omit this sort, the letters will appear first.

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

The final xsl:sort will sort the letters alphabetically.

like image 181
Tim C Avatar answered Nov 08 '22 18:11

Tim C