2011-06-28 79 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>