2012-10-05 55 views
10

我而使用XSL有不一致,數量舍入和精度問題1.0

這裏是XML,

<Rate> 
    <TotalRate>506.41</TotalRate> 
    <TotalTax>17</TotalTax> 
    <Currency>INR</Currency> 
</Rate> 

和xsl,

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:template match="/"> 
     <TotalAmount> 
      <xsl:value-of select="Rate/TotalRate + Rate/TotalTax"/> 
     </TotalAmount> 
    </xsl:template> 
</xsl:stylesheet> 

和輸出是,

<TotalAmount xmlns:fo="http://www.w3.org/1999/XSL/Format">523.4100000000001</TotalAmount> 

但經過c/o是,

<TotalAmount xmlns:fo="http://www.w3.org/1999/XSL/Format">523.41</TotalAmount> 

爲什麼o/p是523.4100000000001?我怎麼能得到523.41沒有舍入呢?

回答

15

在XSLT 1.0號碼與類型實現,並且與任何二進制浮點型,有精度的損失。

在XSLT 2.0/XPath 2.0中,人們可以使用xs:decimal類型工作而不會損失精度


I. XSLT 1.0溶液

使用format-number()功能:

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

    <xsl:template match="/*"> 
     <TotalAmount> 
     <xsl:value-of select="format-number(TotalRate + TotalTax, '0.##')"/>  
     </TotalAmount> 
    </xsl:template> 
</xsl:stylesheet> 

當這個變換所提供的XML文檔應用:

<Rate> 
    <TotalRate>506.41</TotalRate> 
    <TotalTax>17</TotalTax> 
    <Currency>INR</Currency> 
</Rate> 

的想要的,正確的結果產生:

<TotalAmount>523.41</TotalAmount> 

這裏也是一個例子,顯示出想要的精度maynot靜態已知的,並且可以被傳遞給變換作爲外部/全局參數

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

    <xsl:param name="pPrec" select="2"/> 
    <xsl:param name="pPrec2" select="13"/> 

    <xsl:variable name="vPict" select="'##################'"/> 

    <xsl:template match="/*"> 
     <TotalAmount> 
     <xsl:value-of select= 
     "format-number(TotalRate + TotalTax, 
        concat('0.', substring($vPict,1,$pPrec)) 
        )"/> 
     </TotalAmount> 
     <TotalAmount> 
     <xsl:value-of select= 
     "format-number(TotalRate + TotalTax, 
        concat('0.', substring($vPict,1,$pPrec2)) 
        )"/> 
     </TotalAmount> 
    </xsl:template> 
</xsl:stylesheet> 

當這個變換所提供的XML文檔應用,兩個結果產生 - 精密2和精密13

<TotalAmount>523.41</TotalAmount> 
<TotalAmount>523.4100000000001</TotalAmount> 

II。 XSLT 2。使用xs:decimal 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="/*"> 
     <TotalAmount> 
     <xsl:value-of select="xs:decimal(TotalRate) + xs:decimal(TotalTax)"/> 
     </TotalAmount> 
</xsl:template> 
</xsl:stylesheet> 

當這種轉變是在同一個XML文檔(以上)應用,在想,正確的結果產生

<TotalAmount>523.41</TotalAmount> 
+0

感謝,很高興見到你的迴應,但如果我不知道所提供的十進制數的確切小數位是什麼? – Sujit

+0

@asdasd,如果你不知道它,你可以把它作爲一個全局參數傳遞給變換 - 然後一些額外的XSLT代碼可以動態地構造'format-number()'所需的參數。另外,請參閱我的XSLT 2.0解決方案,您可以使用'xs:decimal'類型進行精確計算。 –

+0

@asdasd,請看我更新的答案。當所需的精度事先不知道並且作爲參數傳遞給變換時,我添加了一個解決方案。 –