12

xsl を使用しているときに矛盾があります。

これが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>

しかし、期待されるo/pは、

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

なぜ o/p は 523.4100000000001 なのですか? 丸めずに 523.41 を取得するにはどうすればよいですか?

4

1 に答える 1

17

XSLT 1.0 では、数値はdouble型で実装されており、他のバイナリ浮動小数点型と同様に、精度が失われます。

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>

また、必要な精度が静的に認識されず、外部/グローバル パラメータとして変換に渡される可能性があることを示す例も示します

<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 の 2 つの結果が生成されます

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

Ⅱ.を使用した XSLT 2.0 ソリューションxs:decimal:

<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>
于 2012-10-05T12:59:04.433 に答える