2011-06-28 76 views
3

当前我们连接的系统希望接收XML,其中包含格式化为一位小数的三个双字段。就我个人而言,我觉得我们的系统应该能够以默认格式发送值,然后由其他系统根据自己的喜好来格式化自己的表示,但是这似乎不是一种选择。格式化XML的十进制值

我的基于Java的系统当前通过使用XStream将对象转换为XML。我们有一个伴随着XML的XSD,并将各种元素定义为字符串,双精度,日期时间等。

我有三个双字段,它们保存着12.5,100.123,5.23445等值。现在它们几乎被转换为 - 进入XML。我需要的是将这些值在XML中格式化为一位小数; 12.5,100.1,5.2等

我简要地想出选项来实现这一点:

  • 不知怎的,具备Java格式的这些值这个精密它转到XML之前。也许NumberFormat可以做到这一点,但我认为这主要是为了使用String输出。
  • 希望XSD能为我做到这一点;我知道你可以在XSD中对精度设置限制,但我不确定它是否实际处理舍入本身,或者只是说'123.123的这个值对于这个模式无效'?
  • 使用XSLT以某种方式为我完成此操作。

我会选择你的集体大脑,以便在这种情况下使用“接受”方式/最佳做法。

谢谢, 戴夫。

+0

显示一些代码,也许我们将有上下文来帮助更好一点。 –

+0

XSLT 2.0是您的选择吗?你可以使用'format-number()'和'xsl:decimal-format'。 –

+0

@Don - 目前没有任何相关的代码。我正在考虑上面提到的3个选择。 @empo - 我需要看看XStream是否支持XSLT 2.0;如果是这种情况,那可能会有所帮助。 – f1dave

回答

3

XStream有converterstutorial)。你将不得不注册你自己的Double转换器来处理这个问题。在转换器中使用DecimalFormat来限制小数位数。

+0

好的建议 - 转换器可以锁定到一组特定的元素吗?我公司拥有一批在XML双打,但如果我只希望那些关于价格要.1例如...... – f1dave

+0

不是我所知道的。 – Bozho

+0

@Bozho:你可能会有兴趣看我的答案:) –

4

这可以在单个XPath表达式中完成。

使用

floor(.) + round(10*(. -floor(.))) div 10 

验证使用XSLT作为主机的XPath的:

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

当这种转变是在下面的XML文档应用:

<t> 
<n>12.5</n> 
<n>100.123</n> 
<n>5.26445</n> 
</t> 

的希望,正确的结果产生:

<t> 
    <n>12.5</n> 
    <n>100.1</n> 
    <n>5.3</n> 
</t> 

说明:标准XPath函数floor()round()使用和XPath的操作div和你的逻辑。

广义表达

floor(.) + round($vFactor*(. -floor(.))) div $vFactor 

其中$vFactor10^N,其中N是数字我们想要的小数点后的位数。

利用该表达式,修改后的XSLT转换,这是

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

当该变换是在相同的XML文档(上文),我们生产的$pPrecision任何有意义的值的有用输出施加。在上面的例子中它被设置为4和结果中包含所有数字四舍五入至小数点后四位:

<t> 
    <n>12.5</n> 
    <n>100.123</n> 
    <n>5.2645</n> 
</t>