[xslt] format-number inconsistent with java results
- From: Ken Neighbors <ken nsds com>
- To: xslt gnome org
- Subject: [xslt] format-number inconsistent with java results
- Date: Fri, 14 Jun 2002 14:16:48 -0700
I was trying to format a fractional number *without* a leading zero,
but was unable to. For example, format-number(0,'.0') returns "0.0"
instead of ".0" as I would expect.
I fixed this and while I was at it I checked some other cases at
http://www.zvon.org:9001/saxon/cgi-bin/XLab/XML/addressbook.html?stylesheetFile=XSLT/format-number.xslt
and compared the results with libxslt (cvs snapshot as of 13 June 2002).
Here are the cases I found that differed with regard to leading zeros
and trailing decimal points:
function call : libxslt : zvon(java I assume)
format-number(-1.0, '.' ) : -1 : -1.
format-number(-0.5, '.' ) : -1 : -0. (but I think this should be -1.)
format-number( 0.0, '.' ) : 0 : 0.
format-number( 0.5, '.' ) : 1 : 0. (but I think this should be 1.)
format-number( 1.0, '.' ) : 1 : 1.
format-number(-1.0,'#.' ) : -1 : -1.
format-number(-0.5,'#.' ) : -1 : -0. (but I think this should be -1.)
format-number( 0.0,'#.' ) : 0 : 0.
format-number( 0.5,'#.' ) : 1 : 0. (but I think this should be 1.)
format-number( 1.0,'#.' ) : 1 : 1.
format-number(-1.0,'0.' ) : -1 : -1.
format-number(-0.5,'0.' ) : -1 : -0. (but I think this should be -1.)
format-number( 0.0,'0.' ) : 0 : 0.
format-number( 0.5,'0.' ) : 1 : 0. (but I think this should be 1.)
format-number( 1.0,'0.' ) : 1 : 1.
format-number(-1.0, '.#') : -1 : -1.0
format-number(-0.5, '.#') : -0.5 : -.5
format-number( 0.0, '.#') : 0 : .0
format-number( 0.5, '.#') : 0.5 : .5
format-number( 1.0, '.#') : 1 : 1.0
format-number(-1.0, '.##') : -1 : -1.0
format-number(-0.5, '.##') : -0.5 : -.5
format-number( 0.0, '.##') : 0 : .0
format-number( 0.5, '.##') : 0.5 : .5
format-number( 1.0, '.##') : 1 : 1.0
format-number(-0.5, '.0') : -0.5 : -.5
format-number( 0.0, '.0') : 0.0 : .0
format-number( 0.5, '.0') : 0.5 : .5
format-number(-0.5,'#.0') : -0.5 : -.5
format-number( 0.0,'#.0') : 0.0 : .0
format-number( 0.5,'#.0') : 0.5 : .5
Attached are fixes to numbers.c and numbersInternals.h to produce the
above results consistent with java (except for the cases I noted
above). Also included are additional test cases for
tests/numbers/format-number.xsl.
I assume the java interpretation of these patterns is a reasonable way
to go (except for the round-off discrepancy). If not, let me know and
I'll try to update my patch for the desired behavior.
Also let me know if I should submit these bug reports/patches another
way--this is my first patch to libxslt and I think I followed the
guidelines at http://xmlsoft.org/XSLT/bugs.html.
Ken Neighbors
diff -aur cvs/XSLT/libxslt/numbers.c fix/XSLT/libxslt/numbers.c
--- cvs/XSLT/libxslt/numbers.c Tue Jun 11 07:45:07 2002
+++ fix/XSLT/libxslt/numbers.c Fri Jun 14 20:59:06 2002
@@ -109,16 +109,19 @@
/* Build buffer from back */
pointer = &temp_string[sizeof(temp_string)];
*(--pointer) = 0;
- for (i = 1; i < (int)sizeof(temp_string); i++) {
- *(--pointer) = digit_zero + (int)fmod(number, 10.0);
- number /= 10.0;
+ i = 0;
+ while (pointer > temp_string) {
if ((i >= width) && (fabs(number) < 1.0))
break; /* for */
- if ((groupingCharacter != 0) &&
+ if ((i > 0) && (groupingCharacter != 0) &&
(digitsPerGroup > 0) &&
((i % digitsPerGroup) == 0)) {
*(--pointer) = groupingCharacter;
}
+ if (pointer > temp_string)
+ *(--pointer) = digit_zero + (int)fmod(number, 10.0);
+ number /= 10.0;
+ ++i;
}
xmlBufferCat(buffer, pointer);
}
@@ -871,11 +874,13 @@
return XPATH_MEMORY_ERROR;
}
+ format_info.integer_hash = 0;
format_info.integer_digits = 0;
format_info.frac_digits = 0;
format_info.frac_hash = 0;
format_info.group = -1;
format_info.multiplier = 1;
+ format_info.add_decimal = FALSE;
format_info.is_multiplier_set = FALSE;
format_info.is_negative_pattern = FALSE;
@@ -906,6 +911,7 @@
found_error = 1;
goto OUTPUT_NUMBER;
}
+ format_info.integer_hash++;
if (format_info.group >= 0)
format_info.group++;
} else if (*the_format == self->zeroDigit[0]) {
@@ -934,8 +940,10 @@
}
/* We have finished the integer part, now work on fraction */
- if (*the_format == self->decimalPoint[0])
+ if (*the_format == self->decimalPoint[0]) {
+ format_info.add_decimal = TRUE;
the_format++; /* Skip over the decimal */
+ }
while (*the_format != 0) {
@@ -1070,11 +1078,13 @@
"xsltFormatNumberConversion : error in format string, using default\n");
default_sign = (number < 0.0) ? 1 : 0;
prefix_length = suffix_length = 0;
+ format_info.integer_hash = 0;
format_info.integer_digits = 1;
format_info.frac_digits = 1;
format_info.frac_hash = 4;
format_info.group = -1;
format_info.multiplier = 1;
+ format_info.add_decimal = TRUE;
}
/* Ready to output our number. First see if "default sign" is required */
@@ -1105,9 +1115,26 @@
format_info.group,
(xmlChar) ',');
+ /* Special case: java treats '.#' like '.0', '.##' like '.0#', etc. */
+ if ((format_info.integer_digits + format_info.integer_hash +
+ format_info.frac_digits == 0) && (format_info.frac_hash > 0)) {
+ ++format_info.frac_digits;
+ --format_info.frac_hash;
+ }
+
+ /* Add leading zero, if required */
+ if ((floor(number) == 0) &&
+ (format_info.integer_digits + format_info.frac_digits == 0)) {
+ xmlBufferAdd(buffer, self->zeroDigit, 1);
+ }
+
/* Next the fractional part, if required */
- if (format_info.frac_digits + format_info.frac_hash > 0) {
- number -= floor(number);
+ if (format_info.frac_digits + format_info.frac_hash == 0) {
+ if (format_info.add_decimal)
+ xmlBufferAdd(buffer, self->decimalPoint, 1);
+ }
+ else {
+ number -= floor(number);
if ((number != 0) || (format_info.frac_digits != 0)) {
xmlBufferAdd(buffer, self->decimalPoint, 1);
number = floor(scale * number + 0.5);
diff -aur cvs/XSLT/libxslt/numbersInternals.h fix/XSLT/libxslt/numbersInternals.h
--- cvs/XSLT/libxslt/numbersInternals.h Thu Mar 14 08:45:19 2002
+++ fix/XSLT/libxslt/numbersInternals.h Fri Jun 14 20:59:09 2002
@@ -40,11 +40,13 @@
* This data structure lists the various parameters needed to format numbers.
*/
typedef struct _xsltFormatNumberInfo {
+ int integer_hash; /* Number of '#' in integer part */
int integer_digits; /* Number of '0' in integer part */
int frac_digits; /* Number of '0' in fractional part */
int frac_hash; /* Number of '#' in fractional part */
int group; /* Number of chars per display 'group' */
int multiplier; /* Scaling for percent or permille */
+ char add_decimal; /* Flag for whether decimal point appears in pattern */
char is_multiplier_set; /* Flag to catch multiple occurences of percent/permille */
char is_negative_pattern;/* Flag for processing -ve prefix/suffix */
} xsltFormatNumberInfo, *xsltFormatNumberInfoPtr;
diff -aur cvs/XSLT/tests/numbers/format-number.out fix/XSLT/tests/numbers/format-number.out
--- cvs/XSLT/tests/numbers/format-number.out Sun May 6 07:45:15 2001
+++ fix/XSLT/tests/numbers/format-number.out Fri Jun 14 20:58:52 2002
@@ -1,7 +1,94 @@
<?xml version="1.0" encoding="iso-8859-1"?>
-<pi>
- one prefix3.14suffix
- two -_3.14_
- three -_003.1415_
- four _(3.1)_
- five prefix3*14suffix</pi>
+<format-number>
+ <fixes>
+ one prefix3.14suffix
+ two -_3.14_
+ three -_003.1415_
+ four _(3.1)_
+ five prefix3*14suffix
+ </fixes>
+ <point-test>
+ format-number(-1.0,'#' ) = -1
+ format-number(-0.5,'#' ) = -1
+ format-number( 0.0,'#' ) = 0
+ format-number( 0.5,'#' ) = 1
+ format-number( 1.0,'#' ) = 1
+ </point-test>
+ <point-test>
+ format-number(-1.0,'0' ) = -1
+ format-number(-0.5,'0' ) = -1
+ format-number( 0.0,'0' ) = 0
+ format-number( 0.5,'0' ) = 1
+ format-number( 1.0,'0' ) = 1
+ </point-test>
+ <point-test>
+ format-number(-1.0, '.' ) = -1.
+ format-number(-0.5, '.' ) = -1.
+ format-number( 0.0, '.' ) = 0.
+ format-number( 0.5, '.' ) = 1.
+ format-number( 1.0, '.' ) = 1.
+ </point-test>
+ <point-test>
+ format-number(-1.0,'#.' ) = -1.
+ format-number(-0.5,'#.' ) = -1.
+ format-number( 0.0,'#.' ) = 0.
+ format-number( 0.5,'#.' ) = 1.
+ format-number( 1.0,'#.' ) = 1.
+ </point-test>
+ <point-test>
+ format-number(-1.0,'0.' ) = -1.
+ format-number(-0.5,'0.' ) = -1.
+ format-number( 0.0,'0.' ) = 0.
+ format-number( 0.5,'0.' ) = 1.
+ format-number( 1.0,'0.' ) = 1.
+ </point-test>
+ <point-test>
+ format-number(-1.0, '.#') = -1.0
+ format-number(-0.5, '.#') = -.5
+ format-number( 0.0, '.#') = .0
+ format-number( 0.5, '.#') = .5
+ format-number( 1.0, '.#') = 1.0
+ </point-test>
+ <point-test>
+ format-number(-1.0, '.##') = -1.0
+ format-number(-0.5, '.##') = -.5
+ format-number( 0.0, '.##') = .0
+ format-number( 0.5, '.##') = .5
+ format-number( 1.0, '.##') = 1.0
+ </point-test>
+ <point-test>
+ format-number(-1.0, '.0') = -1.0
+ format-number(-0.5, '.0') = -.5
+ format-number( 0.0, '.0') = .0
+ format-number( 0.5, '.0') = .5
+ format-number( 1.0, '.0') = 1.0
+ </point-test>
+ <point-test>
+ format-number(-1.0,'#.#') = -1
+ format-number(-0.5,'#.#') = -0.5
+ format-number( 0.0,'#.#') = 0
+ format-number( 0.5,'#.#') = 0.5
+ format-number( 1.0,'#.#') = 1
+ </point-test>
+ <point-test>
+ format-number(-1.0,'0.0') = -1.0
+ format-number(-0.5,'0.0') = -0.5
+ format-number( 0.0,'0.0') = 0.0
+ format-number( 0.5,'0.0') = 0.5
+ format-number( 1.0,'0.0') = 1.0
+ </point-test>
+ <point-test>
+ format-number(-1.0,'#.0') = -1.0
+ format-number(-0.5,'#.0') = -.5
+ format-number( 0.0,'#.0') = .0
+ format-number( 0.5,'#.0') = .5
+ format-number( 1.0,'#.0') = 1.0
+ </point-test>
+ <point-test>
+ format-number(-1.0,'0.#') = -1
+ format-number(-0.5,'0.#') = -0.5
+ format-number( 0.0,'0.#') = 0
+ format-number( 0.5,'0.#') = 0.5
+ format-number( 1.0,'0.#') = 1
+ </point-test>
+</format-number>
diff -aur cvs/XSLT/tests/numbers/format-number.xml fix/XSLT/tests/numbers/format-number.xml
--- cvs/XSLT/tests/numbers/format-number.xml Mon Jan 29 17:44:52 2001
+++ fix/XSLT/tests/numbers/format-number.xml Fri Jun 14 20:58:52 2002
@@ -1,4 +1,13 @@
-<functions>
- <pi>3.1415</pi>
- <negpi>-3.1415</negpi>
-</functions>
+<format-number>
+ <fixes>
+ <pi>3.1415</pi>
+ <negpi>-3.1415</negpi>
+ </fixes>
+ <point-test>
+ <number>-1.0</number>
+ <number>-0.5</number>
+ <number> 0.0</number>
+ <number> 0.5</number>
+ <number> 1.0</number>
+ </point-test>
+</format-number>
diff -aur cvs/XSLT/tests/numbers/format-number.xsl fix/XSLT/tests/numbers/format-number.xsl
--- cvs/XSLT/tests/numbers/format-number.xsl Mon Jan 29 17:44:52 2001
+++ fix/XSLT/tests/numbers/format-number.xsl Fri Jun 14 20:58:52 2002
@@ -12,14 +12,119 @@
decimal-separator = "*"
/>
-<xsl:template match="functions">
- <pi>
- one <xsl:value-of select="format-number(pi, 'prefix#,#,###.##suffix')"/>
- two <xsl:value-of select="format-number(negpi, '_#,#,###.##_')"/>
- three <xsl:value-of select="format-number(negpi, '_#,#,000.000##_')"/>
- four <xsl:value-of select="format-number(negpi, '_#.#_;_(#.#)_')"/>
- five <xsl:value-of select="format-number(pi, 'prefix#,#,###*##suffix','special')"/>
- </pi>
+<xsl:template match="/format-number">
+ <format-number>
+ <xsl:apply-templates/>
+ </format-number>
+</xsl:template>
+
+<xsl:template match="/format-number/fixes">
+ <fixes>
+ one <xsl:value-of select="format-number(pi, 'prefix#,#,###.##suffix')"/>
+ two <xsl:value-of select="format-number(negpi, '_#,#,###.##_')"/>
+ three <xsl:value-of select="format-number(negpi, '_#,#,000.000##_')"/>
+ four <xsl:value-of select="format-number(negpi, '_#.#_;_(#.#)_')"/>
+ five <xsl:value-of select="format-number(pi, 'prefix#,#,###*##suffix','special')"/>
+ <xsl:text> </xsl:text>
+ </fixes>
+</xsl:template>
+
+<xsl:template match="/format-number/point-test">
+ <point-test>
+ <xsl:for-each select="number">
+ format-number(<xsl:value-of select="."/>,'#' )<xsl:text> = </xsl:text>
+ <xsl:value-of select="format-number(.,'#')"/>
+ </xsl:for-each>
+ <xsl:text> </xsl:text>
+ </point-test><xsl:text> </xsl:text>
+
+ <point-test>
+ <xsl:for-each select="number">
+ format-number(<xsl:value-of select="."/>,'0' )<xsl:text> = </xsl:text>
+ <xsl:value-of select="format-number(.,'0')"/>
+ </xsl:for-each>
+ <xsl:text> </xsl:text>
+ </point-test><xsl:text> </xsl:text>
+
+ <point-test>
+ <xsl:for-each select="number">
+ format-number(<xsl:value-of select="."/>, '.' )<xsl:text> = </xsl:text>
+ <xsl:value-of select="format-number(.,'.')"/>
+ </xsl:for-each>
+ <xsl:text> </xsl:text>
+ </point-test><xsl:text> </xsl:text>
+
+ <point-test>
+ <xsl:for-each select="number">
+ format-number(<xsl:value-of select="."/>,'#.' )<xsl:text> = </xsl:text>
+ <xsl:value-of select="format-number(.,'#.')"/>
+ </xsl:for-each>
+ <xsl:text> </xsl:text>
+ </point-test><xsl:text> </xsl:text>
+
+ <point-test>
+ <xsl:for-each select="number">
+ format-number(<xsl:value-of select="."/>,'0.' )<xsl:text> = </xsl:text>
+ <xsl:value-of select="format-number(.,'0.')"/>
+ </xsl:for-each>
+ <xsl:text> </xsl:text>
+ </point-test><xsl:text> </xsl:text>
+
+ <point-test>
+ <xsl:for-each select="number">
+ format-number(<xsl:value-of select="."/>, '.#')<xsl:text> = </xsl:text>
+ <xsl:value-of select="format-number(.,'.#')"/>
+ </xsl:for-each>
+ <xsl:text> </xsl:text>
+ </point-test><xsl:text> </xsl:text>
+
+ <point-test>
+ <xsl:for-each select="number">
+ format-number(<xsl:value-of select="."/>, '.##')<xsl:text> = </xsl:text>
+ <xsl:value-of select="format-number(.,'.##')"/>
+ </xsl:for-each>
+ <xsl:text> </xsl:text>
+ </point-test><xsl:text> </xsl:text>
+
+ <point-test>
+ <xsl:for-each select="number">
+ format-number(<xsl:value-of select="."/>, '.0')<xsl:text> = </xsl:text>
+ <xsl:value-of select="format-number(.,'.0')"/>
+ </xsl:for-each>
+ <xsl:text> </xsl:text>
+ </point-test><xsl:text> </xsl:text>
+
+ <point-test>
+ <xsl:for-each select="number">
+ format-number(<xsl:value-of select="."/>,'#.#')<xsl:text> = </xsl:text>
+ <xsl:value-of select="format-number(.,'#.#')"/>
+ </xsl:for-each>
+ <xsl:text> </xsl:text>
+ </point-test><xsl:text> </xsl:text>
+
+ <point-test>
+ <xsl:for-each select="number">
+ format-number(<xsl:value-of select="."/>,'0.0')<xsl:text> = </xsl:text>
+ <xsl:value-of select="format-number(.,'0.0')"/>
+ </xsl:for-each>
+ <xsl:text> </xsl:text>
+ </point-test><xsl:text> </xsl:text>
+
+ <point-test>
+ <xsl:for-each select="number">
+ format-number(<xsl:value-of select="."/>,'#.0')<xsl:text> = </xsl:text>
+ <xsl:value-of select="format-number(.,'#.0')"/>
+ </xsl:for-each>
+ <xsl:text> </xsl:text>
+ </point-test><xsl:text> </xsl:text>
+
+ <point-test>
+ <xsl:for-each select="number">
+ format-number(<xsl:value-of select="."/>,'0.#')<xsl:text> = </xsl:text>
+ <xsl:value-of select="format-number(.,'0.#')"/>
+ </xsl:for-each>
+ <xsl:text> </xsl:text>
+ </point-test>
</xsl:template>
</xsl:stylesheet>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]