xsl-list
[Top] [All Lists]

RE: [xsl] xsl:sort descending causes attribute nodes to be created after children, causing an error

2007-01-16 06:33:08
            <xsl:apply-templates select="node() | @*">
                <xsl:sort
                    select="text()"
                    order="descending" />
            </xsl:apply-templates>

For attribute nodes the value of the sort key (child::text()) will always be
an empty sequence. An empty sequence sorts before any other value, so in
descending order it sorts last, and since the template with match="@*"
creates attribute nodes, you will be adding attributes to the parent after
the children, which is an error.

This behaviour is certainly correct, and I'm not sure which part of it you
are questioning.

Incidentally, if any of your child elements contains an embedded comment,
the sort will fail because text() selects more than one node, and it's an
error in 2.0 for the sort key to be a sequence longer than one (in 1.0 all
but the first are ignored).

Michael Kay
http://www.saxonica.com/

-----Original Message-----
From: Abel Braaksma [mailto:abel(_dot_)online(_at_)xs4all(_dot_)nl] 
Sent: 16 January 2007 13:01
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: [xsl] xsl:sort descending causes attribute nodes to 
be created after children, causing an error

Hi XSLT'ers,

The following issue is easy to workaround, but I am wondering 
if this is correct behavior after the XSLT 2 (or even 1) 
recommendation.

With an xsl:apply-template that includes attribute nodes in 
its select-attribute, and you apply an xsl:sort on the 
children, then it happens that the attribute nodes are 
created after the children when the order of xsl:sort is 
descending. I tried google on this, but couldn't find 
something useful.

The example below throws the following error:
"An attribute node (count) cannot be created after the 
children of the containing element"

I did not try other parsers. The xslt employs a simple copy 
idiom and sorts the rows of the input in $data. Call the XSLT 
on itself to see the error or the results:

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

    <xsl:output indent="yes" />
   
    <xsl:variable name="data">
        <rows count="3">
            <row>bbbb</row>
            <row>aaaa</row>
            <row>cccc</row>
        </rows>
    </xsl:variable>
   
    <xsl:template match="/">
        <xsl:apply-templates select="$data/*" />
    </xsl:template>
   
    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="rows">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*">
                <xsl:sort
                    select="text()"
                    order="descending" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>


Any thoughts on this? Is this behavior desired and/or 
required, or is this the processor's mistake?

Btw: a possible workaround is to apply the attribute node first.

Cheers,
-- Abel Braaksma
   http://www.nuntia.nl



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--