SvenL
SvenL

Reputation: 779

xsl:sort, why is it not working?

i'm trying to generate html pages by using xslt (using VS 2010 as the editor and 'compiler/transformer'). Most of this works well and generates valid xhtml, but when trying to generate a sorted list with the help of <xsl:sort /> the order is not affected at all. I have seen it work, but when trying to determine my problem and creating the sample code below, none of my <xsl:sort /> worked.

Please, who can show me my error.

Below are my sample files.

sample.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="sample.xsl" ?>
<people>
    <person name="Jack" age="12">
        <adress>First road</adress>
    </person>
    <person name="Bob" age="8">
        <adress>Third road</adress>
    </person>
    <person name="Peter" age="20">
        <adress>Second road</adress>
    </person>
    <person name="Juli" age="65">
        <adress>Last road</adress>
    </person>
    <person name="Abbot" age="21">
        <adress>No road</adress>
    </person>
</people>

sample.xsl

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">

    <xsl:output
        method="xml"
        omit-xml-declaration="yes" indent="yes"
        doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
        doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" />

    <xsl:template match="/">
        <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
            <head>
                <title>Sample</title>

                <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            </head>

            <body>
                <h2>By @name</h2>
                <div>
                    <xsl:for-each select="people/person">
                        <xsl:sort select="@name" data-type="text" order="ascending" />
                        <xsl:value-of select="@name" />
                        <xsl:element name="br" />
                        <xsl:text />
                    </xsl:for-each>
                </div>
                <hr />
                <h2>By @age</h2>
                <div>
                    <xsl:for-each select="people/person">
                        <xsl:sort select="@age" data-type="number" order="ascending" />
                        <xsl:value-of select="@age" />
                        <xsl:element name="br" />
                        <xsl:text />
                    </xsl:for-each>
                </div>
                <hr />
                <h2>By adress</h2>
                <div>
                    <xsl:for-each select="people/person">
                        <xsl:sort select="adress" data-type="text" order="ascending" />
                        <xsl:value-of select="adress" />
                        <xsl:element name="br" />
                        <xsl:text />
                    </xsl:for-each>
                </div>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

Upvotes: 5

Views: 2469

Answers (1)

Bert
Bert

Reputation: 82439

You can fix this in your stylesheet by changing the stylesheet version to 1.0. In other words, change

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">

To

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">

This appears to be a bug in the .net 4 xsl transform code. See this related stackoverflow question, Problem with XSL sorting.

What appears to happen is whenever you attempt to sort by an attribute, it actually sorts by the first child element. For example, change your XML to this and the names will sort properly:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="Sample.xslt" ?>
<people>
  <person name="Jack" age="12">
    <name>Jack</name>
    <adress>First road</adress>
  </person>
  <person name="Bob" age="8">
    <name>Bob</name>
    <adress>Third road</adress>
  </person>
  <person name="Peter" age="20">
    <name>Peter</Name>
    <adress>Second road</adress>
  </person>
  <person name="Juli" age="65">
    <name>Juli</Name>
    <adress>Last road</adress>
  </person>
  <person name="Abbot" age="21">
    <name>Abbot</Name>
    <adress>No road</adress>
  </person>
</people>

I found a response from Microsoft about the issue here, http://connect.microsoft.com/VisualStudio/feedback/details/620628/problem-with-xsl-sort-nodes-when-using-xslcompiledtransform, which led me to the fix I suggested above. You might try playing around with the version number for the stylesheet to see what does and does not work.

Upvotes: 5

Related Questions