在xsl中格式化科学数字表示

时间:2010-12-06 15:07:13

标签: xslt numbers format

我的XML -1.8959581529998104E-4中有以下值。我想将其格式化为应该使用XSL给出的确切数字-0.000189595815299981。

format-number(-1.8959581529998104E-4,'0.000000; -0.000000')给了我NaN。

有什么想法吗?

干杯

Andez

5 个答案:

答案 0 :(得分:15)

XSLT 1.0不支持科学记数法。

这:number('-1.8959581529998104E-4') 结果:NaN

这:number('-0.000189595815299981') 结果:-0.000189595815299981

XSLT 2.0支持科学记数法

这:number('-1.8959581529998104E-4') 结果:-0.000189595815299981

编辑:一个非常简单的XSLT 1.0解决方法:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="number[substring-after(.,'E')]">
        <xsl:variable name="vExponent" select="substring-after(.,'E')"/>
        <xsl:variable name="vMantissa" select="substring-before(.,'E')"/>
        <xsl:variable name="vFactor"
             select="substring('100000000000000000000000000000000000000000000',
                               1, substring($vExponent,2) + 1)"/>
        <xsl:choose>
            <xsl:when test="starts-with($vExponent,'-')">
                <xsl:value-of select="$vMantissa div $vFactor"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$vMantissa * $vFactor"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

使用此输入:

<number>-1.8959581529998104E-4</number>

输出:

-0.00018959581529998104

答案 1 :(得分:4)

这是基于user357812的答案。但我让它像一个功能,处理非科学的符号

<xsl:template name="convertSciToNumString" >
    <xsl:param name="inputVal" select="0"/>
    <xsl:variable name="vExponent" select="substring-after($inputVal,'E')"/>
    <xsl:variable name="vMantissa" select="substring-before($inputVal,'E')"/>
    <xsl:variable name="vFactor"
         select="substring('100000000000000000000000000000000000000000000',
                           1, substring($vExponent,2) + 1)"/>
    <xsl:choose>
        <xsl:when test="number($inputVal)=$inputVal">
            <xsl:value-of select="$inputVal"/>
        </xsl:when>
        <xsl:when test="starts-with($vExponent,'-')">
            <xsl:value-of select="format-number($vMantissa div $vFactor, '#0.#############')"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="format-number($vMantissa * $vFactor, '#0.#############')"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

用法:

<xsl:template match="X">
    <X>
        <xsl:call-template name="convertSciToNumString">
            <xsl:with-param name="inputVal" select="text()"/>
        </xsl:call-template>
    </X>    
</xsl:template>

这应该处理科学记数法和小数值的混合。

答案 2 :(得分:1)

没有模板的另一种可能的解决方法:

<xsl:stylesheet version="1.0" ... xmlns:java="http://xml.apache.org/xslt/java">
...
<xsl:value-of select="format-number(java:java.lang.Double.parseDouble('1E-6'), '0.000')"/>

答案 3 :(得分:0)

在Linux下使用版本1.1.24中的libxslt1.1尝试使用xsltproc:

XSLT 1.1能够以指数/科学格式读取,即使没有任何专用模板,它似乎只是工作: - ))

答案 4 :(得分:0)

在一种特定情况下确定vFactor时,上述Moopuser357812的答案中的逻辑似乎无法正常工作。

如果vExponent是个位数的正数(没有前面的'+'号),则vFactor被设置为一个空字符串。这是因为假设vExponent的第一个字符将是一个正号/负号,因此第二个字符起是有趣的。然后,将vMantissa变量乘以一个空字符串,这将导致模板输出NaN

如果vExponent是一个多位数的正数(没有前面的'+'号),则vFactor设置为错误的值。由于上述假设,第一个数字将被忽略,然后将vMantissa乘以错误的vFactor

因此,我对先前发布的代码进行了一些修改,以便可以处理以下形式的科学数字:2E-4、2E + 4和2E4。

<xsl:template name="convertSciToNumString" >
    <xsl:param name="inputVal" select="0"/>
    <xsl:variable name="vMantissa" select="substring-before(., 'E')"/>
    <xsl:variable name="vExponent" select="substring-after(., 'E')"/>
    <xsl:variable name="vExponentAbs" select="translate($vExponent, '-', '')"/>
    <xsl:variable name="vFactor" select="substring('100000000000000000000000000000000000000000000', 1, substring($vExponentAbs, 1) + 1)"/>
    <xsl:choose>
        <xsl:when test="number($inputVal)=$inputVal">
            <xsl:value-of select="$inputVal"/>
        </xsl:when>
        <xsl:when test="starts-with($vExponent,'-')">
            <xsl:value-of select="format-number($vMantissa div $vFactor, '#0.#############')"/>
        </xsl:when>
        <xsl:otherwise>         
            <xsl:value-of select="format-number($vMantissa * $vFactor, '#0.#############')"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>