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

发布于 2024-11-17 12:45:51 字数 230 浏览 1 评论 0 原文

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

format-number(-1.8959581529998104E-4,'0.000000;-0.000000') gives me NaN.

有什么想法吗?

I have the following value in my XML -1.8959581529998104E-4. I want to format this to the exact number it should be using XSL to give me -0.000189595815299981.

format-number(-1.8959581529998104E-4,'0.000000;-0.000000') gives me NaN.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一腔孤↑勇 2024-11-24 12:45:51

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

XSLT 1.0 does not have support for scientific notation.

This: number('-1.8959581529998104E-4')
Result: NaN

This: number('-0.000189595815299981')
Result: -0.000189595815299981

XSLT 2.0 has support for scientific notation

This: number('-1.8959581529998104E-4')
Result: -0.000189595815299981

EDIT: A very simple XSLT 1.0 workaround:

<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>

With this input:

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

Output:

-0.00018959581529998104
七禾 2024-11-24 12:45:51

这是基于 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>

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

This is based on user357812 answer. But I made it act like a function and handle non-scientific notation

<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>

Usage:

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

This should handle a mix of scientific notation and decimal values.

赏烟花じ飞满天 2024-11-24 12:45:51

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

<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')"/>

Another possible workaround without a template:

<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')"/>
近箐 2024-11-24 12:45:51

Moopuser357812 在一种特定场景中确定 vFactor 时。

如果 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>

The logic doesn't appear to work correctly in the above answers by Moop and user357812 when determining vFactor in one particular scenario.

If vExponent is a single-digit positive number (without a preceding '+' sign), then vFactor is set to an empty string. This is because an assumption was made that the 1st character of vExponent would be a plus/minus sign and therefore the 2nd character onwards were of interest. The vMantissa variable is then multiplied by an empty string which results in the template outputting NaN.

If vExponent is a multi-digit positive number (without a preceding '+' sign), then vFactor is set to an incorrect value. Because of the aforementioned assumption, the 1st digit is ignored and the vMantissa is then multiplied by an incorrect vFactor.

Therefore, I've modified the previously posted code a little so that it can handle scientific numbers of the forms: 2E-4, 2E+4 and 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>
澉约 2024-11-24 12:45:51

刚刚在 Linux 下使用 1.1.24 版本中的 libxslt1.1 与 xsltproc 进行了尝试:

即使没有任何专用模板,XSLT 1.1 现在也能够以指数/科学格式读取,它似乎很简单:-))

Just tried this with xsltproc using libxslt1.1 in version 1.1.24 under Linux:

XSLT 1.1 is able to read in exponential/scientific format now even without any dedicated template, it seems to simply work :-))

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文