Re: [xsl] xsl:sort problem

Subject: Re: [xsl] xsl:sort problem
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Mon, 8 Apr 2002 23:15:22 +0100
Hi Danny,

> When I try to load my XML file I get the following error:
>
> Keyword xsl:apply-templates may not contain xsl:sort. 
>
> I don't understand. Everywhere I look it says that xsl:sort can be
> contained in xsl:for-each and xsl:apply-templates. So, what's the
> problem?

You're probably trying to use XSLT with MSXML2, which doesn't support
XSLT. You need to upgrade to MSXML3 or MSXML4, which do support XSLT.
If you're doing client-side transformation in Internet Explorer, you
need MSXML3 installed in replace mode. See the MSXML FAQ at
http://www.netcrucible.com/xslt/msxml-faq.htm.

Even if you use the correct processor, though, I think that you will
have problems with your code:

> <xsl:template match='PEOPLE'>
>      <xsl:for-each select='PERSON'>
>           <TR>
>                <xsl:apply-templates>
>                 <xsl:sort select='LAST_NAME'/>
>            </xsl:apply-templates>
>           </TR>
>      </xsl:for-each>
> </xsl:template>

This tells the processor that when it finds a PEOPLE element, it
should process each of its child PERSON elements in document order.
For each of those PERSON elements, it should create a TR element. For
the content of that TR element, it should apply templates to the child
nodes of the PERSON element, sorted in alphabetical order based on
their child LAST_NAME element. The kind of structure this implies is:

  PEOPLE
    +- PERSON
        +- some element
            +- LAST_NAME

> <xsl:template match='PERSON'>
>      <TD><xsl:value-of select='FIRST_NAME'/></TD>
>      <TD><xsl:value-of select='LAST_NAME'/></TD>
>      <TD><xsl:value-of select='BIRTH_DATE'/></TD>
> </xsl:template>

This template would be used if you ever applies templates to PERSON
elements, which I doubt that you do (although you might, if you have
PERSON elements nested inside each other). Each PERSON element creates
a number of TD elements for the FIRST_NAME, LAST_NAME and BIRTH_DATE
element children of the PERSON element.

I think that what you probably want is to apply templates to the
PERSON elements in the order of their LAST_NAME element children, and
create a TR element for each:

<xsl:template match='PEOPLE'>
  <xsl:apply-templates select='PERSON'>
    <xsl:sort select='LAST_NAME'/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match='PERSON'>
  <TR>
    <TD><xsl:value-of select='FIRST_NAME'/></TD>
    <TD><xsl:value-of select='LAST_NAME'/></TD>
    <TD><xsl:value-of select='BIRTH_DATE'/></TD>
  </TR>
</xsl:template>

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread