У меня были бесконечные проблемы с десятичными знаками в XSLT / XPath 1.0, часто в комбинации, представляющей десятичные числа в виде чисел с плавающей запятой, и с использованием округления до половины (округление банкира).К сожалению, подход round(yournum*100) div 100
не работал для меня из-за неточности с плавающей запятой.Например, умножение 1.255 на 100 дает 125.49999999999999 (это не должно зависеть от реализации, поскольку предполагается, что это IEEE 754, но я не знаю, все ли реализации придерживаются этого).Когда округлено, это дает 125, а не желаемое значение 126.
Я выбрал следующий подход, который, я думаю, работает (хотя это всегда сложная область, поэтому я не буду заявлять слишком много уверенности!).Однако это зависит от вашего движка XSLT, поддерживающего расширения EXSLT.Предполагается, что вы хотите округлить до двух десятичных знаков.
<func:function name="local:RoundHalfUp">
<xsl:param name="number"/>
<xsl:choose>
<xsl:when test="contains($number, '.')">
<xsl:variable name="decimal" select="estr:split($number, '.')[2]"/>
<xsl:choose>
<xsl:when test="string-length($decimal) > 2">
<func:result select="format-number(concat($number, '1'), '0.00')"/>
</xsl:when>
<xsl:otherwise>
<func:result select="format-number($number, '0.00')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<func:result select="format-number($number, '0.00')"/>
</xsl:otherwise>
</xsl:choose>
</func:function>
, которые можно назвать так:
<xsl:value-of select="local:RoundHalfUp(1.255)"/>
Пространства имен:
xmlns:func="http://exslt.org/functions"
xmlns:estr="http://exslt.org/strings"
xmlns:local="http://www.acme.org/local_function"
Это важноотметить, что функция добавляет a '1', а не добавляет 0,001 или аналогичный.
Определенно лучше использовать XSLT 2.0, если это опция (поскольку она имеет правильный десятичный тип), ноЯ знаю, что это часто не вариант (из мучительного опыта!).