Formatting decimal values for XML

自作多情 提交于 2019-12-23 20:51:54

问题


I have a problem currently where a system we are connecting to expects to receive XML which contains, among other things, three double fields formatted to one decimal place. Personally I feel that our system should just be able to send values in default format and then it's up to other systems to format their own representation as they please, but alas this doesn't seem to be an option.

My Java-based system is currently converting objects to XML through the use of XStream. We have an XSD which accompanies the XML and defines the various elements as string, double, dateTime, etc.

I have three double fields which hold values like 12.5, 100.123, 5.23445 etc. Right now they are converted pretty much as-is into the XML. What I need is these values to be formatted in the XML to one decimal place; 12.5, 100.1, 5.2, etc.

I have briefly thought up options to accomplish this:

  • Somehow have Java format these values to this precision before it goes to the XML. Perhaps NumberFormat can do this, although I thought that was mainly for using with String output.
  • Hope that the XSD can do this for me; I know you can place limits on precision in the XSD, but I am unsure whether it actually handles the rounding itself or will just say 'this value of 123.123 is invalid for this schema'?
  • Use XSLT to somehow accomplish this for me.

I'd to pick your collective brains as to what would be the 'accepted' way / best practice to use in a situation like this.

Thanks, Dave.


回答1:


XStream has converters (tutorial). You would have to register your own Double converter that will handle this. In the converter use DecimalFormat to limit the number of decimal places.




回答2:


This can be done in a single XPath expression.

Use:

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

Verification using XSLT as a host of 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>

when this transformation is applied on the following XML document:

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

the wanted, correct result is produced:

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

Explanation: Use of the standard XPath functions floor(), round() and the XPath operator div and your logic.

Generalized expression:

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

where $vFactor is 10^N, where N is the number of digits after the decimal point we want.

Using this expression, the modified XSLT transformation is this:

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

when this transformation is applied on the same XML document (above), we produce the wanted output for any meaningful value of $pPrecision. In the above example it is set to 4 and the result contains all numbers rounded up to four digits after the decimal point:

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


来源:https://stackoverflow.com/questions/6505532/formatting-decimal-values-for-xml

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!