Reputation: 775
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
Upvotes: 2
Views: 115
Reputation: 775
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 !
Upvotes: 0
Reputation: 163322
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".
Upvotes: 1
Reputation: 23637
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:sort
s:
<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:
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>
Upvotes: 1