Java 格式化XML的十进制值
我目前遇到一个问题,我们正在连接的系统希望接收XML,其中包含三个格式化为小数点后一位的双字段。就我个人而言,我觉得我们的系统应该能够以默认格式发送值,然后由其他系统按照自己的意愿格式化它们自己的表示,但遗憾的是,这似乎不是一个选项 我的基于Java的系统目前正在通过使用XStream将对象转换为XML。我们有一个伴随XML的XSD,它将各种元素定义为string、double、dateTime等 我有三个双字段,它们包含12.5、100.123、5.23445等值。现在它们被转换成XML。我需要的是将这些值在XML中格式化为小数点后一位;12.5、100.1、5.2等 我简要地想到了实现这一目标的各种方案:Java 格式化XML的十进制值,java,xml,xslt,xsd,xstream,Java,Xml,Xslt,Xsd,Xstream,我目前遇到一个问题,我们正在连接的系统希望接收XML,其中包含三个格式化为小数点后一位的双字段。就我个人而言,我觉得我们的系统应该能够以默认格式发送值,然后由其他系统按照自己的意愿格式化它们自己的表示,但遗憾的是,这似乎不是一个选项 我的基于Java的系统目前正在通过使用XStream将对象转换为XML。我们有一个伴随XML的XSD,它将各种元素定义为string、double、dateTime等 我有三个双字段,它们包含12.5、100.123、5.23445等值。现在它们被转换成XML。我需
- 以某种方式让Java在将这些值转换为XML之前将其格式化为这种精度。也许NumberFormat可以做到这一点,尽管我认为它主要用于字符串输出
- 希望XSD能为我做到这一点;我知道你可以在XSD中限制精度,但我不确定它是否真的处理舍入本身,或者只是说“123.123的这个值对于这个模式无效”
- 使用XSLT以某种方式为我实现这一点
Dave.XStream有()。您必须注册自己的双转换器来处理此问题。在转换器中,用于限制小数位数。这可以在单个XPath表达式中完成 使用:
floor(.) + round(10*(. -floor(.))) div 10
<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="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()[contains(.,'.')]">
<xsl:value-of select=
"floor(.) + round(10*(. -floor(.))) div 10"/>
</xsl:template>
</xsl:stylesheet>
<t>
<n>12.5</n>
<n>100.123</n>
<n>5.26445</n>
</t>
floor(.) + round($vFactor*(. -floor(.))) div $vFactor
<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:param name="pPrecision" select="4"/>
<xsl:variable name="vFactor" select=
"substring('10000000000000000000000',
1, $pPrecision+1
)
"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()[contains(.,'.')]">
<xsl:value-of select=
"floor(.) + round($vFactor*(. -floor(.))) div $vFactor"/>
</xsl:template>
</xsl:stylesheet>
使用XSLT作为XPath主机进行验证:
floor(.) + round(10*(. -floor(.))) div 10
<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="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()[contains(.,'.')]">
<xsl:value-of select=
"floor(.) + round(10*(. -floor(.))) div 10"/>
</xsl:template>
</xsl:stylesheet>
<t>
<n>12.5</n>
<n>100.123</n>
<n>5.26445</n>
</t>
floor(.) + round($vFactor*(. -floor(.))) div $vFactor
<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:param name="pPrecision" select="4"/>
<xsl:variable name="vFactor" select=
"substring('10000000000000000000000',
1, $pPrecision+1
)
"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()[contains(.,'.')]">
<xsl:value-of select=
"floor(.) + round($vFactor*(. -floor(.))) div $vFactor"/>
</xsl:template>
</xsl:stylesheet>
其中$vFactor
是10^N
,其中N
是小数点后的位数
使用此表达式,修改后的XSLT转换如下所示:
floor(.) + round(10*(. -floor(.))) div 10
<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="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()[contains(.,'.')]">
<xsl:value-of select=
"floor(.) + round(10*(. -floor(.))) div 10"/>
</xsl:template>
</xsl:stylesheet>
<t>
<n>12.5</n>
<n>100.123</n>
<n>5.26445</n>
</t>
floor(.) + round($vFactor*(. -floor(.))) div $vFactor
<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:param name="pPrecision" select="4"/>
<xsl:variable name="vFactor" select=
"substring('10000000000000000000000',
1, $pPrecision+1
)
"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()[contains(.,'.')]">
<xsl:value-of select=
"floor(.) + round($vFactor*(. -floor(.))) div $vFactor"/>
</xsl:template>
</xsl:stylesheet>
展示一些代码,也许我们可以从上下文中得到一些帮助。XSLT2.0是否适合您?您将有
format-number()
和xsl:decimal-format
供您使用。@Don-目前没有任何相关的代码。我正在仔细考虑上面提到的3个选择@empo—我需要研究XStream是否支持XSLT2.0;如果是这样的话,这些可能会有所帮助。好问题,+1。有关完整、简短且简单的XPath单行程序解决方案,请参见我的答案:)我还添加了一个通用表达式,该表达式可以执行任意精度的舍入操作。:)很好的建议-转换器可以锁定到一组特定的元素吗?我在XML中有很多双精度,但如果我只希望价格相关的双精度是。1例如…@Bozho:您可能有兴趣在我的答案中看到纯XPath解决方案:)@Bozho:为什么?你能提出一个简单的表达吗?不,这就是为什么我没有提出一个表达的原因: