This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: IF-ELSE.. Sorting
- To: pcaspian at iafrica dot com
- Subject: Re: [xsl] IF-ELSE.. Sorting
- From: Jeni Tennison <mail at jenitennison dot com>
- Date: Mon, 18 Jun 2001 13:19:11 +0100
- CC: xsl-list at lists dot mulberrytech dot com
- Organization: Jeni Tennison Consulting Ltd
- References: <3.0.1.32.20010618120738.00de5ac0@pe-pop01.iafrica.com>
- Reply-To: xsl-list at lists dot mulberrytech dot com
Hi Karlo,
> * Hi, I am trying to do a conditional sort. I want to have a look at an
> input parameter $arrangeby and if this is of Type DATE then I would like to
> specify a sorting different from my usual
>
> <xsl:sort select="*[name()=$arrangeby]"/>
>
> as now I want to specify the data-type as "number" and then also
> break it up into substring-before and substring-after, I will want
> to specify a different <xsl:sort>, so I assumed I would use <xsl:if
> test="$arrangeby = 'DATE'"> and put in my xsl code and finish it off
> with </xsl:if>.
If you need to specify an 'else' condition, then you need to use
xsl:choose/xsl:when/xsl:otherwise rather than xsl:if. For example,
you could store the data type that you wanted to use with:
<xsl:variable name="dataType">
<xsl:choose>
<xsl:when test="$arrangeby = 'DATE'">number</xsl:when>
<xsl:otherwise>text</xsl:otherwise>
</xsl:choose>
</xsl:variable>
The $dataType variable will have the value 'number' when the
$arrangeby parameter is 'DATE' and the value 'text' otherwise.
The data-type attribute on xsl:sort is an attribute value template.
Anything that you put within {}s in the value will be evaluated as an
XPath to give the value used for the attribute. This means that you
can create this variable before the xsl:for-each, and then use it
within the xsl:sort as follows:
<xsl:for-each select="LIST/ASSIGN">
<xsl:sort select="*[name() = $arrangeby]"
data-type="{$dataType}" />
...
</xsl:for-each>
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.)
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list