Question

I would like to sort data This is the xml file

<item name="HOUSE 10">
</item>
<item name="HOUSE 2">
</item>
<item name="MY 3 APPARTMENT">
</item>
<item name="MY 15 APPARTMENT">
</item>

I would like to get: "HOUSE 2,HOUSE 10, MY 3 APPARTMENT, MY 15 APPARTMENT"

But I get "HOUSE 10,HOUSE 2, MY 15 APPARTMENT 15, MY 3 APPARTMENT"

NOTE

I am really really SORRY

of course HOUSE must come before MY

Sorry I did not really understand your remarks until now

END OF NOTE

My xlst is:

<xsl:for-each select="//item>
<xsl:sort data-type="number" select="./@name"/>
</xsl>

How can I make it ?

EDITED1: there is no "logic" about the number or position of numerical values in the labels, the numerical values can be placed anywhere.

EIDTED2: I came up with an idea and I am almost there

I created a Java function This function concatenes the number with the postion of the highest digit. basically it returns

HOUSE 10 => HOUSE 210
HOUSE 2 => HOUSE 12
MY 3 APPARTMENT => MY 13 APPARTMENT
MY 15 APPARTMENT => MY 215 APPARTMENT

public static String concateneHighestDigit(String name){
    Pattern digitPattern = Pattern.compile("(\\d+)"); // 

    Matcher matcher = digitPattern.matcher(name);
    StringBuffer result = new StringBuffer();
    int i = 0;
    while (matcher.find())
    {
         matcher.appendReplacement(result, String.valueOf(matcher.group(1).length())+ matcher.group(1));
    }
    matcher.appendTail(result);
    System.out.println("result :" + result);
    return result.toString();

}

and in the xlst I have

 <xsl:sort data-type="number" select="special:concateneHighestDigit(./@name)"/>

where

  special

correponds to a customized xmlns

It still does not work, but I think I am not too far

Was it helpful?

Solution 3

Found it!

By changing form "number" to "text", it works. Still I do not understand why

<xsl:sort data-type="text" select="special:concateneHighestDigit(./@name)"/>

Thanks to you all for your support and your remarks ! It really helped to debug !

OTHER TIPS

You are sorting a string as number. It won't sort correctly.

Also, you want to order strings by character order, and the numbers by numerical order. To achieve this you have to separate the terms and order strings and numbers separately. You can do this with two xsl:sorts:

<xsl:for-each select="item">
    <xsl:sort data-type="text"   select="substring-before(@name, ' ')"/>
    <xsl:sort data-type="number" select="substring-after(@name, ' ')"/>
    <item><xsl:value-of select="@name"/></item>
</xsl:for-each>

This will work considering you have one word followed by one number, since substring-before and substring-after will return the strings before or after the first space.

UPDATE

You edited your question with new requirements:

  • there is one number and it can appear anywhere in the text;
  • the text may have spaces anywhere.

You can still use the two xs:sort expressions. You just have to find a way to extract the numbers and the strings to use them in ordering. If you can use XSLT 2.0 then you can use a regular expression for that. This code removes the digits or the non-digits to obtain the sorting data for each case:

<xsl:for-each select="item">
     <xsl:sort data-type="text" select="normalize-space(replace(@name, '\d+',''))"/>
     <xsl:sort data-type="number" select="normalize-space(replace(@name, '\D+',''))"/>
     <item><xsl:value-of select="@name"/></item>
</xsl:for-each>

Saxon has a collation that will do this kind of sorting:

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

This will sort "house 2" before "house 10". But it will sort "house 2" before "my 3 apartment", because "h" sorts before "m".

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top