Re: [xsl] value of xsl:param in xsl:sort

Subject: Re: [xsl] value of xsl:param in xsl:sort
From: Joerg Pietschmann <joerg.pietschmann@xxxxxx>
Date: Thu, 14 Feb 2002 10:32:06 +0100
"Kunal H. Parikh" <kunal@xxxxxxxxxx> wrote:
[a FAQ]
> <xsl:param name="sortCriteria">TAP/TutorialList/Tutorial/AuthorList/Author/Name</xsl:param>
...
>    <xsl:for-each select="TAP/TutorialList/Tutorial">
>      <xsl:sort select="$sortCriteria" order="ascending"></xsl:sort>

The attribute value of the select attribute of xsl sort is a
XPath expression. The expression "$sortCriteria" evaluates
to the string value you have assigned to it: "TAP/TutorialList/..."
You expect the processor to interpret this string as a XPath
and evaluate it again to get the sort key you intended, but
this does not happen by design. Writing
  <xsl:param name="sortCriteria">TAP/TutorialList</xsl:param>
  ...
       <xsl:sort select="$sortCriteria"/>
is exactly equivalent to
       <xsl:sort select="'TAP/TutorialList'"/>
note the small difference to the indended expression
       <xsl:sort select="TAP/TutorialList"/>
the first one uses the constant string 'TAP/TutorialList'
while the second uses the the node set TAP/TutorialList
for computing the sort key. Using a constant string as sort
key for all elements results of course in no sorting.

There are several ways to overcome the apparent restriction.
Before i go on, i have to tell you that while computing the
sort key the element for which the key is computed is the
context element, so your selection path TAP/TutorialList/Tutorial/Aut...
is unlikely to work for sorting the TAP/TutorialList/Tutorial
list, you probably wanted AuthorList/Author/Name only.

If your sort criterium is a single element name, you can use
the well known trick
       <xsl:sort select="*[name()=$sortCriteria]"/>
or in your case, you could sort for various attributes of authors
by using
       <xsl:sort select="AuthorList/Author/*[name()=$sortCriteria]"/>
you could set $sortCriteria to name or, say, phone.
If your sort criteria represent more complex, you could first
try to expand on the schema above, like
  <xsl:param name="sortCriteriaStep1">AuthorList</xsl:param>
  <xsl:param name="sortCriteriaStep2">Author</xsl:param>
  <xsl:param name="sortCriteriaStep3">Name</xsl:param>
...
  <xsl:sort select="*[name()=$sortCriteriaStep1]/*[name()=$sortCriteriaStep2]/*[name()=$sortCriteriaStep3]/"/>

Because this becomes unwieldy soon, you might want to look up
whether you processor supports an evaluate() function. Saxon
and Xalan have one. MSXML does not, but you can build one using
JavaScript, look it up in the archive of this list. The evaluate()
function does exactly what you want, it takes a string and
evaluates it as XPath expression, so you can write
       <xsl:sort select="xyz:evaluate($sortCriteria)"/>
Check your processors documentation for the exact way how to do
it.

A further note: your sort criterium will sort the tutorials by the
name name of the first author in the author list. For example
  <TutorialList>
     <Tutorial>
       <AuthorList>
          <Author><Name>Zielinsky</Name></Author>
          <Author><Name>Apertius</Name></Author>
       </AuthorList>
     </Tutorial>
     <Tutorial>
       <AuthorList>
          <Author><Name>Burgerberger</Name></Author>
       </AuthorList>
     </Tutorial>
  </TutorialList>
will be reversed. This may or may not be what you actually want.

Last note: Please trim unnecessary quotations in replies.

J.Pietschmann

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


Current Thread