fixed bug #78501 when using a non ascii character for the number
authorDaniel Veillard <veillard@src.gnome.org>
Tue, 22 Oct 2002 15:34:36 +0000 (15:34 +0000)
committerDaniel Veillard <veillard@src.gnome.org>
Tue, 22 Oct 2002 15:34:36 +0000 (15:34 +0000)
* libxslt/numbers.c libxslt/numbersInternals.h libxslt/xsltutils.[ch]:
  fixed bug #78501 when using a non ascii character for the
  number formatting grouping separator.
* tests/docs/Makefile.am tests/docs/bug-95.xml
  tests/general/Makefile.am tests/general/bug-95.*: added the
  example in the regression tests for this case
* libxslt/attributes.c: cleaning up a problem introduced in last
  patch
Daniel

12 files changed:
ChangeLog
libxslt/attributes.c
libxslt/numbers.c
libxslt/numbersInternals.h
libxslt/preproc.c
libxslt/xsltutils.c
libxslt/xsltutils.h
tests/docs/Makefile.am
tests/docs/bug-95.xml [new file with mode: 0644]
tests/general/Makefile.am
tests/general/bug-95.out [new file with mode: 0644]
tests/general/bug-95.xsl [new file with mode: 0644]

index afad426..458d837 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Mon Oct 21 20:56:31 CEST 2002 Daniel Veillard <daniel@veillard.com>
+
+       * libxslt/numbers.c libxslt/numbersInternals.h libxslt/xsltutils.[ch]:
+         fixed bug #78501 when using a non ascii character for the
+         number formatting grouping separator.
+       * tests/docs/Makefile.am tests/docs/bug-95.xml
+         tests/general/Makefile.am tests/general/bug-95.*: added the
+         example in the regression tests for this case
+       * libxslt/attributes.c: cleaning up a problem introduced in last
+         patch
+
 Mon Oct 21 09:31:55 CEST 2002 Igor Zlatkovic <igor@stud.fh-frankfurt.de>
 
        * libxslt/attributes.c: fixed minor typo in a call to
index 39d6563..368e1b4 100644 (file)
@@ -617,7 +617,10 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt, xmlNodePtr node,
         URL = ns->href;
 
     if (fromset) {
-       attr = xmlHasNsProp(ctxt->insert, name, ns->href);
+       if (URL != NULL)
+           attr = xmlHasNsProp(ctxt->insert, name, URL);
+       else
+           attr = xmlHasProp(ctxt->insert, name);
        if (attr != NULL)
            return;
     }
index e99aed2..39641ff 100644 (file)
@@ -21,6 +21,7 @@
 #include <libxml/parserInternals.h>
 #include <libxml/xpath.h>
 #include <libxml/xpathInternals.h>
+#include <libxml/encoding.h>
 #include "xsltutils.h"
 #include "pattern.h"
 #include "templates.h"
@@ -100,9 +101,10 @@ xsltNumberFormatDecimal(xmlBufferPtr buffer,
                        xmlChar digit_zero,
                        int width,
                        int digitsPerGroup,
-                       xmlChar groupingCharacter)
+                       int groupingCharacter,
+                       int groupingCharacterLen)
 {
-    xmlChar temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 1];
+    xmlChar temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 4];
     xmlChar *pointer;
     int i;
 
@@ -116,7 +118,8 @@ xsltNumberFormatDecimal(xmlBufferPtr buffer,
        if ((i > 0) && (groupingCharacter != 0) &&
            (digitsPerGroup > 0) &&
            ((i % digitsPerGroup) == 0)) {
-           *(--pointer) = groupingCharacter;
+           pointer -= groupingCharacterLen;
+           xmlCopyCharMultiByte(pointer, groupingCharacter);
        }
        if (pointer > temp_string)
            *(--pointer) = digit_zero + (int)fmod(number, 10.0);
@@ -403,7 +406,8 @@ xsltNumberFormatInsertNumbers(xsltNumberDataPtr data,
                                                token->token,
                                                token->width,
                                                data->digitsPerGroup,
-                                               data->groupingCharacter);
+                                               data->groupingCharacter,
+                                               data->groupingCharacterLen);
                    }
                    break;
                }
@@ -837,6 +841,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
     int            prefix_length, suffix_length = 0, nprefix_length, nsuffix_length;
     double  scale;
     int            j;
+    int     self_grouping_len;
     xsltFormatNumberInfo format_info;
     /* delayed_multiplier allows a 'trailing' percent or permille to be treated as suffix */
     int                delayed_multiplier = 0;
@@ -897,6 +902,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
     /* Here we process the "number" part of the format.  It gets a little messy because of    */
     /* the percent/per-mille - if that appears at the end, it may be part of the suffix       */
     /* instead of part of the number, so the variable delayed_multiplier is used to handle it */
+    self_grouping_len = xmlStrlen(self->grouping);
     while ((*the_format != 0) &&
           (*the_format != self->decimalPoint[0]) &&
           (*the_format != self->patternSeparator[0])) {
@@ -918,9 +924,12 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
            format_info.integer_digits++;
            if (format_info.group >= 0)
                format_info.group++;
-       } else if (*the_format == self->grouping[0]) {
+       } else if ((self_grouping_len > 0) &&
+           (!xmlStrncmp(the_format, self->grouping, self_grouping_len))) {
            /* Reset group count */
            format_info.group = 0;
+           the_format += self_grouping_len;
+           continue;
        } else if (*the_format == self->percent[0]) {
            if (format_info.is_multiplier_set) {
                found_error = 1;
@@ -1103,16 +1112,18 @@ OUTPUT_NUMBER:
     number = fabs(number) * (double)format_info.multiplier;
     scale = pow(10.0, (double)(format_info.frac_digits + format_info.frac_hash));
     number = floor((scale * number + 0.5)) / scale;
-    if ((self->grouping != NULL) && (self->grouping[0] != 0))
+    if ((self->grouping != NULL) && (self->grouping[0] != 0)) {
+       int sep, len;
+       sep = xsltGetUTF8Char(self->grouping, &len);
        xsltNumberFormatDecimal(buffer, floor(number), self->zeroDigit[0],
                                format_info.integer_digits,
                                format_info.group,
-                               (xmlChar) self->grouping[0]);
-    else
+                               sep, len);
+    else
        xsltNumberFormatDecimal(buffer, floor(number), self->zeroDigit[0],
                                format_info.integer_digits,
                                format_info.group,
-                               (xmlChar) ',');
+                               ',', 1);
 
     /* Special case: java treats '.#' like '.0', '.##' like '.0#', etc. */
     if ((format_info.integer_digits + format_info.integer_hash +
@@ -1144,7 +1155,7 @@ OUTPUT_NUMBER:
            }
            xsltNumberFormatDecimal(buffer, floor(number), self->zeroDigit[0],
                                format_info.frac_digits + j,
-                               0, (xmlChar)0);
+                               0, 0, 0);
        }
     }
     /* Put the suffix into the buffer */
index c599f0d..b1a583e 100644 (file)
@@ -29,7 +29,8 @@ typedef struct _xsltNumberData {
     xmlChar *format;
     int has_format;
     int digitsPerGroup;
-    xmlChar groupingCharacter;
+    int groupingCharacter;
+    int groupingCharacterLen;
     xmlDocPtr doc;
     xmlNodePtr node;
 } xsltNumberData, *xsltNumberDataPtr;
index 9149af8..08f0cee 100644 (file)
@@ -26,6 +26,7 @@
 #include <libxml/valid.h>
 #include <libxml/hash.h>
 #include <libxml/uri.h>
+#include <libxml/encoding.h>
 #include <libxml/xmlerror.h>
 #include "xslt.h"
 #include "xsltutils.h"
@@ -770,7 +771,8 @@ xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
     prop = xsltGetNsProp(cur, (const xmlChar *)"grouping-separator",
                        XSLT_NAMESPACE);
     if (prop != NULL) {
-       comp->numdata.groupingCharacter = prop[0];
+       comp->numdata.groupingCharacter =
+           xsltGetUTF8Char(prop, &(comp->numdata.groupingCharacterLen));
        xmlFree(prop);
     }
     
index 7732d39..a1914cc 100644 (file)
@@ -129,6 +129,75 @@ xsltGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace) {
     return(NULL);
 }
 
+/**
+ * xsltGetUTF8Char:
+ * @utf:  a sequence of UTF-8 encoded bytes
+ * @len:  a pointer to @bytes len
+ *
+ * Read one UTF8 Char from @utf
+ * Function copied from libxml2 xmlGetUTF8Char() ... to discard ultimately
+ * and use the original API
+ *
+ * Returns the char value or -1 in case of error and update @len with the
+ *        number of bytes used
+ */
+int
+xsltGetUTF8Char(const unsigned char *utf, int *len) {
+    unsigned int c;
+
+    if (utf == NULL)
+       goto error;
+    if (len == NULL)
+       goto error;
+    if (*len < 1)
+       goto error;
+
+    c = utf[0];
+    if (c & 0x80) {
+       if (*len < 2)
+           goto error;
+       if ((utf[1] & 0xc0) != 0x80)
+           goto error;
+       if ((c & 0xe0) == 0xe0) {
+           if (*len < 3)
+               goto error;
+           if ((utf[2] & 0xc0) != 0x80)
+               goto error;
+           if ((c & 0xf0) == 0xf0) {
+               if (*len < 4)
+                   goto error;
+               if ((c & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
+                   goto error;
+               *len = 4;
+               /* 4-byte code */
+               c = (utf[0] & 0x7) << 18;
+               c |= (utf[1] & 0x3f) << 12;
+               c |= (utf[2] & 0x3f) << 6;
+               c |= utf[3] & 0x3f;
+           } else {
+             /* 3-byte code */
+               *len = 3;
+               c = (utf[0] & 0xf) << 12;
+               c |= (utf[1] & 0x3f) << 6;
+               c |= utf[2] & 0x3f;
+           }
+       } else {
+         /* 2-byte code */
+           *len = 2;
+           c = (utf[0] & 0x1f) << 6;
+           c |= utf[1] & 0x3f;
+       }
+    } else {
+       /* 1-byte code */
+       *len = 1;
+    }
+    return(c);
+
+error:
+    *len = 0;
+    return(-1);
+}
+
 
 /************************************************************************
  *                                                                     *
index d2cebb3..25e8aaf 100644 (file)
@@ -87,9 +87,11 @@ extern "C" {
 /*
  * Our own version of namespaced atributes lookup.
  */
-xmlChar *       xsltGetNsProp                  (xmlNodePtr node,
+xmlChar *      xsltGetNsProp                   (xmlNodePtr node,
                                                 const xmlChar *name,
                                                 const xmlChar *nameSpace);
+int            xsltGetUTF8Char                 (const unsigned char *utf,
+                                                int *len);
 
 /*
  * XSLT specific error and debug reporting functions.
index 4438444..d214b88 100644 (file)
@@ -94,6 +94,7 @@ EXTRA_DIST =  \
        bug-92.xml \
        bug-93.xml \
        bug-94.xml \
+       bug-95.xml \
        character.xml \
        array.xml \
        items.xml
diff --git a/tests/docs/bug-95.xml b/tests/docs/bug-95.xml
new file mode 100644 (file)
index 0000000..91f84d4
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Kapital>
+       <Vklad><Kc>1234567890.12</Kc></Vklad>
+</Kapital>
+
index 705cc31..c92b12d 100644 (file)
@@ -98,6 +98,7 @@ EXTRA_DIST = \
     bug-93.out bug-93.xsl \
     bug-93-inc.out bug-93-inc.xsl \
     bug-94.out bug-94.xsl \
+    bug-95.out bug-95.xsl \
     character.out character.xsl \
     character2.out character2.xsl \
     itemschoose.out itemschoose.xsl \
diff --git a/tests/general/bug-95.out b/tests/general/bug-95.out
new file mode 100644 (file)
index 0000000..e1fc837
--- /dev/null
@@ -0,0 +1,4 @@
+<html>
+<title>Example xsltproc</title>
+<body>1 234 567 890,12 Kè</body>
+</html>
diff --git a/tests/general/bug-95.xsl b/tests/general/bug-95.xsl
new file mode 100644 (file)
index 0000000..a4c89e8
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="html" encoding="ISO-8859-1"/>
+
+<xsl:decimal-format name="czf"
+     decimal-separator=","
+     grouping-separator="&#160;"/>
+
+<xsl:template match="Kapital">
+<html>
+<title>Example xsltproc</title>
+<body>
+       <xsl:apply-templates select="Vklad"/>
+</body>
+</html>
+</xsl:template>        
+
+<xsl:template match="Vklad" >
+<xsl:value-of select="format-number(Kc,  '#&#160;###,00 Kè', 'czf')"/>
+</xsl:template>
+
+</xsl:stylesheet>