How do I sort XML records that contain numbers but sometimes also contain letters?

I have these id values ​​that I want to sort:

<rule id="1.1">
</rule>
<rule id="1.2">
</rule>
<rule id="1.3">
</rule>
<rule id="Id. 4.3">
</rule>
<rule id="Id. 4.9">
</rule>
<rule id="Id. 4.10">
</rule>
<rule id="Id. 4.11">
</rule>
<rule id="Id. 4.12">
</rule>

      

I am currently trying to sort like this. This works for id values ​​that only have numbers, but not those that also have letters.

<xsl:sort select="substring-before(@id, '.')" data-type="number"/>
<xsl:sort select="substring-after(@id, '.')" data-type="number"/>

      

The order I am currently giving:

Id. 4.10
Id. 4.11
Id. 4.12
Id. 4.3
Id. 4.9
1.1
1.2
1.3

      

How can I sort it so that the order is:

Id. 4.3
Id. 4.9
Id. 4.10
Id. 4.11
Id. 4.12
1.1
1.2
1.3

      

+3


source to share


2 answers


The order you show can be executed with:

<xsl:sort select="number(starts-with(@id, 'Id. '))" data-type="number" order="descending"/>
<xsl:sort select="substring-before(replace(@id, '^Id. ', ''), '.')" data-type="number"/>
<xsl:sort select="substring-after(replace(@id, '^Id. ', ''), '.')" data-type="number"/>

      




This can be simplified with an attribute collation

(which would also handle more levels in your numbering scheme, such as "1.10.2"), however this depends on which processor you are using.

+2


source


XSLT 3.0 defines the mapping URI for this:

<xsl:sort collation="http://www.w3.org/2013/collation/UCA?numeric=yes"/>

      

This treats any sequence of digits as a number, so 2.20 (a) -3 will sort before 2.20 (a) -10 and after 2.8 (b) -4.

But this (I think) will put "id. 4.10" after "1.3". To solve this, you will need to precede another sort key

<xsl:sort select="not(starts-with(., 'id'))"/>

      



(false sorts to true)

This is implemented in current Saxon releases. Earlier Saxon releases provide mapping URIs

http://saxon.sf.net/collation?alphanumeric=yes

      

with similar semantics.

If that doesn't work for you, then if you always have the same number of numeric components, you can split the value up using regular expressions and use multiple sort keys.

+2


source







All Articles