xsl-list
[Top] [All Lists]

RE: [xsl] Temporary tree elements and namespaces

2008-02-13 14:48:47
I'm having trouble understanding this problem because it says "namespaces"
in the title (and in the prose) but there are no namespaces in the source
document or stylesheet.

The temporary tree seems a bit heavy to me. Why not just have a temporary
sequence of numbers?

  <xsl:template match="/values">
      <xsl:variable name="taxes" as="xs:decimal*">
        <xsl:for-each select="value">
          <xsl:sequence select="xs:decimal(format-number(., '#.00'))"/>
        </xsl:for-each>
    </xsl:variable>
    <xsl:for-each select="$taxes">
      <xsl:value-of select="."/>
      <xsl:text> || </xsl:text>
    </xsl:for-each>
    <xsl:value-of select="format-number(sum($taxes), '#.00')"/>
  </xsl:template>

which reduces further to

<xsl:template match="/values">
  <xsl:variable name="taxes" select="value/xs:decimal(format-number(.,
'#.00'))"/>
  <xsl:value-of select="$taxes, format-number(sum($taxes), '#.00')"
separator=" || "/>
</xsl:template>

You could also do the rounding using round-half-to-even(), which would avoid
formatting the number as a string only to convert it back to a number.

Note the general programming style here: as with SQL, it's useful to learn
to think in terms of processing sets of things in bulk without having to
iterate over them.

Michael Kay
http://www.saxonica.com/


 

-----Original Message-----
From: João Cruz Morais [mailto:spiderfish(_at_)gmail(_dot_)com] 
Sent: 13 February 2008 19:47
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: [xsl] Temporary tree elements and namespaces

Hello everyone,

I was about to finish converting a xml document to an excel 
xml file when I noticed that some tax values on the input 
file can have up to 4 decimal places while in the final 
document they are all being rounded to 2 decimal places which 
raises problems when you sum all of them, since the sum of 
the rounding might be different from the rounding of the sum.
Try 0.123 + 0.234 for example:
1: 0.123 => 0.12
2: 0.234 => 0.23
sum: 0.123 + 0.234 = 0.357 => 0.36 (not correct given the 
previous values)

To get rid of this problem I've decided it was a good idea to 
use a temporary tree that saves all the rounded values in 
advance, so I can show them individually and also present a 
correct sum in the end.
Everything went well with my sample tests but it didn't work 
in the final version. After some wasted hours I've figured 
out that the problem is the default namespace that Excel 
*requires* to be present.
As soon as I added a default namespace (xmlns="something") to 
my test stylesheet it stopped working too. When I thought 
about it, I realized that maybe the elements in the temporary 
tree weren't binded to the source default namespace and so 
I've added a namespace attribute to the xsl:element which 
unfortunately didn't do anything. What am I doing wrong?
Below goes both the xml and the xsl files. For the sake of 
simplicity I've cut down a lot of the content and a bit of 
the temp tree to only keep what matters. Also this version is 
working but if you had a default namespace to the stylesheet 
definition the select stops returning any nodes.
Finally I'm using Saxon 9 (great piece of software btw).

Thanks in advance,
João C. Morais

=== XML FILE ===

<?xml version="1.0" encoding="ISO-8859-1"?> <values>
  <value>0.123</value>
  <value>0.234</value>
</values>

=== XSL FILE ===

<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet 
version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  <xsl:output method="text"/>
  <xsl:template match="/values">
    <xsl:variable name="taxes" as="item()*">
      <xsl:for-each select="value">
        <xsl:element name="tax">
          <xsl:element name="value">
            <xsl:value-of select="number(format-number(., '#.00'))"/>
          </xsl:element>
        </xsl:element>
      </xsl:for-each>
    </xsl:variable>
    <xsl:for-each select="$taxes">
      <xsl:value-of select="value"/>
      <xsl:text> || </xsl:text>
    </xsl:for-each>
    <xsl:value-of select="format-number(sum($taxes/value), '#.00')"/>
  </xsl:template>
</xsl:stylesheet>

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--