Если я вас правильно понимаю, вы хотите:
- "Integer-XML" всегда отображается как округленное число, без десятичных разрядов
- «Десятичный XML» всегда отображается с двумя десятичными знаками
- не использовать шаблон, который выполняет форматирование, а однострочник XPath
Самое близкое к тому, что вы хотите, это выражение:
<xsl:value-of select="
format-number($cost + $extraCharges - $discount, '0.00')
" />
Поскольку в XPath 1.0 нет простого в использовании условного выражения ( XPath 2.0 имеет if/then/else
), компромисс будет следующим:
<xsl:value-of select="
substring-before(
concat(format-number($cost + $extraCharges - $discount, '0.00'), '.00')
, '.00'
)
" />
Однако это «не получается» (обрезание десятичных дробей), когда $cost
, $extraCharges
и $discount
складываются в круглое число.
Непривлекательной альтернативой является использование метода Беккера (названного в честь Оливер Беккер из HU Berlin ):
concat(
substring($s1, 1, number($condition) * string-length($s1)),
substring($s2, 1, number(not($condition)) * string-length($s2))
)
Технически это однострочник. Две sub-string()
части являются взаимоисключающими на основе $condition
, поэтому concat()
будет возвращать только одно значение или другое.
Практически (особенно для вашего случая) это будет неуправляемый беспорядок, медленный и полностью скрывающий намерение:
concat(
substring(
format-number($cost + $extraCharges - $discount, '0.00')
, 1
, number(
contains($cost, '.')
) * string-length(format-number($cost + $extraCharges - $discount, '0.00'))
),
substring(
format-number($cost + $extraCharges - $discount, '#.##')
, 1
, number(
not(contains($cost, '.'))
) * string-length(format-number($cost + $extraCharges - $discount, '#.##'))
)
)
Поскольку вы указали, что либо все входные значения содержат десятичные дроби, либо ни одного из них, вышеприведенное выражение только проверяет, содержит ли $cost
десятичную точку. Думаю, было бы правильно проверить $extraCharges
и $discount
.