XSL Sort treats lowercase letters separately from uppercase

My XSLT sorts names in alphabetical order, but I just noticed that some names start with "de" and "von" or "van". These lowercase prefixes are sorted and placed after the uppercase name. How do I tell XSLT to sort all cases?

Using XSLT 1.0

Here's a section that sorts data:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="Data">
<xsl:strip-space elements="*"/>
<xsl:template match="Data">
<xsl:copy>
<xsl:apply-templates select="Consultant">
<xsl:sort select="Surname" order="ascending" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>  
<xsl:template match="Consultant">
<consultant><Surname><xsl:value-of select="Surname"/></Surname>
<FirstName><xsl:value-of select="FirstName"/></FirstName>
<!--…-->
</consultant>
</xsl:template>
</xsl:stylesheet>

Here is an example XML:

<?xml version="1.0" encoding="UTF-8"?>
<Data>
<consultant>
<Surname>Arnon</Surname>
<FirstName>Lana</FirstName>
</consultant>
<consultant>
<Surname>von Armon</Surname>
<FirstName>George</FirstName>
</consultant>
<consultant>
<Surname>Arnon</Surname>
<FirstName>Lana</FirstName>
</consultant>
<consultant>
<Surname>de Armon</Surname>
<FirstName>George</FirstName>
</consultant>
</Data>
+3
source share
5 answers

You need to normalize the register to <xsl:sort/>

If your environment supports XPATH 2.0, you can use either uppercase () or lowercase (), as shown below:

<xsl:sort select="upper-case(Surname)" order="ascending" />

If your environment does not support XPATH 2.0, you will need to use translate (), as shown below:

<xsl:sort select="translate(Surname, 'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')" order="ascending" />
+3

translate() - , , lang <xsl: sort> - . http://www.w3.org/TR/xslt#sorting.

+1

XSLT-, 1.0, 2.0.

lang="nl" ( - ) xsl: sort, .

+1

XSLT 2.0, . translate xsl:sort

<xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />

<xsl:sort select="translate(Surname, $smallcase, $uppercase)" order="ascending" />
0

, . , "van", "de" .. .

If so, simply translating the lower letters to nothing may work.

Style sheet (adapted from @therealmarv solution)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
    <xsl:variable name="uppercase" select="''" />

    <xsl:template match="Data">
    <xsl:copy>
    <xsl:apply-templates select="consultant">
    <xsl:sort select="translate(Surname, $smallcase, $uppercase)" order="ascending" />
    </xsl:apply-templates>
    </xsl:copy>
    </xsl:template>

    <xsl:template match="consultant">
    <consultant><Surname><xsl:value-of select="Surname"/></Surname>
    <FirstName><xsl:value-of select="FirstName"/></FirstName>
    <!--…-->
    </consultant>
    </xsl:template>
</xsl:stylesheet>

Output

<?xml version="1.0" encoding="utf-8"?>
<Data>
   <consultant>
      <Surname>von Armon</Surname>
      <FirstName>George</FirstName>
   </consultant>
   <consultant>
      <Surname>de Armon</Surname>
      <FirstName>George</FirstName>
   </consultant>
   <consultant>
      <Surname>Arnon</Surname>
      <FirstName>Lana</FirstName>
   </consultant>
   <consultant>
      <Surname>Arnon</Surname>
      <FirstName>Lana</FirstName>
   </consultant>
</Data>
0
source

All Articles