Как округлить сумму значений узлов до 2 десятичных? - PullRequest
0 голосов
/ 01 января 2019

Я создаю pdf из файлов xml и xslt с помощью Apache FOP 2.3.

У меня есть следующий XML:

<root>
    <operations>
        <operation>
            <sold>5800.00</sold>
        </operation>
        <operation>
            <sold>422.92</sold>
        </operation>
        <operation>
            <sold>422.92</sold>
        </operation>
        <operation>
            <sold>422.92</sold>
        </operation>
        <operation>
            <sold>422.92</sold>
        </operation>
        <operation>
            <sold>422.92</sold>
        </operation>
        <operation>
            <sold>422.92</sold>
        </operation>
        <operation>
            <sold>422.92</sold>
        </operation>
        <operation>
            <sold>422.92</sold>
        </operation>
        <operation>
            <sold>422.92</sold>
        </operation>
        <operation>
            <sold>422.92</sold>
        </operation>
        <operation>
            <sold>422.92</sold>
        </operation>
        <operation>
            <sold>422.92</sold>
        </operation>
        <operation>
            <sold>422.92</sold>
        </operation>
        <operation>
            <sold>0.00</sold>
        </operation>
    </operations>
</root>

В файле xslt у меня есть следующая строка:

<xsl:value-of select="sum(.//operation/sold[number(.) = .])"/>

Это вычислит сумму всех sold элементов, что приведет к 11297.960000000001 (правильный результат будет 11297.96).Мне нужно, чтобы оно было округлено до 2 десятичных знаков, например: 11297.96.Также, если второе десятичное число равно 0, я все еще хочу отобразить его, поэтому, если сумма была, например, 12.3, я хочу, чтобы 12.30 появилось.

1 Ответ

0 голосов
/ 01 января 2019

В зависимости от версии XSLT и процессора вы можете избежать двойной неточности, суммируя десятичные числа в XSLT / XPath 2 или более поздних версиях sum(.//operation/sold/xs:decimal(.)), для форматирования любого числа при необходимости вы можете использовать format-number например, format-number(sum(.//operation/sold/xs:decimal(.)), '0.00').

Тип данных xs:decimal обеспечивает более высокую точность, чем тип данных xs:double (соответственно число в XPath 1). Неточность, которую вы видите, заключается в том, как IEEE определяет 64-разрядный тип IEEE с двойной точностью с плавающей запятойчто XSLT / XPath 2 и более поздние версии наследуются от языка схемы XSD https://www.w3.org/TR/xmlschema-2/#double. Вы найдете такую ​​же проблему в других языках программирования, использующих этот тип данных (например, Javascript http://jsfiddle.net/23g5wexz/).

The sum(.//operation/sold) будет работать с типом данных xs:double (https://www.w3.org/TR/xpath-functions/#func-sum),, если вы знаете, что в любом случае вы используете format-number, для результата достаточно работать со значением по умолчанию xs:double (я думаю, что по умолчанию в основном используется в XSLT/ XPath 2 и более поздних версий для обратной совместимости с XSLT / XPath, где существует тип данных с одним числом, который реализует / следует 64-битному плавающему стандарту IEEE с двойной точностьюпункт спец.).

...