We help IT Professionals succeed at work.

more questions on Converting 4e-3 to 0.004

meow00
meow00 asked
on
296 Views
Last Modified: 2013-11-18
Hi experts,

I have the following xml file:

<?xml version="1.0" encoding="UTF-8"?>
 <MyFile>
<MySchema>
    <MyField import="3.399e-001" name="name1" type="good"/>
    <MyField import="4.690e-001" name="name2" type="good"/>
    <MyField import="5.746e-001" name="name3" type="good"/>
    <MyField import="2.298e-001" name="name4" type="good"/>
    <MyField name="subject" type="bad"/>
</MySchema>
  </MyFile>
----------------------------------------------
and I want the output to be

<?xml version="1.0" encoding="UTF-8"?>
 <MyFile>
<MySchema>
    <MyField import="0.003399" name="name1" type="good"/>
    <MyField import="0.004690" name="name2" type="good"/>
    <MyField import="0.005746" name="name3" type="good"/>
    <MyField import="0.002298" name="name4" type="good"/>
    <MyField name="subject" type="bad"/>
</MySchema>
  </MyFile>
------------------------------------------
The following is my code, but it didn't work. Could anyone please help me? Thanks.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:template match="MySchema">
        <xsl:element name="MyField">
 
                <xsl:attribute name="import">
                    <xsl:value-of select="format-number(., '#.####')"/>
                </xsl:attribute>
         </xsl:element>
        <xsl:apply-templates/>
    </xsl:template>
    
    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <!-- go process attributes and children -->
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
    
    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

Open in new window

Comment
Watch Question

Author

Commented:
Actually, I made a little change in the above code:

Then the output becomes:
<?xml version="1.0" encoding="UTF-8"?><MyFile>
<MySchema>
    NaN
    NaN
    NaN
    NaN
    NaN
</MySchema>
  </MyFile>
-------------------------
Did I miss anything? Thanks!

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:template match="MyField">
            <xsl:value-of select="number(@import)" />
    </xsl:template>
    
    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <!-- go process attributes and children -->
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
    
    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

Open in new window

Author

Commented:
I added a bit more changes ... now the output is:

<?xml version="1.0" encoding="UTF-8"?><MyFile>
<MySchema>
    <MyField name="name1" type="good" import="NaN"/>
    <MyField name="name2" type="good" import="NaN"/>
    <MyField name="name3" type="good" import="NaN"/>
    <MyField name="name4" type="good" import="NaN"/>
    <MyField name="subject" type="bad" import="NaN"/>
</MySchema>
  </MyFile>

----------------------------------------------------
Does anyone know why? Thanks!

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:template match="MyField">
        <xsl:copy>
        <xsl:attribute name="name"><xsl:value-of select="@name" />
        </xsl:attribute>
            <xsl:attribute name="type"><xsl:value-of select="@type" />
            </xsl:attribute>
        <xsl:attribute name="import">
            <xsl:value-of select="number(@import)" />
        </xsl:attribute>
            </xsl:copy>
    </xsl:template>
    
    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <!-- go process attributes and children -->
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
    
    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

Open in new window

zc2
CERTIFIED EXPERT

Commented:
Actually, I don't know how to handle numbers with an exponent.
If you use a MSXML processor, you can try to use a script as follows:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
      xmlns:msxsl="urn:schemas-microsoft-com:xslt"
      xmlns:user="http://mycompany.com/mynamespace" version="2.0">
 
<msxsl:script language="JScript" implements-prefix="user">
   function convert( n ) {
      return parseFloat( n.item(0).text );
   }
</msxsl:script>
 
 
    <xsl:template match="MyField">
        <xsl:element name="MyField">
            <xsl:apply-templates select="@* | *"/>
         </xsl:element>
    </xsl:template>
 
	<xsl:template match="@import">
        <xsl:attribute name="import"><xsl:value-of select="format-number(user:convert(.), '#0.####' )"/></xsl:attribute>
	</xsl:template>
    
    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <!-- go process attributes and children -->
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
    
    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
    
 
 
</xsl:stylesheet>

Open in new window

Gertone (Geert Bormans)Information Architect
CERTIFIED EXPERT
Top Expert 2006

Commented:
please don't go using scripts as zc2 suggests, unless you realy have to.
The script forces you to use one particular processor (msxml in this case)

I see you are using XSLT2.
XPath2 has support for scientific notation as an input format for float numbers
So, your code should work. And it does with Saxon9B.

