This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Sorting on a variable
- To: xsl-list at mulberrytech dot com
- Subject: Sorting on a variable
- From: "John E. Simpson" <simpson at polaris dot net>
- Date: Sun, 15 Oct 2000 13:06:05 -0400
- Reply-To: xsl-list at mulberrytech dot com
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