This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
RE: Sorting on a variable
- To: "'xsl-list at mulberrytech dot com'" <xsl-list at mulberrytech dot com>
- Subject: RE: Sorting on a variable
- From: Kay Michael <Michael dot Kay at icl dot com>
- Date: Mon, 16 Oct 2000 10:39:44 +0100
- Reply-To: xsl-list at mulberrytech dot com
This is one of those things that "can't be done" in standard XSLT.
Two suggestions:
- create an (unsorted) copy of the node-set, adding the computed sort key as
an additional attribute, then use the node-set() extension to do a second
pass.
- use the saxon:function extension, which allows you to write an extension
function in XSLT and use it in contexts such as a sort key.
- try to write your computed sort key in pure XPath. Without conditional
expressions, it's not easy, but it can be done. There's a horrible hack that
relies on strange properties of the substring function:
substring("xyz", 1 div (condition)) equals "xyz" if condition is true, and
"" if condition is false.
Mike Kay
> -----Original Message-----
> From: John E. Simpson [mailto:simpson@polaris.net]
> Sent: 15 October 2000 18:06
> To: xsl-list@mulberrytech.com
> Subject: Sorting on a variable
>
>
> I've got XML which looks like this:
>
> <products>
> <product prodID="A1234">
> <name>First prod</name>
> <price curr="USD">29.95</price>
> </product>
> <product prodID="A5678">
> <name>Second prod</name>
> <price curr="GBP">29.95</price>
> </product>
> <product prodID="A9012">
> <name>Third prod</name>
> <price curr="EU">29.95</price>
> </product>
> <product prodID="A9012">
> <name>Fourth prod</name>
> <price curr="USD">50.00</price>
> </product>
> </products>
>
> No problem at all displaying this as a table, sorted (or not)
> by name or
> price. But then I wanted to sort not by raw price, but by a
> single "USD
> equivalent" -- converting the price to a common denomination.
>
> Here's a variable to do the conversion (rates as of last night :):
>
> <xsl:variable name="usd_equiv">
> <xsl:choose>
> <xsl:when test="price/@curr='USD'">
> <xsl:value-of select="price"/>
> </xsl:when>
> <xsl:when test="price/@curr='GBP'">
> <xsl:value-of select="price * 1.47275"/>
> </xsl:when>
> <xsl:when test="price/@curr='EU'">
> <xsl:value-of select="price * 0.864379"/>
> </xsl:when>
> <xsl:otherwise>Unknown Currency</xsl:otherwise>
> </xsl:choose>
> </xsl:variable>
>
> (I've varied the values of the xsl:when test attributes in
> different ways;
> this is just the most current iteration, which assumes the
> context node to
> be a <product> element.)
>
> Using a variable with xsl:sort introduces a number of
> stylesheet structural
> problems. E.g., if you do the sort within a for-each, the
> xsl:sort must be
> a first child of the xsl:for-each... and of course the
> variable goes out of
> scope for use *by* the xsl:sort. But if you do xsl:sort as a child of
> xsl:apply-templates, well, xsl:variable is not a legitimate child of
> xsl:apply-templates.
>
> So then, rethinking a bit, I came up with what I thought was a fairly
> simple solution, a global variable:
>
> <xsl:variable name="product_usd">
> <xsl:for-each select="/products/product">
> <xsl:copy-of select="."/>
> <usd_equiv>
> <xsl:choose>
> <xsl:when test="price/@curr='USD'">
> <xsl:value-of select="price"/>
> </xsl:when>
> <xsl:when test="price/@curr='GBP'">
> <xsl:value-of select="price * 1.47275"/>
> </xsl:when>
> <xsl:when test="price/@curr='EU'">
> <xsl:value-of select="price * 0.864379"/>
> </xsl:when>
> <xsl:otherwise>Unknown Currency</xsl:otherwise>
> </xsl:choose>
> </usd_equiv>
> </xsl:for-each>
> </xsl:variable>
>
> Basically, this clones the <product> elements from the source
> tree (with
> xsl:copy-of select=".") into a variable ($prod_usd) as an
> RTF. And -- I
> thought -- it added an extra child element, <usd_equiv>, as a
> child of each
> <product> element. Then in the xsl:sort, instead of sorting
> the source
> tree, I'm sorting (with the node-set() function converting
> this RTF to a
> true node-set) the RTF contained by this variable, with
> <usd_equiv> as my
> sort key.
>
> Near as I can tell, this should be giving me *something*. The
> problem is
> that the <usd_equiv> element always seems to be empty.
>
> I feel really stupid. Must be missing something obvious...
> and at this
> point, have been banging my head against the problem for,
> like, 6 hours.
>
> Any ideas?
>
> THANKS in advance!
> ===============================================================
> John E. Simpson | "He asked me if I knew what
> http://www.flixml.org | time it was. I said, 'Yes, but
> XML Q&A: http://www.xml.com | not right now.'" (Steven Wright)
>
>
> XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
>
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list