Which processor are you using for the XSLT?
Likely not an XSLT2 one. I recommend using Saxon9B then

cheers

Geert

Author

Commented:
Hi Gertone,

I am using Xalan, and the reason I need to use Xalan is Saxon was not doing the right thing in certain cases (https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/XSLT/Q_23405813.html).
Is there a way to resolve this issue in Xalan? ( because I can not use Saxon for the above reason)

Thanks a lot!
Gertone (Geert Bormans)Information Architect
CERTIFIED EXPERT
Top Expert 2006

Commented:
The issue you mentioned is not a problem of saxon.
it is a problem of the old xslt transformer hidden in Java.
You could very well plug in Saxon9B and use it in Java
(the saxonica website explains how to use saxon9B in Java)
You will not have the above mentioned issue when using Saxon.

Xalan has no support for XSLT2
So you are bound to XSLT1 if you continue using Xalan.

z2c's solution will not work for you either, since that one requires msxml, not xalan.
You could develop a similar external function in Java and plug that in,
or you could simply develop a template in XSLT that does a similar thing.

Check the saxonica website www.saxonica.com and see if you could migrate to XSLT2 and saxon9B.
In the mean time I will see if I can get it working in XSLT1
Gertone (Geert Bormans)Information Architect
CERTIFIED EXPERT
Top Expert 2006

Commented:
Here is a stylesheet that works accross multiple XSLT1 processors

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:template match="MyField">
        <xsl:copy>
            <xsl:attribute name="name"><xsl:value-of select="@name" />
            </xsl:attribute>
            <xsl:attribute name="type"><xsl:value-of select="@type" />
            </xsl:attribute>
            <xsl:attribute name="import">
                <xsl:call-template name="SciNum2Float">
                    <xsl:with-param name="scinum" select="translate(@import, 'E', 'e')"/>
                </xsl:call-template>
            </xsl:attribute>
        </xsl:copy>
    </xsl:template>
   
    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <!-- go process attributes and children -->
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
   
    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
   
    <xsl:template name="SciNum2Float">
        <xsl:param name="scinum"/>
        <xsl:variable name="exp" select="number(substring-after($scinum, 'e'))"/>
        <xsl:choose>
            <xsl:when test="not(string($exp) = 'NaN') and not (string(number(substring-before($scinum, 'e'))) = 'NaN')">
                <xsl:variable name="multiplier">
                    <xsl:call-template name="power">
                        <xsl:with-param name="base" select="10"/>
                        <xsl:with-param name="power" select="$exp * (1 - 2 * number($exp < 0))"></xsl:with-param>
                    </xsl:call-template>
                </xsl:variable>
                <xsl:choose>
                    <xsl:when test="substring(substring-after($scinum, 'e'), 1, 1) = '-'">
                        <xsl:value-of select="number(substring-before($scinum, 'e'))  div $multiplier "/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="number(substring-before($scinum, 'e')) * $multiplier"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:otherwise>NaN</xsl:otherwise>
        </xsl:choose>
       
    </xsl:template>
   
    <xsl:template name="power">
        <xsl:param name="base"/>
        <xsl:param name="power"/>
        <xsl:choose>
            <xsl:when test="$power = 0">
                <xsl:value-of select="1"></xsl:value-of>
             </xsl:when>
            <xsl:otherwise>
                <xsl:variable name="temp">
                    <xsl:call-template name="power">
                        <xsl:with-param name="base" select="$base"/>
                        <xsl:with-param name="power" select="$power - 1"></xsl:with-param>
                    </xsl:call-template>
                </xsl:variable>
                <xsl:value-of select="$temp * $base"></xsl:value-of>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

Author

Commented:
Thanks Gertone,

But I got the following error:

Description: The value of attribute "select" associated with an element type "xsl:with-param" must not contain the '<' character.

at line:
  <xsl:with-param name="power" select="$exp * (1 - 2 * number($exp < 0))"></xsl:with-param>
--------------------------------------
do u know what happened? Thanks!
Gertone (Geert Bormans)Information Architect
CERTIFIED EXPERT
Top Expert 2006

Commented:
Oh, that is what the EE forum made of my code
(new functionality lead to this I am afraid)
the < in the XPath should be &amp;lt;
I will paste my code in the code snippet pane next time
Information Architect
CERTIFIED EXPERT
Top Expert 2006
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION
Unlock the solution to this question.
Join our community and discover your potential

Experts Exchange is the only place where you can interact directly with leading experts in the technology field. Become a member today and access the collective knowledge of thousands of technology experts.

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.