xsl-list
[Top] [All Lists]

Re: Sort question

2003-02-27 13:30:30

"Tom Whitehouse" <whitehousetom(_at_)hotmail(_dot_)com> wrote in message
news:F126URGEekE30OScycU000090f2(_at_)hotmail(_dot_)com(_dot_)(_dot_)(_dot_)
Is it possible to sort a set of elements with an unknown number of sort
keys:

[snip]

I need to sort this in the first instance depending on the first crumb
element, then if two crumbtrails share identical values on the second
crumb
element etc.etc.

The problem is There could be any number of crumb elements and I don`t
want
to have to write

<xsl:sort select="crumb[1]"/>
<xsl:sort select="crumb[2]"/>
<xsl:sort select="crumb[3]"/>
<xsl:sort select="crumb[4]"/>
<xsl:sort select="crumb[5]"/>
.
.
etc.

as the sort key since there could be any number of crumb elements.


For your type of xml source document, yes, it is possible.

The following transformation:

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

  <xsl:output omit-xml-declaration="yes"/>

  <xsl:variable name="vWhite" select="' &#10;&#13;'"/>
  <xsl:variable name="vLowest" select="'&#9;&#9;&#9;'"/>

  <xsl:template match="/">
    <sorted>
       <xsl:for-each select="/*/crumbtrail">
         <xsl:sort select="translate(., $vWhite, $vLowest)"/>

         <xsl:copy-of select="."/>
       </xsl:for-each>
    </sorted>
  </xsl:template>
</xsl:stylesheet>


when applied on this source.xml:

<root>
  <crumbtrail>
    <crumb>top</crumb>
    <crumb>sport</crumb>
    <crumb>football</crumb>
    <crumb>liverpool</crumb>
  </crumbtrail>
  <crumbtrail>
    <crumb>top3</crumb>
    <crumb>spo</crumb>
    <crumb>foot</crumb>
    <crumb>liverpool</crumb>
  </crumbtrail>
  <crumbtrail>
    <crumb>top</crumb>
    <crumb>sport</crumb>
  </crumbtrail>
  <crumbtrail>
    <crumb>top2</crumb>
    <crumb>sportX</crumb>
  </crumbtrail>
  <crumbtrail>
    <crumb>top2</crumb>
    <crumb>spo</crumb>
  </crumbtrail>
  <crumbtrail>
    <crumb>top</crumb>
    <crumb>sport</crumb>
    <crumb>cricket</crumb>
  </crumbtrail>
</root>

produces this result:

<sorted><crumbtrail>
    <crumb>top</crumb>
    <crumb>sport</crumb>
  </crumbtrail><crumbtrail>
    <crumb>top</crumb>
    <crumb>sport</crumb>
    <crumb>cricket</crumb>
  </crumbtrail><crumbtrail>
    <crumb>top</crumb>
    <crumb>sport</crumb>
    <crumb>football</crumb>
    <crumb>liverpool</crumb>
  </crumbtrail><crumbtrail>
    <crumb>top2</crumb>
    <crumb>spo</crumb>
  </crumbtrail><crumbtrail>
    <crumb>top2</crumb>
    <crumb>sportX</crumb>
  </crumbtrail><crumbtrail>
    <crumb>top3</crumb>
    <crumb>spo</crumb>
    <crumb>foot</crumb>
    <crumb>liverpool</crumb>
  </crumbtrail></sorted>


Of course, this is quite special case. In order for this to work two things
must be assured:

1. Whitespace nodes in the xml source must be preseved.

2. The "lowest character" for the given XSLT processor must be known in
advance, so that it can be used as the intended result of translating the
white-space.

3. The text-nodes children of crumb may contain only one (and the same) type
of whitespace character (e.g. only blanks are allowed).

Note that because the implementation of xsl:sort differs on different XSLT
processors (or even between different versions of the same XSLT procesor --
e.g. Xalan-J and Xalan-C), different results may be produced if the
xsl:variable "vLowest" is not set appropriately.

The above result is produced by: MSXML3/4, MS .Net xslTransform, Saxon
6.5.2, XalanC 1.3.

In order for XalanJ 2.4.1 to produce the same results the following should
be specified:

  <xsl:variable name="vLowest" select="000"/>


These limitations can be avoided if a generic-template/functional sort
implementation is used (or I guess in XSLT2 too).


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL





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



<Prev in Thread] Current Thread [Next in Thread>