This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]