Link to home
Start Free TrialLog in
Avatar of meow00
meow00

asked on

more questions on Converting 4e-3 to 0.004

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

Avatar of meow00
meow00

ASKER

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

Avatar of meow00

ASKER

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

Avatar of zc2
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

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
Avatar of meow00

ASKER

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/questions/23405813/order-of-conditions.html).
Is there a way to resolve this issue in Xalan? ( because I can not use Saxon for the above reason)

Thanks a lot!
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
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>
Avatar of meow00

ASKER

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!
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
ASKER CERTIFIED SOLUTION
Avatar of Gertone (Geert Bormans)
Gertone (Geert Bormans)
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial