Как я могу обрезать десятичное значение до четырех знаков после запятой с помощью XSLT

В моем процессе ORACLE SOA BPEL мы получаем значение в виде строки @ 10.2345678956, но для целевой системы нам просто нужно отправить до 4 десятичных знаков, например 10.2345. Не могли бы вы рассказать мне, как мы можем добиться этого с помощью xslt.

также, если исходная система отправляет значение как 10, даже в этом случае, в целевую систему нам нужно отправить 10.0000 (всегда 4 цифры в десятичном формате)


person kumarb    schedule 24.08.2015    source источник
comment
Это очень похоже на дубликат stackoverflow.com/questions /3805248/ . Не могли бы вы подтвердить?   -  person fvu    schedule 24.08.2015
comment
@fvu - спасибо за ваш ответ. Я не совсем уверен, что оба вопроса одинаковы, но я думаю, что мы оба пытаемся достичь почти одного и того же. поскольку этот пост дает решение как ‹xsl:value-of select='format-number(round(100*$quantity) div 100,##0.00)' /› .. не могли бы вы сказать мне, что именно здесь делает ##0.00   -  person kumarb    schedule 24.08.2015
comment
0 представляет позицию, которая должна быть отрисована, # позиция, которая будет отрисована, если она значима. Таким образом, #0.0000 должно быть достаточно близко к тому, что вам нужно.   -  person fvu    schedule 24.08.2015
comment
@kumarb stackoverflow.com/help/someone-answers   -  person michael.hor257k    schedule 01.09.2015


Ответы (2)


Чтобы усечь (т.е. округлить вниз) число до 4 знаков после запятой, вы можете сделать следующее:

floor($number * 10000) div 10000

Чтобы отформатировать результат, чтобы всегда отображались 4 десятичные цифры:

format-number(floor($number * 10000) div 10000, '0.0000')

Это работает как в XSLT 1.0, так и в XSLT 2.0.


Если вас не волнует направление округления, сделайте просто:

format-number($number, '0.0000')

и покончим с этим.

person michael.hor257k    schedule 26.08.2015
comment
Привет всем - Нужен ваш вклад в эту тему. Приведенная выше логика работает отлично до настоящего времени, но сегодня, когда мы отправляем значение 5,56, происходит сбой кода. для значения 5,56 на выходе должно получиться 5,5600, но по какой-то причине оно будет 5,5599. - person kumarb; 13.10.2015
comment
это логика, которую я пытаюсь использовать - формат-номер ((этаж (((KBETR div KPEIN) * 10000.0)) div 10000.0), 0.0000) . Это очень странно для меня. Если я попробую 6.56, все работает отлично. - person kumarb; 13.10.2015
comment
@kumarb Нам нужен воспроизводимый пример. Я предполагаю, что значение не совсем 5,56. Мы узнаем наверняка, если вы сообщите нам значения KBETR и KPEIN. - person michael.hor257k; 13.10.2015
comment
@michael.hor257k будет ли format-number($number - 0.00005, '0.0000') иметь тот же результат, что и format-number(floor($number * 10000) div 10000, '0.0000')? - person dave; 24.12.2020
comment
@dave Думаю, нет: xsltfiddle.liberty-development.net/pNvtBGD - person michael.hor257k; 24.12.2020

Вы не указываете, какую версию XSLT вы используете, но в XSLT 1.0 вы должны сделать это «вручную», например, следующим образом:

Примечание: как говорит Майкл в комментариях, вы можете использовать номер формата в XSLT 1.0. Однако выбранное округление неясно. Пока это работает, см. Ответ Майкла для более тривиального решения.

<xsl:template match="/">
    <xsl:variable name="input" select="10.23456789" />

    <xsl:call-template name="truncate">
        <xsl:with-param name="val" select="$input" />
    </xsl:call-template>
</xsl:template>

<xsl:template name="truncate">
    <xsl:param name="val" />
    <xsl:variable name="adj">
        <xsl:value-of select="$val"/>
        <xsl:if test="not(contains($val, '.'))">.</xsl:if>
        <xsl:text>0000</xsl:text>
    </xsl:variable>
    <xsl:variable name="before" select="substring-before($adj, '.')" />
    <xsl:variable name="after" select="substring-after($adj, '.')" />
    <xsl:value-of select="$before" />
    <xsl:text>.</xsl:text>
    <xsl:value-of select="substring($after, 1, 4)" />        
</xsl:template>

А в XSLT 2.0 и 3.0 можно просто сделать так:

<xsl:value-of select="format-number($input, '#.0000')" /> 

Но это округлит (от половины до четного), то есть с вашим вводом это даст вам 10.2346. Если это нежелательно, вы можете использовать трюк предложено fvu:

<xsl:value-of select="
    format-number(xs:integer(number($input) * 10000) div 10000, '#.0000')" /> 

Обе версии XSLT 1.0 и XSLT 2.0/3.0, указанные выше, будут добавлять необходимые нули до четырех.

person Abel    schedule 26.08.2015
comment
Почему бы вам не использовать format-number() и в XSLT 1.0? -- П.С. format-number() не округляет (всегда) в большую сторону, а округляет до четного (в XSLT 2.0 и в некоторых реализациях XSLT 1.0). - person michael.hor257k; 26.08.2015
comment
@ michael.hor257k: лол, понятия не имею, почему, но я так долго работал с 2.0+, что просто предположил, что он не будет поддерживать эту функцию, не проверив. Вы абсолютно правы, этому ничто не мешает. Да, округляется до четного, мне было неясно (введенные данные округляются). - person Abel; 27.08.2015
comment
@Abel У меня есть эта логика ‹xsl:value-of select= format-number(($input), '0.0000000') /›. Как обрезать 0,31661129 до 0,3166112? В настоящее время округляется до 0,3166113. - person Nik; 10.04.2018