【问题标题】:XSL transformation using Java: number format issue使用 Java 进行 XSL 转换:数字格式问题
【发布时间】:2012-10-19 22:09:49
【问题描述】:

我有 JDK6 并使用 JAXP 进行转换。我是 XSLT 的初学者。

源 XML:

<Number>
    <Value>529.82</Value>
</Number>

XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="Number">
        <xsl:element name="Result">
            <xsl:element name="Total">
                <xsl:attribute name="Amount">
                    <xsl:value-of select="format-number(Value, '#.00')*100"/>
                </xsl:attribute>
            </xsl:element>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

输出 XML:

<?xml version="1.0" encoding="UTF-8"?>
<Result>
     <Total Amount="52982.00000000001"/>
</Result>

这里Amount属性的值应该是52982。 请帮忙。

【问题讨论】:

  • Java 是一个单词而不是缩写

标签: java transform xslt-1.0 xslt


【解决方案1】:

使用

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="Number">
     <Result>
      <Total amount="{round(format-number(Value, '#.00')*100)}"/>
     </Result>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<Number>
    <Value>529.82</Value>
</Number>

产生想要的正确结果

<Result>
   <Total amount="52982"/>
</Result>

解释

XSLT 1.0 只有一个数字类型,它是 double 类型。

与任何浮点类型一样,存在精度错误。

在 XPath 2.0 / XSLT 2.0 中,可以使用 xs:decimal 类型,这样就可以消除任何精度错误——当然,xs:decimal 类型具有已定义的最大位数。


作为参考,这里是使用xs:decimal的相应XSLT 2.0转换:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="Number">
     <Result>
      <Total amount="{xs:decimal(format-number(Value, '#.00'))*100}"/>
     </Result>
 </xsl:template>
</xsl:stylesheet>

结果

<Result>
   <Total amount="52982"/>
</Result>

或者更简单(没有format-number()):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="Number">
     <Result>
      <Total amount="{xs:decimal(Value)*100}"/>
     </Result>
 </xsl:template>
</xsl:stylesheet>

【讨论】:

  • 那么实际上根本不需要format-number,只需&lt;Total amount="{round(Value*100)}"/&gt; 就可以了,确定吗?
  • @IanRoberts,是的,但我们不知道实际的上下文——OP 可能有一些使用它的原因。
  • @IanRoberts:我需要先转换成 2 个十进制值,这就是原因
【解决方案2】:

试试

<xsl:value-of select="format-number(Value*100, '#')"/>

您之前方法的问题是您将Value 格式化为字符串,然后将其转换回数字并将其乘以100。您需要对原始数字进行乘法运算,然后格式化结果。

【讨论】:

  • @joergl 我最初复制了您的原始格式模式,现在我已将答案编辑为更合适的模式。
  • 看到了,并在我看到你之前删除了我的评论。太多的并行;)
【解决方案3】:

您可以使用round() 函数。只需将您的 format-number() 电话包裹在其中即可。以下样式表可以解决问题:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="Number">
        <xsl:element name="Result">
            <xsl:element name="Total">
                <xsl:attribute name="Amount">
                    <xsl:value-of select="round(format-number(Value, '#.00')*100)"/>
                </xsl:attribute>
            </xsl:element>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-18
    • 2011-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多