[xsl] Re: IF-ELSE.. Sorting

Subject: [xsl] Re: IF-ELSE.. Sorting
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Mon, 18 Jun 2001 07:56:37 -0700 (PDT)
Jeni Tennison wrote:

> However, as you want to use substring-before() and substring-after()
> in this case, you also need to do something complicated within the
> select attribute to alter what expression is used according to the
> $arrangeby parameter. Unfortunately, this isn't possible in pure XSLT
> 1.0, and you can't wrap the xsl:sort within a xsl:if or xsl:choose.
> It's easiest to this with two separate xsl:for-eaches:
>   <xsl:choose>
>      <xsl:when test="$arrangeby = 'DATE'">
>         <xsl:for-each select="LIST/ASSIGN">
>            <xsl:sort select="substring-before(DATE, 'T')"
>                      data-type="number" />
>            ...
>         </xsl:for-each>
>      </xsl:when>
>      <xsl:otherwise>
>         <xsl:for-each select="LIST/ASSIGN">
>            <xsl:sort select="*[name() = $arrangeby]" />
>            ...
>         </xsl:for-each>
>      </xsl:otherwise>
>   </xsl:choose>
> (You would probably be better off changing the xsl:for-eaches into
> xsl:apply-templates in this case - that way you could place the common
> processing in a common template rather than repeating it.)
> Or, if you're willing to use extensions and are using a processor like
> Saxon or Xalan that has an evaluate() function, then you could
> construct the expression that you want to use as a string within a
> variable, and then evaluate that expression within the select
> attribute.  This also enables you to use an expression consisting of
> the value of the $arrangeby attribute (i.e. the name of the child
> element that you're using to sort by) rather than using *[name() =
> $arrangeby] to get at it:
>    <xsl:variable name="selectExpression">
>       <xsl:choose>
>          <xsl:when test="$arrangeby = 'DATE'">
>             <xsl:text>substring-before(DATE, 'T')</xsl:text>
>          </xsl:when>
>          <xsl:otherwise>
>             <xsl:value-of select="$arrangeby" />
>          </xsl:otherwise>
>       </xsl:choose>
>    </xsl:variable>
>    <xsl:variable name="dataType">
>       ...
>    </xsl:variable>
>    <xsl:for-each select="LIST/ASSIGN">
>       <xsl:sort select="saxon:evaluate($selectExpression)"
>                 data-type="{$dataType}" />
>       ...
>    </xsl:for-each>
> (Note that to use this extension function you need to declare the
> 'saxon' namespace and be using Saxon; as I say, Xalan has a similar
> extension function if you're using that.)

This nice explanation illustrates extremely well why we need to use a generic sort
template in this case.

And, Jeni certainly knows that well, this kind of sorting can be achieved without
using any extension functions in 100% pure XSLT.

Where any use of a generic sort() will be natural, any attempt to use xsl:sort for
cases far from the most trivial -- these will look perverted and totally
incomprehensible to anybody but their author.

This is because xsl:sort needs a sort-key as ***one*** expression to be specified as
the value of its select attribute.

Contrary to this, a generic sort template leaves to the caller-supplied template the
definition of what a sort-key is and how sort-keys should be compared.

Dimitre Novatchev.

Do You Yahoo!?
Spot the hottest trends in music, movies, and more.

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

Current Thread