zero after decimal point dropped when no number before decimal point, .06 cents becomes .60 cents

rcheney
rcheney used Ask the Experts™
on
When I transform my XML to HTML, I lose the zero after the decimal point, IF, there is no number before the decimal point.

In the XML                  In the HTML

1.06                        1.06
0.06                        0.6
.06                        0.6

My XSL

<xsl:template match="value">
<xsl:choose>
  <xsl:when test=".!=''">
    <xsl:choose>
      <xsl:when test="number(.)=number(.)">
        <xsl:value-of select="format-number(.,'###,##0.0###')" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="." />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:when>

I have tried (.,'###,##0.####')
and      (.,'###,##0.00##'),    etc.,  with no luck.    6 cents always ends up as 60 cents.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
Hi rcheney:

What are you using for your parser?  I passed the above numbers and stylesheet through Xalan, and it returns the correct results.



-Xikilm

Author

Commented:
I am using Altova, the "XML Spy" parser.

Commented:
Just did a quick search and found this:

http://www.altova.com/Fixed_Defects.html
3573 | XSLT format-number removes leading 0 from decimal part of value | Spy Ent | AltovaXSLT

Sounds like its a known problem that is fixed in "Release 3".  HTH.


-Xikilm
Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

weareuProgrammer

Commented:
It is a known problem and it was supposedly fixed in release 3 but it still doesn't seem to always work correctly... I suggest just writing an ugly little hack which check if the value starts with either 0 or '.' and then after formatting just selecting the value of the first part (before the '.') + a '.0' and then the value after the '.'. Quite nasty but successful.

Author

Commented:
You are right.  They either didn't fix it, or it was working correctly and they broke it.  Anyway I agree the nasty hack is the way to go.  Could I trouble you for a little help or just point me in the right direction.  I started the hack by finding the decimal point and zero like you said <xsl:when test="contains(number(.),'.0')">  but how do I split the number and deal with the before and after the decimal point parts?

<xsl:template match="value">
<xsl:choose>
<xsl:when test=".!=''">
<xsl:choose>
<xsl:when test="number(.)=0">0</xsl:when>
<xsl:when test="number(.)=number(.)">
<xsl:choose>
<xsl:when test="contains(number(.),'.0')">

Here I find the decimal point zero but how do I split the before and after and format separately??

</xsl:when>
</xsl:choose>
<xsl:value-of select="format-number(.,'###,##0.0###')"/></xsl:when>

Author

Commented:
I think I need to make a parameter and then create the before and after variables.

<xsl:param name="numwithdecimal" select="number(.)"/>
<xsl:variable name="beforedecimal" select="substring-before(numwithdecimal, '.')"/>
<xsl:variable name="afterdecimal" select="substring-before(substring-after(numwithdecimal, '.'),'.')"/>

and then (after formatting the separate pieces) put the result back together like below

<xsl:when test="contains(number(.),'.0')">
<xsl:value-of select="beforedecimal"/> AND <xsl:value-of select="afterdecimal"/>

    How do I format the separate pieces?
Programmer
Commented:
<xsl:template match="value">
<xsl:choose>
  <xsl:when test=".!=''">
    <xsl:choose>
      <xsl:when test="number(.)=number(.)">
         <xsl:choose>
            <xsl:when test="starts-with(.,'.') or starts-with(.,'0')">
                  <xsl:value-of select="format-number(number(substring-before(.,'.')),'###,###')"/>.0<xsl:value-of select="format-number(number(substring-after(.,'.')),'##')"/>
             </xsl:when>
             <xsl:otherwise>
                <xsl:value-of select="format-number(.,'###,##0.0###')"/>
             </xsl:otherwise>
         </xsl:choose>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="." />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:when>
  <xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:template>

couldn't really test this, but see if it works or if you could rip it appart and make it work...

Author

Commented:
Thanks that looks great.  I haven't had time to test it yet but it gets me close enough so I can tweak it, if necessary.   A big thanks to wearu and  Xikilm.

Commented:
When I run ".06" through it returns a "NaN.06".  Not sure if you're having similar problems with your parser.  If so, you can fix it with:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:decimal-format name="test" NaN="0"/>
    <xsl:template match="value">
<xsl:choose>
  <xsl:when test=".!=''">
    <xsl:choose>
      <xsl:when test="number(.)=number(.)">
         <xsl:choose>
            <xsl:when test="starts-with(.,'.') or starts-with(.,'0')">
                  <xsl:value-of select="format-number(number(substring-before(.,'.')),'###,###','test')"/>.0<xsl:value-of select="format-number(number(substring-after(.,'.')),'##')"/>
             </xsl:when>
             <xsl:otherwise>
                <xsl:value-of select="format-number(.,'###,##0.0###')"/>
             </xsl:otherwise>
         </xsl:choose>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="." />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:when>
  <xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>


-Xikilm

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial