From: Bjorn Reese Date: Sun, 11 Feb 2001 16:25:41 +0000 (+0000) Subject: Partial support for xsl:number/@level X-Git-Tag: v1.1.28~1472 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=08d6d40a944a94a6d78fd415e7ef1aa66a4a8213;p=platform%2Fupstream%2Flibxslt.git Partial support for xsl:number/@level --- diff --git a/AUTHORS b/AUTHORS index 60740c8..9f3c0e1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -10,4 +10,6 @@ Daniel Veillard: Bjorn Reese: breese@users.sourceforge.net - + http://home1.stofanet.dk/breese/ + Software developer at http://www.systematic.dk/ + Member of the XML-MTF Mapping WG. diff --git a/ChangeLog b/ChangeLog index 6049cd4..66d3008 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Sun Feb 11 17:24:03 CET 2001 Bjorn Reese + + * FEATURES libxslt/transform.c libxslt/numbers.c: partial support + for the level attribute for xsl:number + * libxslt/numbers.c: internal restructuring + Fri Feb 9 15:49:19 CET 2001 Daniel Veillard * libxslt/Makefile.am libxslt/documents.[ch]: added a new module diff --git a/FEATURES b/FEATURES index d094e8e..e3b38a5 100644 --- a/FEATURES +++ b/FEATURES @@ -117,7 +117,7 @@ YES select = string-expression NO disable-output-escaping = "yes" | "no" YES xsl:number -NO level = "single" | "multiple" | "any" +PARTIAL level = "single" | "multiple" | "any" NO count = pattern NO from = pattern YES value = number-expression diff --git a/libxslt/numbers.c b/libxslt/numbers.c index 3a15187..5d44de6 100644 --- a/libxslt/numbers.c +++ b/libxslt/numbers.c @@ -10,7 +10,6 @@ * Bjorn Reese */ -#include #include #include #include @@ -22,6 +21,7 @@ #include #endif +#include #include #include #include "xsltutils.h" @@ -34,7 +34,6 @@ #define SYMBOL_QUOTE ((xmlChar)'\'') -static char digit_list[] = "0123456789"; static char alpha_upper_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static char alpha_lower_list[] = "abcdefghijklmnopqrstuvwxyz"; @@ -75,6 +74,18 @@ xsltIsDigitZero(xmlChar ch) } #ifndef isnan +/* + * NaN (Not-A-Number) + * + * In C99 isnan() is defined as a macro, so its existence can be determined + * with the preprocessor. + * + * ANSI/IEEE 754-1986 states that "Every NaN shall compare unordered + * with everything, including itself." This means that "number == number" + * will return true for all numbers, except NaN. Unfortunately, this + * simple test does not work on all platforms supporting NaNs. Instead + * we use an almost equivalent comparison. + */ static int isnan(volatile double number) { @@ -83,6 +94,11 @@ isnan(volatile double number) #endif #ifndef isinf +/* + * Infinity (positive and negative) + * + * C99 defines isinf() as a macro. See comment for isnan(). + */ static int isinf(double number) { @@ -96,7 +112,466 @@ isinf(double number) /************************************************************************ * - * JDK 1.1 DecimalFormat class: + * xsltNumberFormat + * + * Convert one number. + */ +static void +xsltNumberFormatDecimal(xmlBufferPtr buffer, + double number, + xmlChar digit_zero, + int width, + int digitsPerGroup, + xmlChar groupingCharacter) +{ + xmlChar temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 1]; + xmlChar *pointer; + int i; + + /* 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; + if ((i >= width) && (fabs(number) < 1.0)) + break; /* for */ + if ((groupingCharacter != 0) && + (digitsPerGroup > 0) && + ((i % digitsPerGroup) == 0)) { + *(--pointer) = groupingCharacter; + } + } + xmlBufferCat(buffer, pointer); +} + +static void +xsltNumberFormatAlpha(xmlBufferPtr buffer, + double number, + int is_upper) +{ + char temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 1]; + char *pointer; + int i; + char *alpha_list; + double alpha_size = (double)(sizeof(alpha_upper_list) - 1); + + /* Build buffer from back */ + pointer = &temp_string[sizeof(temp_string)]; + *(--pointer) = 0; + alpha_list = (is_upper) ? alpha_upper_list : alpha_lower_list; + + for (i = 1; i < (int)sizeof(buffer); i++) { + number--; + *(--pointer) = alpha_list[((int)fmod(number, alpha_size))]; + number /= alpha_size; + if (fabs(number) < 1.0) + break; /* for */ + } + xmlBufferCCat(buffer, pointer); +} + +static void +xsltNumberFormatRoman(xmlBufferPtr buffer, + double number, + int is_upper) +{ + /* + * Based on an example by Jim Walsh + */ + while (number >= 1000.0) { + xmlBufferCCat(buffer, (is_upper) ? "M" : "m"); + number -= 1000.0; + } + if (number >= 900.0) { + xmlBufferCCat(buffer, (is_upper) ? "CM" : "cm"); + number -= 900.0; + } + while (number >= 500.0) { + xmlBufferCCat(buffer, (is_upper) ? "D" : "d"); + number -= 500.0; + } + if (number >= 400.0) { + xmlBufferCCat(buffer, (is_upper) ? "CD" : "cd"); + number -= 400.0; + } + while (number >= 100.0) { + xmlBufferCCat(buffer, (is_upper) ? "C" : "c"); + number -= 100.0; + } + if (number >= 90.0) { + xmlBufferCCat(buffer, (is_upper) ? "XC" : "xc"); + number -= 90.0; + } + while (number >= 50.0) { + xmlBufferCCat(buffer, (is_upper) ? "L" : "l"); + number -= 50.0; + } + if (number >= 40.0) { + xmlBufferCCat(buffer, (is_upper) ? "XL" : "xl"); + number -= 40.0; + } + while (number >= 10.0) { + xmlBufferCCat(buffer, (is_upper) ? "X" : "x"); + number -= 10.0; + } + if (number >= 9.0) { + xmlBufferCCat(buffer, (is_upper) ? "IX" : "ix"); + number -= 9.0; + } + while (number >= 5.0) { + xmlBufferCCat(buffer, (is_upper) ? "V" : "v"); + number -= 5.0; + } + if (number >= 4.0) { + xmlBufferCCat(buffer, (is_upper) ? "IV" : "iv"); + number -= 4.0; + } + while (number >= 1.0) { + xmlBufferCCat(buffer, (is_upper) ? "I" : "i"); + number--; + } +} + +typedef struct _xsltNumberFormatToken { + xmlChar token; + int width; + xmlChar *filling; +} xsltNumberFormatToken, *xsltNumberFormatTokenPtr; + +static int +xsltNumberFormatTokenize(xmlChar *format, + xsltNumberFormatTokenPtr array, + int array_max) +{ + int index = 0; + int cnt; + int j; + + for (cnt = 0; cnt < array_max; cnt++) { + if (format[index] == 0) { + break; /* for */ + } else if (IS_DIGIT_ONE(format[index]) || + IS_DIGIT_ZERO(format[index])) { + array[cnt].width = 1; + while (IS_DIGIT_ZERO(format[index])) { + array[cnt].width++; + index++; + } + if (IS_DIGIT_ONE(format[index])) { + array[cnt].token = format[index] - 1; + index++; + } + } else if (format[index] == (xmlChar)'A') { + array[cnt].token = format[index]; + index++; + } else if (format[index] == (xmlChar)'a') { + array[cnt].token = format[index]; + index++; + } else if (format[index] == (xmlChar)'I') { + array[cnt].token = format[index]; + index++; + } else if (format[index] == (xmlChar)'i') { + array[cnt].token = format[index]; + index++; + } else { + /* XSLT section 7.7 + * "Any other format token indicates a numbering sequence + * that starts with that token. If an implementation does + * not support a numbering sequence that starts with that + * token, it must use a format token of 1." + */ + array[cnt].token = (xmlChar)'0'; + array[cnt].width = 1; + index++; + } + /* + * Skip over remaining alphanumeric characters from the Nd + * (Number, decimal digit), Nl (Number, letter), No (Number, + * other), Lu (Letter, uppercase), Ll (Letter, lowercase), Lt + * (Letters, titlecase), Lm (Letters, modifiers), and Lo + * (Letters, other (uncased)) Unicode categories. This happens + * to correspond to the Letter and Digit classes from XML (and + * one wonders why XSLT doesn't refer to these instead). + */ + while (IS_LETTER(format[index]) || IS_DIGIT(format[index])) + index++; + /* + * Insert non-alphanumeric separator. + */ + j = index; + while (! (IS_LETTER(format[index]) || IS_DIGIT(format[index]))) { + if (format[index] == 0) + break; /* while */ + index++; + } + array[cnt].filling = (index > j) + ? xmlStrndup(&format[j], index - j) + : NULL; + } + return cnt; +} + + +static void +xsltNumberFormatInsertNumbers(xsltNumberDataPtr data, + double *numbers, + int numbers_max, + xsltNumberFormatToken (*array)[], + int array_max, + xmlBufferPtr buffer) +{ + int i = 0; + int minmax; + double number; + xsltNumberFormatTokenPtr token; + + minmax = (array_max >= numbers_max) ? numbers_max : array_max; + for (i = 0; i < minmax; i++) { + /* Insert number */ + number = numbers[(numbers_max - 1) - i]; + token = &(*array)[i]; + + switch (isinf(number)) { + case -1: + xmlBufferCCat(buffer, "-Infinity"); + break; + case 1: + xmlBufferCCat(buffer, "Infinity"); + break; + default: + if (isnan(number)) { + xmlBufferCCat(buffer, "NaN"); + } else { + + switch (token->token) { + case 'A': + xsltNumberFormatAlpha(buffer, + number, + TRUE); + + break; + case 'a': + xsltNumberFormatAlpha(buffer, + number, + FALSE); + + break; + case 'I': + xsltNumberFormatRoman(buffer, + number, + TRUE); + + break; + case 'i': + xsltNumberFormatRoman(buffer, + number, + FALSE); + + break; + default: + if (IS_DIGIT_ZERO(token->token)) { + xsltNumberFormatDecimal(buffer, + number, + token->token, + token->width, + data->digitsPerGroup, + data->groupingCharacter); + } + break; + } + } + + } + + if (token->filling) + xmlBufferCat(buffer, token->filling); + } +} + +#if 0 +static void +xsltNumberFormatGetAnyLevel(xmlXPathContextPtr context) +{ + /* preceding | ancestor-or-self */ +} +#endif + +static int +xsltNumberFormatMatch(xmlXPathContextPtr context, + xmlNodePtr node, + xmlChar *pattern) +{ + /* FIXME: must handle generic patterns */ + return xmlStrEqual(node->name, pattern); +} + +static int +xsltNumberFormatGetMultipleLevel(xmlXPathContextPtr context, + xmlNodePtr node, + xmlChar *count, + xmlChar *from, + double *array, + int max) +{ + int amount = 0; + int cnt; + xmlNodePtr ancestor; + xmlNodePtr preceding; + xmlXPathParserContextPtr parser; + + context->node = node; + parser = xmlXPathNewParserContext(NULL, context); + if (parser) { + /* ancestor-or-self::*[count] */ + for (ancestor = node; + ancestor != NULL; + ancestor = xmlXPathNextAncestor(parser, ancestor)) { + + if ((from != NULL) && + xsltNumberFormatMatch(context, ancestor, from)) + break; /* for */ + + if ((count == NULL) || + xsltNumberFormatMatch(context, ancestor, count)) { + /* count(preceding-sibling::*) */ + cnt = 0; + for (preceding = ancestor; + preceding != NULL; + preceding = xmlXPathNextPrecedingSibling(parser, preceding)) { + if (count == NULL) { + if (preceding->type == ancestor->type) + cnt++; + } else { + if (preceding->type != XML_TEXT_NODE) + cnt++; + } + } + array[amount++] = (double)cnt; + } + } + xmlXPathFreeParserContext(parser); + } + return amount; +} + +static int +xsltNumberFormatGetValue(xmlXPathContextPtr context, + xmlNodePtr node, + xmlChar *value, + double *number) +{ + int amount = 0; + xmlBufferPtr pattern; + xmlXPathObjectPtr obj; + + pattern = xmlBufferCreate(); + if (pattern != NULL) { + xmlBufferCCat(pattern, "number("); + xmlBufferCat(pattern, value); + xmlBufferCCat(pattern, ")"); + context->node = node; + obj = xmlXPathEvalExpression(xmlBufferContent(pattern), + context); + if (obj != NULL) { + *number = obj->floatval; + amount++; + xmlXPathFreeObject(obj); + } + xmlBufferFree(pattern); + } + return amount; +} + +void +xsltNumberFormat(xsltTransformContextPtr ctxt, + xsltNumberDataPtr data, + xmlNodePtr node) +{ + xmlBufferPtr output = NULL; + xmlNodePtr copy = NULL; + int amount; + int array_amount; + double number; + xsltNumberFormatToken array[1024]; + + output = xmlBufferCreate(); + if (output == NULL) + goto XSLT_NUMBER_FORMAT_END; + + array_amount = xsltNumberFormatTokenize(data->format, + array, + sizeof(array)/sizeof(array[0])); + + /* + * Evaluate the XPath expression to find the value(s) + */ + if (data->value) { + amount = xsltNumberFormatGetValue(ctxt->xpathCtxt, + node, + data->value, + &number); + if (amount == 1) { + xsltNumberFormatInsertNumbers(data, + &number, + 1, + &array, + array_amount, + output); + } + + } else if (data->level) { + + if (xmlStrEqual(data->level, "single")) { + amount = xsltNumberFormatGetMultipleLevel(ctxt->xpathCtxt, + node, + data->count, + data->from, + &number, + 1); + if (amount == 1) { + xsltNumberFormatInsertNumbers(data, + &number, + 1, + &array, + array_amount, + output); + } + } else if (xmlStrEqual(data->level, "multiple")) { + double numarray[1024]; + int max = sizeof(numarray)/sizeof(numarray[0]); + amount = xsltNumberFormatGetMultipleLevel(ctxt->xpathCtxt, + node, + data->count, + data->from, + numarray, + max); + if (amount > 0) { + xsltNumberFormatInsertNumbers(data, + numarray, + amount, + &array, + array_amount, + output); + } + } else if (xmlStrEqual(data->level, "any")) { + TODO; + } + } + /* Insert number as text node */ + copy = xmlNewText(xmlBufferContent(output)); + if (copy != NULL) { + xmlAddChild(ctxt->insert, copy); + } + + XSLT_NUMBER_FORMAT_END: + if (output != NULL) + xmlBufferFree(output); +} + +/************************************************************************ + * + * format-number() uses the JDK 1.1 DecimalFormat class: * * http://java.sun.com/products/jdk/1.1/docs/api/java.text.DecimalFormat.html * @@ -129,14 +604,6 @@ isinf(double number) * X any other characters can be used in the prefix or suffix * ' used to quote special characters in a prefix or suffix. */ -/* TODO - * - * The JDK description does not tell where they may and may not appear - * within the format string. Nor does it tell what happens to integer - * values that does not fit into the format string. - * - * Inf and NaN not tested. - */ xmlXPathError xsltFormatNumberConversion(xsltDecimalFormatPtr self, xmlChar *format, @@ -146,18 +613,14 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self, xmlXPathError status = XPATH_EXPRESSION_OK; xmlChar *the_format; xmlBufferPtr buffer; - char digit_buffer[2]; int use_minus; int i, j; int length; - int group = 0; + int group = INT_MAX; int integer_digits = 0; - int integer_hash = 0; int fraction_digits = 0; int fraction_hash = 0; int decimal_point; - double divisor; - int digit; int is_percent; int is_permille; @@ -226,9 +689,13 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self, /* * Parse the number part of the format string */ + is_percent = (the_format[i] == self->percent[0]) ? TRUE : FALSE; + is_permille = (the_format[i] == self->permille[0]) ? TRUE : FALSE; + if (is_percent || is_permille) + i++; + for ( ; i < length; i++) { if (the_format[i] == self->zeroDigit[0]) { - integer_hash++; group++; } else if (the_format[i] == self->grouping[0]) { group = 0; /* Reset count */ @@ -260,8 +727,12 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self, break; /* for */ } } - is_percent = (the_format[i] == self->percent[0]) ? TRUE : FALSE; - is_permille = (the_format[i] == self->permille[0]) ? TRUE : FALSE; + if (!(is_percent || is_permille)) { + is_percent = (the_format[i] == self->percent[0]) ? TRUE : FALSE; + is_permille = (the_format[i] == self->permille[0]) ? TRUE : FALSE; + if (is_percent || is_permille) + i++; + } /* * Format the number @@ -275,35 +746,27 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self, number *= 100.0; else if (is_permille) number *= 1000.0; - number = floor(0.5 + number * pow(10.0, (double)(fraction_digits + fraction_hash))); /* Integer part */ - digit_buffer[1] = (char)0; - divisor = pow(10.0, (double)(integer_digits + integer_hash + fraction_digits + fraction_hash - 1)); - for (j = integer_digits + integer_hash; j > 0; j--) { - digit = (int)(number / divisor); - number -= (double)digit * divisor; - divisor /= 10.0; - if ((digit > 0) || (j <= integer_digits)) { - digit_buffer[0] = digit_list[digit]; - xmlBufferCCat(buffer, digit_buffer); - } - } - - if (decimal_point) + xsltNumberFormatDecimal(buffer, floor(number), (xmlChar)'0', + integer_digits, group, (xmlChar)','); + + if (decimal_point) { xmlBufferAdd(buffer, self->decimalPoint, 1); - /* Fraction part */ - for (j = fraction_digits + fraction_hash; j > 0; j--) { - digit = (int)(number / divisor); - number -= (double)digit * divisor; - divisor /= 10.0; - if ((digit > 0) || (j > fraction_hash)) { - digit_buffer[0] = digit_list[digit]; - xmlBufferCCat(buffer, digit_buffer); + /* Fraction part */ + number -= floor(number); + number = number * pow(10.0, (double)(fraction_digits + fraction_hash)); + for (j = fraction_hash; j > 0; j--) { + if (fmod(number, 10.0) >= 1.0) + break; /* for */ + number /= 10.0; } + number = floor(0.5 + number); + xsltNumberFormatDecimal(buffer, number, (xmlChar)'0', + fraction_digits + j, + 0, (xmlChar)0); } - if (is_percent) xmlBufferAdd(buffer, self->percent, 1); else if (is_permille) @@ -323,259 +786,3 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self, xmlBufferFree(buffer); return status; } - -/************************************************************************ - * - * xsltNumberFormat - * - * Convert one number. - */ -static void -xsltNumberFormatDecimal(xmlBufferPtr buffer, - double number, - xmlChar digit_zero, - int width, - int digitsPerGroup, - xmlChar groupingCharacter) -{ - xmlChar temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 1]; - xmlChar *pointer; - int i; - - /* Build buffer from back */ - pointer = &temp_string[sizeof(temp_string) - 1]; - *pointer-- = 0; - for (i = 1; i < (int)sizeof(temp_string); i++) { - *pointer-- = digit_zero + (int)fmod(number, 10.0); - number /= 10.0; - width--; - if ((width <= 0) && (fabs(number) < 1.0)) - break; /* for */ - if ((groupingCharacter != 0) && - ((i % digitsPerGroup) == 0)) { - *pointer-- = groupingCharacter; - } - } - xmlBufferCat(buffer, pointer + 1); -} - -static void -xsltNumberFormatAlpha(xmlBufferPtr buffer, - double number, - int is_upper) -{ - char temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 1]; - char *pointer; - int i; - char *alpha_list; - double alpha_size = (double)(sizeof(alpha_upper_list) - 1); - - /* Build buffer from back */ - pointer = &temp_string[sizeof(temp_string) - 1]; - *pointer-- = 0; - alpha_list = (is_upper) ? alpha_upper_list : alpha_lower_list; - - for (i = 1; i < (int)sizeof(buffer); i++) { - number--; - *pointer-- = alpha_list[((int)fmod(number, alpha_size))]; - number /= alpha_size; - if (fabs(number) < 1.0) - break; /* for */ - } - xmlBufferCCat(buffer, pointer + 1); -} - -static void -xsltNumberFormatRoman(xmlBufferPtr buffer, - double number, - int is_upper) -{ - /* - * Based on an example by Jim Walsh - */ - while (number >= 1000.0) { - xmlBufferCCat(buffer, (is_upper) ? "M" : "m"); - number -= 1000.0; - } - if (number >= 900.0) { - xmlBufferCCat(buffer, (is_upper) ? "CM" : "cm"); - number -= 900.0; - } - while (number >= 500.0) { - xmlBufferCCat(buffer, (is_upper) ? "D" : "d"); - number -= 500.0; - } - if (number >= 400.0) { - xmlBufferCCat(buffer, (is_upper) ? "CD" : "cd"); - number -= 400.0; - } - while (number >= 100.0) { - xmlBufferCCat(buffer, (is_upper) ? "C" : "c"); - number -= 100.0; - } - if (number >= 90.0) { - xmlBufferCCat(buffer, (is_upper) ? "XC" : "xc"); - number -= 90.0; - } - while (number >= 50.0) { - xmlBufferCCat(buffer, (is_upper) ? "L" : "l"); - number -= 50.0; - } - if (number >= 40.0) { - xmlBufferCCat(buffer, (is_upper) ? "XL" : "xl"); - number -= 40.0; - } - while (number >= 10.0) { - xmlBufferCCat(buffer, (is_upper) ? "X" : "x"); - number -= 10.0; - } - if (number >= 9.0) { - xmlBufferCCat(buffer, (is_upper) ? "IX" : "ix"); - number -= 9.0; - } - while (number >= 5.0) { - xmlBufferCCat(buffer, (is_upper) ? "V" : "v"); - number -= 5.0; - } - if (number >= 4.0) { - xmlBufferCCat(buffer, (is_upper) ? "IV" : "iv"); - number -= 4.0; - } - while (number >= 1.0) { - xmlBufferCCat(buffer, (is_upper) ? "I" : "i"); - number--; - } -} - -void -xsltNumberFormat(xsltTransformContextPtr ctxt, - xsltNumberDataPtr data, - xmlNodePtr node) -{ - xmlXPathParserContextPtr parser = NULL; - xmlXPathObjectPtr res; - xmlBufferPtr buffer; - xmlNodePtr copy = NULL; - xmlChar *format; - int i, j; - int width; - - buffer = xmlBufferCreate(); - if (buffer == NULL) - goto XSLT_NUMBER_FORMAT_END; - - format = data->format; - - /* - * Evaluate the XPath expression to find the value(s) - */ - parser = xmlXPathNewParserContext(data->value, ctxt->xpathCtxt); - if (parser == NULL) - goto XSLT_NUMBER_FORMAT_END; - ctxt->xpathCtxt->node = node; - valuePush(parser, xmlXPathNewNodeSet(node)); - xmlXPathEvalExpr(parser); - - /* - * Parse format string - */ - i = 0; - for (;;) { - /* - * Workaround: - * There always seem to be a superfluos object on the stack. - * We handle this by exiting the loop if there is only one - * object back. - */ - if (parser->valueNr == 1) - break; /* for */ - - /* Cast to number if necessary */ - if ((parser->value != NULL) && - (parser->value->type != XPATH_NUMBER)) - xmlXPathNumberFunction(parser, 1); - - res = valuePop(parser); - if (res == NULL) - break; /* for */ - - if (res->type == XPATH_NUMBER) { - - switch (isinf(res->floatval)) { - case -1: - xmlBufferCCat(buffer, "-Infinity"); - break; - case 1: - xmlBufferCCat(buffer, "Infinity"); - break; - default: - if (isnan(res->floatval)) { - xmlBufferCCat(buffer, "NaN"); - } else { - - /* Find formatting token */ - if (IS_DIGIT_ONE(format[i]) || IS_DIGIT_ZERO(format[i])) { - width = 1; - while (IS_DIGIT_ZERO(format[i])) { - width++; - i++; - } - if (IS_DIGIT_ONE(format[i])) { - xsltNumberFormatDecimal(buffer, - res->floatval, - format[i] - 1, - width, - data->digitsPerGroup, - data->groupingCharacter); - i++; - } - } else if (format[i] == 'A') { - xsltNumberFormatAlpha(buffer, - res->floatval, - TRUE); - i++; - } else if (format[i] == 'a') { - xsltNumberFormatAlpha(buffer, - res->floatval, - FALSE); - i++; - } else if (format[i] == 'I') { - xsltNumberFormatRoman(buffer, - res->floatval, - TRUE); - i++; - } else if (format[i] == 'i') { - xsltNumberFormatRoman(buffer, - res->floatval, - FALSE); - i++; - } - } - break; - } - /* Insert separator */ - for (j = i; !isalnum(format[i]); i++) - ; - if (i > j) - xmlBufferAdd(buffer, &format[j], i - j); - } - xmlXPathFreeObject(res); - } - /* Insert number as text */ - copy = xmlNewText(xmlBufferContent(buffer)); - if (copy != NULL) { - xmlAddChild(ctxt->insert, copy); - } - - if (parser != NULL) { - while ((res = valuePop(parser)) != NULL) { - xmlXPathFreeObject(res); - } - } - - XSLT_NUMBER_FORMAT_END: - if (parser != NULL) - xmlXPathFreeParserContext(parser); - if (buffer != NULL) - xmlBufferFree(buffer); -} diff --git a/libxslt/numbersInternals.h b/libxslt/numbersInternals.h index 600c959..a112d23 100644 --- a/libxslt/numbersInternals.h +++ b/libxslt/numbersInternals.h @@ -10,6 +10,7 @@ #ifndef __XML_XSLT_NUMBERSINTERNALS_H__ #define __XML_XSLT_NUMBERSINTERNALS_H__ +#include #include "xsltInternals.h" #ifdef __cplusplus @@ -20,6 +21,9 @@ extern "C" { * This data structure is just a wrapper to pass data in */ typedef struct _xsltNumberData { + xmlChar *level; + xmlChar *count; + xmlChar *from; xmlChar *value; xmlChar *format; int digitsPerGroup; diff --git a/libxslt/transform.c b/libxslt/transform.c index 49576d8..294d5a5 100644 --- a/libxslt/transform.c +++ b/libxslt/transform.c @@ -830,59 +830,31 @@ xsltNumber(xsltTransformContextPtr ctxt, memset(&numdata, 0, sizeof(numdata)); - prop = xmlGetNsProp(cur, (const xmlChar *)"level", XSLT_NAMESPACE); - if (prop != NULL) { - if (xmlStrEqual(prop, BAD_CAST("single"))) { - TODO; - } else if (xmlStrEqual(prop, BAD_CAST("multiple"))) { - TODO; - } else if (xmlStrEqual(prop, BAD_CAST("any"))) { - TODO; - } else { - xsltGenericError(xsltGenericErrorContext, - "invalid value %s for level\n", prop); - } - xmlFree(prop); - } - - prop = xmlGetNsProp(cur, (const xmlChar *)"count", XSLT_NAMESPACE); - if (prop != NULL) { - TODO; - xmlFree(prop); - } - - prop = xmlGetNsProp(cur, (const xmlChar *)"from", XSLT_NAMESPACE); - if (prop != NULL) { - TODO; - xmlFree(prop); - } - - prop = xmlGetNsProp(cur, (const xmlChar *)"value", XSLT_NAMESPACE); - if (prop != NULL) { - numdata.value = prop; - } else { - numdata.value = xmlStrdup(BAD_CAST("position()")); - } + numdata.value = xmlGetNsProp(cur, (const xmlChar *)"value", XSLT_NAMESPACE); prop = xmlGetNsProp(cur, (const xmlChar *)"format", XSLT_NAMESPACE); if (prop != NULL) { - /* Unicode categories: - * Nd = Number, decimal digit - * Nl = Number, letter - * No = Number, other - * Lu = Letters, uppercase - * Ll = Letters, lowercase - * Lt = Letters, titlecase - * Lm = Letters, modifiers - * Lo = Letters, other (uncased) - * - * This corresponds to isalnum() in a Unicode locale. - */ numdata.format = prop; } else { numdata.format = xmlStrdup(BAD_CAST("1")); } + numdata.count = xmlGetNsProp(cur, (const xmlChar *)"count", XSLT_NAMESPACE); + numdata.from = xmlGetNsProp(cur, (const xmlChar *)"from", XSLT_NAMESPACE); + + prop = xmlGetNsProp(cur, (const xmlChar *)"level", XSLT_NAMESPACE); + if (prop != NULL) { + if (xmlStrEqual(prop, BAD_CAST("single")) || + xmlStrEqual(prop, BAD_CAST("multiple")) || + xmlStrEqual(prop, BAD_CAST("any"))) { + numdata.level = prop; + } else { + xsltGenericError(xsltGenericErrorContext, + "invalid value %s for level\n", prop); + xmlFree(prop); + } + } + prop = xmlGetNsProp(cur, (const xmlChar *)"lang", XSLT_NAMESPACE); if (prop != NULL) { TODO; @@ -918,10 +890,16 @@ xsltNumber(xsltTransformContextPtr ctxt, xsltNumberFormat(ctxt, &numdata, node); - if (numdata.format != NULL) - xmlFree(numdata.format); + if (numdata.level != NULL) + xmlFree(numdata.level); + if (numdata.count != NULL) + xmlFree(numdata.count); + if (numdata.from != NULL) + xmlFree(numdata.from); if (numdata.value != NULL) xmlFree(numdata.value); + if (numdata.format != NULL) + xmlFree(numdata.format); } /**