Problemy z zaokrąglaniem i precyzją w XSLT 1.0


Mam niespójność podczas używania xsl,
to jest xml,
<Rate>
<TotalRate>506.41</TotalRate>
<TotalTax>17</TotalTax>
<Currency>INR</Currency>
</Rate>

i xsl,
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[url=http://www.w3.org/1999/XSL/Transform"]http://www.w3.org/1999/XSL/Transform"[/url] xmlns:fo="[url=http://www.w3.org/1999/XSL/Format">]http://www.w3.org/1999/XSL/Format">[/url]
<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>

I jest wyjście,
<TotalAmount xmlns:fo="[url=http://www.w3.org/1999/XSL/Format">523.4100000000001</TotalAmount>]http://www.w3.org/1999/XSL/For ... gt%3B[/url]

ale oczekiwany O/R,
<TotalAmount xmlns:fo="[url=http://www.w3.org/1999/XSL/Format">523.41</TotalAmount>]http://www.w3.org/1999/XSL/For ... gt%3B[/url]

Dlaczego o/p 523.4100000000001? jak uzyskać 523,41 bez zaokrąglania w górę?
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


W XSLT 1.0 liczby są implementowane z typem

double


i tak jak w przypadku każdego typu binarnego zmiennoprzecinkowego następuje utrata precyzji.

W XSLT 2.0/XPath 2.0 możesz używać typu
xs: decimal
do pracy bez utraty precyzji

.

Rozwiązanie I. XSLT 1.0

:
Posługiwać się


funkcja
format-number ()
:
<xsl:stylesheet version="1.0" xmlns:xsl="[url=http://www.w3.org/1999/XSL/Transform">]http://www.w3.org/1999/XSL/Transform">[/url]
<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>


Gdy ta transformacja ma zastosowanie do dostarczonego dokumentu

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


chciałem prawidłowy wynik

:
<TotalAmount>523.41</TotalAmount>


Tutaj jest również przykład pokazujący, że wymagana precyzja nie może być znana statycznie i może być przekazana do transformacji jako parametr zewnętrzny/globalny

:
<xsl:stylesheet version="1.0" xmlns:xsl="[url=http://www.w3.org/1999/XSL/Transform">]http://www.w3.org/1999/XSL/Transform">[/url]
<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>


Gdy ta konwersja ma zastosowanie do dostarczonego dokumentu XML, otrzymuje się dwa wyniki - z dokładnością 2 i dokładność 13

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


II. Rozwiązanie XSLT 2.0 używające
xs: decimal

:
<xsl:stylesheet version="2.0" xmlns:xsl="[url=http://www.w3.org/1999/XSL/Transform"]http://www.w3.org/1999/XSL/Transform"[/url]
xmlns:xs="[url=http://www.w3.org/2001/XMLSchema"]http://www.w3.org/2001/XMLSchema"[/url] 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>


Po zastosowaniu tej transformacji do tego samego dokumentu XML (powyżej) uzyskuje się pożądany, prawidłowy wynik

:
<TotalAmount>523.41</TotalAmount>

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się