Search code examples
xslt-2.0saxonxslt-3.0

format-number() with picture string '#.##'


I've been using the picture string '#.##" in XSLT 1.0 code for many years to format numbers with decimals if they have a fractional part, and not displaying decimals if there is no fractional part.

Saxon 6.5.5.
format-number(123.456,'#.##’)   123.46
format-number(123.000,'#.##’)   123

But when using XSLT 2.0 or 3.0, I'm getting different behavior.

Saxon 9.9.1.5J
format-number(123.456,'#.##’)   123.46
format-number(123.000,'#.##’)   123.0

I haven't been able to figure out why the last case has the fractional part. https://www.w3.org/TR/xslt20/#dt-picture-string states:

The minimum-fractional-part-size is set to the number of zero-digit-sign characters found in the fractional part of the sub-picture.

https://www.w3.org/TR/xpath-functions-30/#syntax-of-picture-string states:

The minimum-fractional-part-size is set to the number of decimal-digit-family characters found in the fractional part of the sub-picture.

And with no zero-digit-sign and no decimal-digit-family characters, the fractional size should be zero, like it is in the XSLT 1.0 case.

Am I missing something?


Solution

  • Saxon is applying the rule:

    If (after making the above adjustments) the minimum-integer-part-size and the minimum-fractional-part-size are both zero, then the minimum-fractional-part-size is set to 1 (one).

    The XSLT 1.0 spec for format-number() was defined by reference to the JDK 1.1 specification, which was a bad mistake because (a) it was always grossly underspecified in the JDK, and (b) that version of the JDK specification is now almost impossible to get hold of. So we spent many happy hours writing a new spec from scratch that tried to reproduce the JDK spec in cases where it was clear and unbuggy, but filled in the gaps. We took into account the way that different XSLT 1.0 vendors had interpreted the spec, but didn't regard any existing implementations (or the JDK) as definitive.

    Your test case is similar to test case numberformat228 at https://github.com/w3c/qt3tests/blob/master/fn/format-number.xml, and the notes for this test case refer to bug 29164. The bug entry at https://www.w3.org/Bugs/Public/show_bug.cgi?id=29164 reveals that the rule cited above was a fairly late addition/change to the spec (Sept 2015 - long after XPath 2.0).

    The discussion in the bug entry suggests that the primary consideration was to prevent zero being formatted as an empty string. Perhaps, with hindsight, we should have treated that case specially.