updated libxml2 to 2.5.10
[TestXSLT.git] / libxml2 / xmlschemastypes.c
index e19391f..53c6e15 100644 (file)
@@ -42,7 +42,7 @@
 typedef enum {
     XML_SCHEMAS_UNKNOWN = 0,
     XML_SCHEMAS_STRING,
-    XML_SCHEMAS_NMTOKEN,
+    XML_SCHEMAS_NORMSTRING,
     XML_SCHEMAS_DECIMAL,
     XML_SCHEMAS_TIME,
     XML_SCHEMAS_GDAY,
@@ -56,12 +56,37 @@ typedef enum {
     XML_SCHEMAS_FLOAT,
     XML_SCHEMAS_DOUBLE,
     XML_SCHEMAS_BOOLEAN,
+    XML_SCHEMAS_TOKEN,
+    XML_SCHEMAS_LANGUAGE,
+    XML_SCHEMAS_NMTOKEN,
+    XML_SCHEMAS_NMTOKENS,
+    XML_SCHEMAS_NAME,
+    XML_SCHEMAS_QNAME,
+    XML_SCHEMAS_NCNAME,
+    XML_SCHEMAS_ID,
+    XML_SCHEMAS_IDREF,
+    XML_SCHEMAS_IDREFS,
+    XML_SCHEMAS_ENTITY,
+    XML_SCHEMAS_ENTITIES,
+    XML_SCHEMAS_NOTATION,
+    XML_SCHEMAS_ANYURI,
+    XML_SCHEMAS_INTEGER,
+    XML_SCHEMAS_NPINTEGER,
+    XML_SCHEMAS_NINTEGER,
+    XML_SCHEMAS_NNINTEGER,
+    XML_SCHEMAS_PINTEGER,
     XML_SCHEMAS_INT,
-    XML_SCHEMAS_,
-    XML_SCHEMAS_XXX
+    XML_SCHEMAS_UINT,
+    XML_SCHEMAS_LONG,
+    XML_SCHEMAS_ULONG,
+    XML_SCHEMAS_SHORT,
+    XML_SCHEMAS_USHORT,
+    XML_SCHEMAS_BYTE,
+    XML_SCHEMAS_UBYTE,
+    XML_SCHEMAS_HEXBINARY
 } xmlSchemaValType;
 
-unsigned long powten[10] = {
+static unsigned long powten[10] = {
     1, 10, 100, 1000, 10000, 100000, 1000000, 10000000L,
     100000000L, 1000000000L
 };
@@ -76,7 +101,7 @@ struct _xmlSchemaValDate {
     unsigned int       hour    :5;     /* 0 <=  hour   <= 23   */
     unsigned int       min     :6;     /* 0 <=  min    <= 59   */
     double             sec;
-    int                        tz_flag :1;     /* is tzo explicitely set? */
+    unsigned int       tz_flag :1;     /* is tzo explicitely set? */
     int                        tzo     :11;    /* -1440 <= tzo <= 1440 */
 };
 
@@ -93,11 +118,27 @@ typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal;
 typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr;
 struct _xmlSchemaValDecimal {
     /* would use long long but not portable */
-    unsigned long base;
+    unsigned long lo;
+    unsigned long mi;
+    unsigned long hi;
     unsigned int extra;
     unsigned int sign:1;
-    int frac:7;
-    int total:8;
+    unsigned int frac:7;
+    unsigned int total:8;
+};
+
+typedef struct _xmlSchemaValQName xmlSchemaValQName;
+typedef xmlSchemaValQName *xmlSchemaValQNamePtr;
+struct _xmlSchemaValQName {
+    xmlChar *name;
+    xmlChar *uri;
+};
+
+typedef struct _xmlSchemaValHex xmlSchemaValHex;
+typedef xmlSchemaValHex *xmlSchemaValHexPtr;
+struct _xmlSchemaValHex {
+    xmlChar     *str;
+    unsigned int total;
 };
 
 struct _xmlSchemaVal {
@@ -106,9 +147,12 @@ struct _xmlSchemaVal {
        xmlSchemaValDecimal     decimal;
         xmlSchemaValDate        date;
         xmlSchemaValDuration    dur;
+       xmlSchemaValQName       qname;
+       xmlSchemaValHex         hex;
        float                   f;
        double                  d;
        int                     b;
+       xmlChar                *str;
     } value;
 };
 
@@ -131,12 +175,10 @@ static xmlSchemaTypePtr xmlSchemaTypeGDayDef = NULL;
 static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL;
 static xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL;
 static xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL;
-static xmlSchemaTypePtr xmlSchemaTypeNmtoken = NULL;
 static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL;
 static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL;
 static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL;
-static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL;
-static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL;
 static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL;
 
 /*
@@ -155,16 +197,30 @@ static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef = NULL;
 static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef = NULL;
 static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef = NULL;
 static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeNormStringDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeTokenDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeLanguageDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL;
 static xmlSchemaTypePtr xmlSchemaTypeNCNameDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeIdDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeIdrefDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeEntityDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeNotationDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL;
 
 /*
  * xmlSchemaInitBasicType:
  * @name:  the type name
+ * @type:  the value type associated
  *
  * Initialize one default type
  */
 static xmlSchemaTypePtr
-xmlSchemaInitBasicType(const char *name) {
+xmlSchemaInitBasicType(const char *name, xmlSchemaValType type) {
     xmlSchemaTypePtr ret;
 
     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
@@ -176,6 +232,7 @@ xmlSchemaInitBasicType(const char *name) {
     memset(ret, 0, sizeof(xmlSchemaType));
     ret->name = xmlStrdup((const xmlChar *)name);
     ret->type = XML_SCHEMA_TYPE_BASIC;
+    ret->flags = type;
     ret->contentType = XML_SCHEMA_CONTENT_BASIC;
     xmlHashAddEntry2(xmlSchemaTypesBank, ret->name,
                     XML_SCHEMAS_NAMESPACE_NAME, ret);
@@ -188,53 +245,110 @@ xmlSchemaInitBasicType(const char *name) {
  * Initialize the default XML Schemas type library
  */
 void
-xmlSchemaInitTypes(void) {
+xmlSchemaInitTypes(void)
+{
     if (xmlSchemaTypesInitialized != 0)
-       return;
+        return;
     xmlSchemaTypesBank = xmlHashCreate(40);
-    
+
     /*
      * primitive datatypes
      */
-    xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string");
-    xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType");
-    xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType");
-    xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal");
-    xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date");
-    xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime");
-    xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time");
-    xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear");
-    xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth");
-    xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth");
-    xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay");
-    xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay");
-    xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration");
-    xmlSchemaTypeNmtoken = xmlSchemaInitBasicType("NMTOKEN");
-    xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float");
-    xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double");
-    xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean");
-    xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name");
-    xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName");
-    xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI");
+    xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string",
+                                                    XML_SCHEMAS_STRING);
+    xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType",
+                                                     XML_SCHEMAS_UNKNOWN);
+    xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType",
+                                                           XML_SCHEMAS_UNKNOWN);
+    xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal",
+                                                     XML_SCHEMAS_DECIMAL);
+    xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date",
+                                                  XML_SCHEMAS_DATE);
+    xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime",
+                                                      XML_SCHEMAS_DATETIME);
+    xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time",
+                                                  XML_SCHEMAS_TIME);
+    xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear",
+                                                   XML_SCHEMAS_GYEAR);
+    xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth",
+                                                        XML_SCHEMAS_GYEARMONTH);
+    xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth",
+                                                    XML_SCHEMAS_GMONTH);
+    xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay",
+                                                       XML_SCHEMAS_GMONTHDAY);
+    xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay",
+                                                  XML_SCHEMAS_GDAY);
+    xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration",
+                                                      XML_SCHEMAS_DURATION);
+    xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float",
+                                                   XML_SCHEMAS_FLOAT);
+    xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double",
+                                                    XML_SCHEMAS_DOUBLE);
+    xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean",
+                                                     XML_SCHEMAS_BOOLEAN);
+    xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI",
+                                                    XML_SCHEMAS_ANYURI);
+    xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary",
+                                                     XML_SCHEMAS_HEXBINARY);
 
     /*
      * derived datatypes
      */
-    xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer");;
-    xmlSchemaTypeNonPositiveIntegerDef = xmlSchemaInitBasicType("nonPositiveInteger");;
-    xmlSchemaTypeNegativeIntegerDef = xmlSchemaInitBasicType("negativeInteger");;
-    xmlSchemaTypeLongDef = xmlSchemaInitBasicType("long");;
-    xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int");;
-    xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short");;
-    xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte");;
-    xmlSchemaTypeNonNegativeIntegerDef = xmlSchemaInitBasicType("nonNegativeInteger");
-    xmlSchemaTypeUnsignedLongDef = xmlSchemaInitBasicType("unsignedLong");;
-    xmlSchemaTypeUnsignedIntDef = xmlSchemaInitBasicType("unsignedInt");;
-    xmlSchemaTypeUnsignedShortDef = xmlSchemaInitBasicType("insignedShort");;
-    xmlSchemaTypeUnsignedByteDef = xmlSchemaInitBasicType("unsignedByte");;
-    xmlSchemaTypePositiveIntegerDef = xmlSchemaInitBasicType("positiveInteger");
-    xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName");
-
+    xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer",
+                                                     XML_SCHEMAS_INTEGER);;
+    xmlSchemaTypeNonPositiveIntegerDef =
+        xmlSchemaInitBasicType("nonPositiveInteger",
+                               XML_SCHEMAS_NPINTEGER);;
+    xmlSchemaTypeNegativeIntegerDef =
+        xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER);;
+    xmlSchemaTypeLongDef =
+        xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG);;
+    xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT);;
+    xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short",
+                                                   XML_SCHEMAS_SHORT);;
+    xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte",
+                                                  XML_SCHEMAS_BYTE);;
+    xmlSchemaTypeNonNegativeIntegerDef =
+        xmlSchemaInitBasicType("nonNegativeInteger",
+                               XML_SCHEMAS_NNINTEGER);
+    xmlSchemaTypeUnsignedLongDef =
+        xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG);;
+    xmlSchemaTypeUnsignedIntDef =
+        xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT);;
+    xmlSchemaTypeUnsignedShortDef =
+        xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT);;
+    xmlSchemaTypeUnsignedByteDef =
+        xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE);;
+    xmlSchemaTypePositiveIntegerDef =
+        xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER);
+
+    xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString",
+                                                        XML_SCHEMAS_NORMSTRING);
+    xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token",
+                                                   XML_SCHEMAS_TOKEN);
+    xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language",
+                                                      XML_SCHEMAS_LANGUAGE);
+    xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID);
+    xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF",
+                                                   XML_SCHEMAS_IDREF);
+    xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS",
+                                                    XML_SCHEMAS_IDREFS);
+    xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY",
+                                                    XML_SCHEMAS_ENTITY);
+    xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES",
+                                                      XML_SCHEMAS_ENTITIES);
+    xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION",
+                                                    XML_SCHEMAS_NOTATION);
+    xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name",
+                                                  XML_SCHEMAS_NAME);
+    xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName",
+                                                   XML_SCHEMAS_QNAME);
+    xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName",
+                                                    XML_SCHEMAS_NCNAME);
+    xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN",
+                                                     XML_SCHEMAS_NMTOKEN);
+    xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS",
+                                                      XML_SCHEMAS_NMTOKENS);
     xmlSchemaTypesInitialized = 1;
 }
 
@@ -282,6 +396,38 @@ void
 xmlSchemaFreeValue(xmlSchemaValPtr value) {
     if (value == NULL)
        return;
+    switch (value->type) {
+        case XML_SCHEMAS_STRING:
+        case XML_SCHEMAS_NORMSTRING:
+        case XML_SCHEMAS_TOKEN:
+        case XML_SCHEMAS_LANGUAGE:
+        case XML_SCHEMAS_NMTOKEN:
+        case XML_SCHEMAS_NMTOKENS:
+        case XML_SCHEMAS_NAME:
+        case XML_SCHEMAS_NCNAME:
+        case XML_SCHEMAS_ID:
+        case XML_SCHEMAS_IDREF:
+        case XML_SCHEMAS_IDREFS:
+        case XML_SCHEMAS_ENTITY:
+        case XML_SCHEMAS_ENTITIES:
+        case XML_SCHEMAS_NOTATION:
+        case XML_SCHEMAS_ANYURI:
+           if (value->value.str != NULL)
+               xmlFree(value->value.str);
+           break;
+        case XML_SCHEMAS_QNAME:
+           if (value->value.qname.uri != NULL)
+               xmlFree(value->value.qname.uri);
+           if (value->value.qname.name != NULL)
+               xmlFree(value->value.qname.name);
+           break;
+        case XML_SCHEMAS_HEXBINARY:
+           if (value->value.hex.str != NULL)
+               xmlFree(value->value.hex.str);
+           break;
+       default:
+           break;
+    }
     xmlFree(value);
 }
 
@@ -707,7 +853,7 @@ _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) {
 
 /**
  * xmlSchemaValidateDates:
- * @type: the predefined type
+ * @type: the expected type or XML_SCHEMAS_UNKNOWN
  * @dateTime:  string to analyze
  * @val:  the return computed value
  *
@@ -718,7 +864,7 @@ _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) {
  *         and -1 in case of internal or API error.
  */
 static int
-xmlSchemaValidateDates (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
+xmlSchemaValidateDates (xmlSchemaValType type,
                        const xmlChar *dateTime, xmlSchemaValPtr *val) {
     xmlSchemaValPtr dt;
     int ret;
@@ -731,9 +877,7 @@ xmlSchemaValidateDates (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
            if (*cur != 0)                                      \
                goto error;                                     \
            dt->type = t;                                       \
-            if (val != NULL)                                    \
-                *val = dt;                                      \
-           return 0;                                           \
+           goto done;                                          \
        }                                                       \
     }
 
@@ -756,6 +900,8 @@ xmlSchemaValidateDates (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
 
        /* is it an xs:gDay? */
        if (*cur == '-') {
+           if (type == XML_SCHEMAS_GMONTH)
+               goto error;
          ++cur;
            ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
            if (ret != 0)
@@ -773,23 +919,42 @@ xmlSchemaValidateDates (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
        if (ret != 0)
            goto error;
 
-       if (*cur != '-')
-           goto error;
-       cur++;
+        /*
+         * a '-' char could indicate this type is xs:gMonthDay or
+         * a negative time zone offset. Check for xs:gMonthDay first.
+         * Also the first three char's of a negative tzo (-MM:SS) can
+         * appear to be a valid day; so even if the day portion
+         * of the xs:gMonthDay verifies, we must insure it was not
+         * a tzo.
+         */
+        if (*cur == '-') {
+            const xmlChar *rewnd = cur;
+            cur++;
+
+           ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
+            if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) {
+
+                /*
+                 * we can use the VALID_MDAY macro to validate the month
+                 * and day because the leap year test will flag year zero
+                 * as a leap year (even though zero is an invalid year).
+                 */
+                if (VALID_MDAY((&(dt->value.date)))) {
+
+                   RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
 
-       /* is it an xs:gMonth? */
-       if (*cur == '-') {
-           cur++;
-           RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
-           goto error;
-       }
+                    goto error;
+                }
+            }
 
-       /* it should be an xs:gMonthDay */
-       ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
-       if (ret != 0)
-           goto error;
+            /*
+             * not xs:gMonthDay so rewind and check if just xs:gMonth
+             * with an optional time zone.
+             */
+            cur = rewnd;
+        }
 
-       RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
+       RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
 
        goto error;
     }
@@ -851,10 +1016,47 @@ xmlSchemaValidateDates (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
     if ((ret != 0) || (*cur != 0) || !VALID_DATETIME((&(dt->value.date))))
        goto error;
 
+
     dt->type = XML_SCHEMAS_DATETIME;
 
+done:
+#if 1
+    if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type))
+        goto error;
+#else
+    /*
+     * insure the parsed type is equal to or less significant (right
+     * truncated) than the desired type.
+     */
+    if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) {
+
+        /* time only matches time */
+        if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME))
+            goto error;
+
+        if ((type == XML_SCHEMAS_DATETIME) &&
+            ((dt->type != XML_SCHEMAS_DATE) ||
+             (dt->type != XML_SCHEMAS_GYEARMONTH) ||
+             (dt->type != XML_SCHEMAS_GYEAR)))
+            goto error;
+
+        if ((type == XML_SCHEMAS_DATE) &&
+            ((dt->type != XML_SCHEMAS_GYEAR) ||
+             (dt->type != XML_SCHEMAS_GYEARMONTH)))
+            goto error;
+
+        if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR))
+            goto error;
+
+        if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH))
+            goto error;
+    }
+#endif
+
     if (val != NULL)
         *val = dt;
+    else
+       xmlSchemaFreeValue(dt);
 
     return 0;
 
@@ -883,6 +1085,10 @@ xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
     xmlSchemaValPtr dur;
     int isneg = 0;
     unsigned int seq = 0;
+    double         num;
+    int            num_type = 0;  /* -1 = invalid, 0 = int, 1 = floating */
+    const xmlChar  desig[]  = {'Y', 'M', 'D', 'H', 'M', 'S'};
+    const double   multi[]  = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
 
     if (duration == NULL)
        return -1;
@@ -896,15 +1102,14 @@ xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
     if (*cur++ != 'P')
        return 1;
 
+    if (*cur == 0)
+       return 1;
+
     dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
     if (dur == NULL)
        return -1;
 
     while (*cur != 0) {
-        double         num;
-        int            num_type = 0;  /* -1 = invalid, 0 = int, 1 = floating */
-        const xmlChar  desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
-        const double   multi[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
 
         /* input string should be empty or invalid date/time item */
         if (seq >= sizeof(desig))
@@ -965,6 +1170,8 @@ xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
 
     if (val != NULL)
         *val = dur;
+    else
+       xmlSchemaFreeValue(dur);
 
     return 0;
 
@@ -974,24 +1181,221 @@ error:
     return 1;
 }
 
+/**
+ * xmlSchemaStrip:
+ * @value: a value
+ *
+ * Removes the leading and ending spaces of a string
+ *
+ * Returns the new string or NULL if no change was required.
+ */
+static xmlChar *
+xmlSchemaStrip(const xmlChar *value) {
+    const xmlChar *start = value, *end, *f;
+
+    if (value == NULL) return(NULL);
+    while ((*start != 0) && (IS_BLANK(*start))) start++;
+    end = start;
+    while (*end != 0) end++;
+    f = end;
+    end--;
+    while ((end > start) && (IS_BLANK(*end))) end--;
+    end++;
+    if ((start == value) && (f == end)) return(NULL);
+    return(xmlStrndup(start, end - start));
+}
 
 /**
- * xmlSchemaValidatePredefinedType:
+ * xmlSchemaCollapseString:
+ * @value: a value
+ *
+ * Removes and normalize white spaces in the string
+ *
+ * Returns the new string or NULL if no change was required.
+ */
+static xmlChar *
+xmlSchemaCollapseString(const xmlChar *value) {
+    const xmlChar *start = value, *end, *f;
+    xmlChar *g;
+    int col = 0;
+
+    if (value == NULL) return(NULL);
+    while ((*start != 0) && (IS_BLANK(*start))) start++;
+    end = start;
+    while (*end != 0) {
+       if ((*end == ' ') && (IS_BLANK(end[1]))) {
+           col = end - start;
+           break;
+       } else if ((*end == 0xa) || (*end == 0x9) || (*end == 0xd)) {
+           col = end - start;
+           break;
+       }
+       end++;
+    }
+    if (col == 0) {
+       f = end;
+       end--;
+       while ((end > start) && (IS_BLANK(*end))) end--;
+       end++;
+       if ((start == value) && (f == end)) return(NULL);
+       return(xmlStrndup(start, end - start));
+    }
+    start = xmlStrdup(start);
+    if (start == NULL) return(NULL);
+    g = (xmlChar *) (start + col);
+    end = g;
+    while (*end != 0) {
+       if (IS_BLANK(*end)) {
+           end++;
+           while (IS_BLANK(*end)) end++;
+           if (*end != 0)
+               *g++ = ' ';
+       } else
+           *g++ = *end++;
+    }
+    *g = 0;
+    return((xmlChar *) start);
+}
+
+/**
+ * xmlSchemaValAtomicListNode:
+ * @type: the predefined atomic type for a token in the list
+ * @value: the list value to check
+ * @ret:  the return computed value
+ * @node:  the node containing the value
+ *
+ * Check that a value conforms to the lexical space of the predefined
+ * list type. if true a value is computed and returned in @ret.
+ *
+ * Returns the number of items if this validates, a negative error code
+ *         number otherwise
+ */
+static int
+xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value,
+                          xmlSchemaValPtr *ret, xmlNodePtr node) {
+    xmlChar *val, *cur, *endval;
+    int nb_values = 0;
+    int tmp = 0;
+
+    if (value == NULL) {
+       return(-1);
+    }
+    val = xmlStrdup(value);
+    if (val == NULL) {
+       return(-1);
+    }
+    cur = val;
+    /*
+     * Split the list
+     */
+    while (IS_BLANK(*cur)) *cur++ = 0;
+    while (*cur != 0) {
+       if (IS_BLANK(*cur)) {
+           *cur = 0;
+           cur++;
+           while (IS_BLANK(*cur)) *cur++ = 0;
+       } else {
+           nb_values++;
+           cur++;
+           while ((*cur != 0) && (!IS_BLANK(*cur))) cur++;
+       }
+    }
+    if (nb_values == 0) {
+       if (ret != NULL) {
+           TODO
+       }
+       xmlFree(val);
+       return(nb_values);
+    }
+    endval = cur;
+    cur = val;
+    while ((*cur == 0) && (cur != endval)) cur++;
+    while (cur != endval) {
+       tmp = xmlSchemaValPredefTypeNode(type, cur, NULL, node);
+       if (tmp != 0)
+           break;
+       while (*cur != 0) cur++;
+       while ((*cur == 0) && (cur != endval)) cur++;
+    }
+    xmlFree(val);
+    if (ret != NULL) {
+       TODO
+    }
+    if (tmp == 0)
+       return(nb_values);
+    return(-1);
+}
+
+/**
+ * xmlSchemaParseUInt:
+ * @str: pointer to the string R/W
+ * @llo: pointer to the low result
+ * @lmi: pointer to the mid result
+ * @lhi: pointer to the high result
+ *
+ * Parse an unsigned long into 3 fields.
+ *
+ * Returns the number of chars parsed or -1 if overflow of the capacity
+ */
+static int
+xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo,
+                  unsigned long *lmi, unsigned long *lhi) {
+    unsigned long lo = 0, mi = 0, hi = 0;
+    const xmlChar *tmp, *cur = *str;
+    int ret = 0, i = 0;
+
+    while (*cur == '0') {
+       ret++;
+       cur++;
+    }
+    tmp = cur;
+    while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) {
+       i++;tmp++;ret++;
+    }
+    if (i > 24) {
+       *str = tmp;
+       return(-1);
+    }
+    while (i > 16) {
+       hi = hi * 10 + (*cur++ - '0');
+       i--;
+    }
+    while (i > 8) {
+       mi = mi * 10 + (*cur++ - '0');
+       i--;
+    }
+    while (i > 0) {
+       lo = lo * 10 + (*cur++ - '0');
+       i--;
+    }
+
+    *str = cur;
+    *llo = lo;
+    *lmi = mi;
+    *lhi = hi;
+    return(ret);
+}
+
+/**
+ * xmlSchemaValAtomicType:
  * @type: the predefined type
  * @value: the value to check
  * @val:  the return computed value
+ * @node:  the node containing the value
+ * flags:  flags to control the vlidation
  *
- * Check that a value conforms to the lexical space of the predefined type.
+ * Check that a value conforms to the lexical space of the atomic type.
  * if true a value is computed and returned in @val.
  *
  * Returns 0 if this validates, a positive error code number otherwise
  *         and -1 in case of internal or API error.
  */
-int
-xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
-                               xmlSchemaValPtr *val) {
+static int
+xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
+                      xmlSchemaValPtr *val, xmlNodePtr node, int flags) {
     xmlSchemaValPtr v;
-    int ret;
+    xmlChar *norm = NULL;
+    int ret = 0;
 
     if (xmlSchemaTypesInitialized == 0)
        return(-1);
@@ -1000,344 +1404,823 @@ xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
 
     if (val != NULL)
        *val = NULL;
-    if (type == xmlSchemaTypeStringDef) { 
-       return(0);
-    } else if (type == xmlSchemaTypeAnyTypeDef) {
-       return(0);
-    } else if (type == xmlSchemaTypeAnySimpleTypeDef) {
-       return(0);
-    } else if (type == xmlSchemaTypeNmtoken) {
-       if (xmlValidateNmtokenValue(value))
-           return(0);
-       return(1);
-    } else if (type == xmlSchemaTypeDecimalDef) {
-       const xmlChar *cur = value, *tmp;
-       int frac = 0, len, neg = 0;
-       unsigned long base = 0;
-       if (cur == NULL)
-           return(1);
-       if (*cur == '+')
-           cur++;
-       else if (*cur == '-') {
-           neg = 1;
-           cur++;
+    if ((flags == 0) && (value != NULL)) {
+       if ((type->flags != XML_SCHEMAS_STRING) &&
+           (type->flags != XML_SCHEMAS_NORMSTRING)) {
+           norm = xmlSchemaCollapseString(value);
+           if (norm != NULL)
+               value = norm;
        }
-       tmp = cur;
-       while ((*cur >= '0') && (*cur <= '9')) {
-           base = base * 10 + (*cur - '0');
-           cur++;
-       }
-       len = cur - tmp;
-       if (*cur == '.') {
-           cur++;
+    }
+
+    switch (type->flags) {
+        case XML_SCHEMAS_UNKNOWN:
+           if (type == xmlSchemaTypeAnyTypeDef)
+               goto return0;
+           goto error;
+        case XML_SCHEMAS_STRING:
+           goto return0;
+        case XML_SCHEMAS_NORMSTRING:
+           TODO
+           goto return0;
+        case XML_SCHEMAS_DECIMAL: {
+           const xmlChar *cur = value, *tmp;
+           unsigned int frac = 0, len, neg = 0;
+           unsigned long base = 0;
+           if (cur == NULL)
+               goto return1;
+           if (*cur == '+')
+               cur++;
+           else if (*cur == '-') {
+               neg = 1;
+               cur++;
+           }
            tmp = cur;
            while ((*cur >= '0') && (*cur <= '9')) {
                base = base * 10 + (*cur - '0');
                cur++;
            }
-           frac = cur - tmp;
-       }
-       if (*cur != 0)
-           return(1);
-       if (val != NULL) {
-           v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
-           if (v != NULL) {
-               v->value.decimal.base = base;
-               v->value.decimal.sign = neg;
-               v->value.decimal.frac = frac;
-               v->value.decimal.total = frac + len;
-               *val = v;
+           len = cur - tmp;
+           if (*cur == '.') {
+               cur++;
+               tmp = cur;
+               while ((*cur >= '0') && (*cur <= '9')) {
+                   base = base * 10 + (*cur - '0');
+                   cur++;
+               }
+               frac = cur - tmp;
            }
-       }
-       return(0);
-    } else if (type == xmlSchemaTypeDurationDef) {
-        return xmlSchemaValidateDuration(type, value, val);
-    } else if ((type == xmlSchemaTypeDatetimeDef) ||
-               (type == xmlSchemaTypeTimeDef) ||
-               (type == xmlSchemaTypeDateDef) ||
-               (type == xmlSchemaTypeGYearDef) ||
-               (type == xmlSchemaTypeGYearMonthDef) ||
-               (type == xmlSchemaTypeGMonthDef) ||
-               (type == xmlSchemaTypeGMonthDayDef) ||
-               (type == xmlSchemaTypeGDayDef))         {
-        return xmlSchemaValidateDates(type, value, val);
-    } else if (type == xmlSchemaTypePositiveIntegerDef) {
-       const xmlChar *cur = value;
-       unsigned long base = 0;
-       int total = 0;
-       if (cur == NULL)
-           return(1);
-       if (*cur == '+')
-           cur++;
-       while ((*cur >= '0') && (*cur <= '9')) {
-           base = base * 10 + (*cur - '0');
-           total++;
-           cur++;
-       }
-       if (*cur != 0)
-           return(1);
-       if (val != NULL) {
-           v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
-           if (v != NULL) {
-               v->value.decimal.base = base;
-               v->value.decimal.sign = 0;
-               v->value.decimal.frac = 0;
-               v->value.decimal.total = total;
-               *val = v;
+           if (*cur != 0)
+               goto return1;
+           if (val != NULL) {
+               v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
+               if (v != NULL) {
+                   v->value.decimal.lo = base;
+                   v->value.decimal.sign = neg;
+                   v->value.decimal.frac = frac;
+                   v->value.decimal.total = frac + len;
+                   *val = v;
+               }
            }
+           goto return0;
        }
-       return(0);
-    } else if (type == xmlSchemaTypeNonNegativeIntegerDef) {
-       const xmlChar *cur = value;
-       unsigned long base = 0;
-       int total = 0;
-       int sign = 0;
-       if (cur == NULL)
-           return(1);
-       if (*cur == '-') {
-           sign = 1;
-           cur++;
-       } else if (*cur == '+')
-           cur++;
-       while ((*cur >= '0') && (*cur <= '9')) {
-           base = base * 10 + (*cur - '0');
-           total++;
-           cur++;
-       }
-       if (*cur != 0)
-           return(1);
-       if ((sign == 1) && (base != 0))
-           return(1);
-       if (val != NULL) {
-           v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
-           if (v != NULL) {
-               v->value.decimal.base = base;
-               v->value.decimal.sign = 0;
-               v->value.decimal.frac = 0;
-               v->value.decimal.total = total;
-               *val = v;
+        case XML_SCHEMAS_TIME:
+        case XML_SCHEMAS_GDAY:
+        case XML_SCHEMAS_GMONTH:
+        case XML_SCHEMAS_GMONTHDAY:
+        case XML_SCHEMAS_GYEAR:
+        case XML_SCHEMAS_GYEARMONTH:
+        case XML_SCHEMAS_DATE:
+        case XML_SCHEMAS_DATETIME:
+           ret = xmlSchemaValidateDates(type->flags, value, val);
+           break;
+        case XML_SCHEMAS_DURATION:
+           ret = xmlSchemaValidateDuration(type, value, val);
+           break;
+        case XML_SCHEMAS_FLOAT:
+        case XML_SCHEMAS_DOUBLE: {
+           const xmlChar *cur = value;
+           int neg = 0;
+           if (cur == NULL)
+               goto return1;
+           if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
+               cur += 3;
+               if (*cur != 0)
+                   goto return1;
+               if (val != NULL) {
+                   if (type == xmlSchemaTypeFloatDef) {
+                       v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
+                       if (v != NULL) {
+                           v->value.f = (float) xmlXPathNAN;
+                       } else {
+                           xmlSchemaFreeValue(v);
+                           goto error;
+                       }
+                   } else {
+                       v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
+                       if (v != NULL) {
+                           v->value.d = xmlXPathNAN;
+                       } else {
+                           xmlSchemaFreeValue(v);
+                           goto error;
+                       }
+                   }
+                   *val = v;
+               }
+               goto return0;
            }
-       }
-       return(0);
-    } else if (type == xmlSchemaTypeIntDef) {
-       const xmlChar *cur = value;
-       unsigned long base = 0;
-       int total = 0;
-       int sign = 0;
-       if (cur == NULL)
-           return(1);
-       if (*cur == '-') {
-           sign = 1;
-           cur++;
-       } else if (*cur == '+')
-           cur++;
-       while (*cur == '0') {
-           total++;
-           cur++;
-       }
-       while ((*cur >= '0') && (*cur <= '9')) {
-           base = base * 10 + (*cur - '0');
-           total++;
-           cur++;
-       }
-       if (*cur != 0)
-           return(1);
-       if ((sign == 1) && (total == 0))
-           return(1);
-       if (val != NULL) {
-           v = xmlSchemaNewValue(XML_SCHEMAS_INT);
-           if (v != NULL) {
-               v->value.decimal.base = base;
-               v->value.decimal.sign = sign;
-               v->value.decimal.frac = 0;
-               v->value.decimal.total = total;
-               *val = v;
+           if (*cur == '-') {
+               neg = 1;
+               cur++;
+           }
+           if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) {
+               cur += 3;
+               if (*cur != 0)
+                   goto return1;
+               if (val != NULL) {
+                   if (type == xmlSchemaTypeFloatDef) {
+                       v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
+                       if (v != NULL) {
+                           if (neg)
+                               v->value.f = (float) xmlXPathNINF;
+                           else
+                               v->value.f = (float) xmlXPathPINF;
+                       } else {
+                           xmlSchemaFreeValue(v);
+                           goto error;
+                       }
+                   } else {
+                       v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
+                       if (v != NULL) {
+                           if (neg)
+                               v->value.d = xmlXPathNINF;
+                           else
+                               v->value.d = xmlXPathPINF;
+                       } else {
+                           xmlSchemaFreeValue(v);
+                           goto error;
+                       }
+                   }
+                   *val = v;
+               }
+               goto return0;
+           }
+           if ((neg == 0) && (*cur == '+'))
+               cur++;
+           if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-'))
+               goto return1;
+           while ((*cur >= '0') && (*cur <= '9')) {
+               cur++;
+           }
+           if (*cur == '.') {
+               cur++;
+               while ((*cur >= '0') && (*cur <= '9')) 
+                   cur++;
+           }
+           if ((*cur == 'e') || (*cur == 'E')) {
+               cur++;
+               if ((*cur == '-') || (*cur == '+'))
+                   cur++;
+               while ((*cur >= '0') && (*cur <= '9')) 
+                   cur++;
            }
-       }
-       return(0);
-    } else if ((type == xmlSchemaTypeFloatDef) ||
-              (type == xmlSchemaTypeDoubleDef)) {
-       const xmlChar *cur = value;
-       int neg = 0;
-       if (cur == NULL)
-           return(1);
-       if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
-           cur += 3;
            if (*cur != 0)
-               return(1);
+               goto return1;
            if (val != NULL) {
                if (type == xmlSchemaTypeFloatDef) {
                    v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
                    if (v != NULL) {
-                       v->value.f = (float) xmlXPathNAN;
+                       if (sscanf((const char *)value, "%f", &(v->value.f))==1) {
+                           *val = v;
+                       } else {
+                           xmlGenericError(xmlGenericErrorContext,
+                                   "failed to scanf float %s\n", value);
+                           xmlSchemaFreeValue(v);
+                           goto return1;
+                       }
                    } else {
-                       xmlSchemaFreeValue(v);
-                       return(-1);
+                       goto error;
                    }
                } else {
                    v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
                    if (v != NULL) {
-                       v->value.d = xmlXPathNAN;
+                       if (sscanf((const char *)value, "%lf", &(v->value.d))==1) {
+                           *val = v;
+                       } else {
+                           xmlGenericError(xmlGenericErrorContext,
+                                   "failed to scanf double %s\n", value);
+                           xmlSchemaFreeValue(v);
+                           goto return1;
+                       }
                    } else {
-                       xmlSchemaFreeValue(v);
-                       return(-1);
+                       goto error;
                    }
                }
-               *val = v;
            }
-           return(0);
+           goto return0;
        }
-       if (*cur == '+')
-           cur++;
-       else if (*cur == '-') {
-           neg = 1;
-           cur++;
+        case XML_SCHEMAS_BOOLEAN: {
+           const xmlChar *cur = value;
+
+           if ((cur[0] == '0') && (cur[1] == 0))
+               ret = 0;
+           else if ((cur[0] == '1') && (cur[1] == 0))
+               ret = 1;
+           else if ((cur[0] == 't') && (cur[1] == 'r') && (cur[2] == 'u') &&
+                    (cur[3] == 'e') && (cur[4] == 0))
+               ret = 1;
+           else if ((cur[0] == 'f') && (cur[1] == 'a') && (cur[2] == 'l') &&
+                    (cur[3] == 's') && (cur[4] == 'e') && (cur[5] == 0))
+               ret = 0;
+           else 
+               goto return1;
+           if (val != NULL) {
+               v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN);
+               if (v != NULL) {
+                   v->value.b = ret;
+                   *val = v;
+               } else {
+                   goto error;
+               }
+           }
+           goto return0;
        }
-       if (cur[0] == 0)
-           return(1);
-       if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) {
-           cur += 3;
-           if (*cur != 0)
-               return(1);
+        case XML_SCHEMAS_TOKEN: {
+           const xmlChar *cur = value;
+
+           if (IS_BLANK(*cur))
+               goto return1;
+
+           while (*cur != 0) {
+               if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
+                   goto return1;
+               } else if (*cur == ' ') {
+                   cur++;
+                   if (*cur == 0)
+                       goto return1;
+                   if (*cur == ' ')
+                       goto return1;
+               } else {
+                   cur++;
+               }
+           }
            if (val != NULL) {
-               if (type == xmlSchemaTypeFloatDef) {
-                   v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
+               v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN);
+               if (v != NULL) {
+                   v->value.str = xmlStrdup(value);
+                   *val = v;
+               } else {
+                   goto error;
+               }
+           }
+           goto return0;
+       }
+        case XML_SCHEMAS_LANGUAGE:
+           if (xmlCheckLanguageID(value) == 1) {
+               if (val != NULL) {
+                   v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE);
                    if (v != NULL) {
-                       if (neg)
-                           v->value.f = (float) xmlXPathNINF;
-                       else
-                           v->value.f = (float) xmlXPathPINF;
+                       v->value.str = xmlStrdup(value);
+                       *val = v;
                    } else {
-                       xmlSchemaFreeValue(v);
-                       return(-1);
+                       goto error;
                    }
-               } else {
-                   v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
+               }
+               goto return0;
+           }
+           goto return1;
+        case XML_SCHEMAS_NMTOKEN:
+           if (xmlValidateNMToken(value, 1) == 0) {
+               if (val != NULL) {
+                   v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN);
                    if (v != NULL) {
-                       if (neg)
-                           v->value.d = xmlXPathNINF;
-                       else
-                           v->value.d = xmlXPathPINF;
+                       v->value.str = xmlStrdup(value);
+                       *val = v;
                    } else {
-                       xmlSchemaFreeValue(v);
-                       return(-1);
+                       goto error;
                    }
                }
-               *val = v;
+               goto return0;
            }
-           return(0);
-       }
-       while ((*cur >= '0') && (*cur <= '9')) {
-           cur++;
-       }
-       if (*cur == '.') {
-           cur++;
-           while ((*cur >= '0') && (*cur <= '9')) 
-               cur++;
-       }
-       if ((*cur == 'e') || (*cur == 'E')) {
-           cur++;
-           if (*cur == '-')
-               cur++;
-           while ((*cur >= '0') && (*cur <= '9')) 
-               cur++;
+           goto return1;
+        case XML_SCHEMAS_NMTOKENS:
+           ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef,
+                                            value, val, node);
+           if (ret > 0)
+               ret = 0;
+           else
+               ret = 1;
+           goto done;
+        case XML_SCHEMAS_NAME:
+           ret = xmlValidateName(value, 1);
+           if ((ret == 0) && (val != NULL)) {
+               TODO;
+           }
+           goto done;
+        case XML_SCHEMAS_QNAME: {
+           xmlChar *uri = NULL;
+           xmlChar *local = NULL;
+
+           ret = xmlValidateQName(value, 1);
+           if ((ret == 0) && (node != NULL)) {
+               xmlChar *prefix;
+               local = xmlSplitQName2(value, &prefix);
+               if (prefix != NULL) {
+                   xmlNsPtr ns;
+
+                   ns = xmlSearchNs(node->doc, node, prefix);
+                   if (ns == NULL)
+                       ret = 1;
+                   else if (val != NULL)
+                       uri = xmlStrdup(ns->href);
+               }
+               if ((local != NULL) && ((val == NULL) || (ret != 0)))
+                   xmlFree(local);
+               if (prefix != NULL)
+                   xmlFree(prefix);
+           }
+           if ((ret == 0) && (val != NULL)) {
+               v = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
+               if (v != NULL) {
+                   if (local != NULL)
+                       v->value.qname.name = local;
+                   else
+                       v->value.qname.name = xmlStrdup(value);
+                   if (uri != NULL)
+                       v->value.qname.uri = uri;
+                   
+                   *val = v;
+               } else {
+                   if (local != NULL)
+                       xmlFree(local);
+                   if (uri != NULL)
+                       xmlFree(uri);
+                   goto error;
+               }
+           }
+           goto done;
        }
-       if (*cur != 0)
-           return(1);
-       if (val != NULL) {
-           if (type == xmlSchemaTypeFloatDef) {
-               v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
+        case XML_SCHEMAS_NCNAME:
+           ret = xmlValidateNCName(value, 1);
+           if ((ret == 0) && (val != NULL)) {
+               v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME);
                if (v != NULL) {
-                   if (sscanf((const char *)value, "%f", &(v->value.f))==1) {
-                       *val = v;
-                   } else {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "failed to scanf float %s\n", value);
-                       xmlSchemaFreeValue(v);
-                       return(1);
-                   }
+                   v->value.str = xmlStrdup(value);
+                   *val = v;
                } else {
-                   return(-1);
+                   goto error;
                }
-           } else {
-               v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
+           }
+           goto done;
+        case XML_SCHEMAS_ID:
+           ret = xmlValidateNCName(value, 1);
+           if ((ret == 0) && (val != NULL)) {
+               v = xmlSchemaNewValue(XML_SCHEMAS_ID);
                if (v != NULL) {
-                   if (sscanf((const char *)value, "%lf", &(v->value.d))==1) {
-                       *val = v;
+                   v->value.str = xmlStrdup(value);
+                   *val = v;
+               } else {
+                   goto error;
+               }
+           }
+           if ((ret == 0) && (node != NULL) &&
+               (node->type == XML_ATTRIBUTE_NODE)) {
+               xmlAttrPtr attr = (xmlAttrPtr) node;
+               /*
+                * NOTE: the IDness might have already be declared in the DTD
+                */
+               if (attr->atype != XML_ATTRIBUTE_ID) {
+                   xmlIDPtr res;
+                   xmlChar *strip;
+
+                   strip = xmlSchemaStrip(value);
+                   if (strip != NULL) {
+                       res = xmlAddID(NULL, node->doc, strip, attr);
+                       xmlFree(strip);
+                   } else
+                       res = xmlAddID(NULL, node->doc, value, attr);
+                   if (res == NULL) {
+                       ret = 2;
                    } else {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "failed to scanf double %s\n", value);
-                       xmlSchemaFreeValue(v);
-                       return(1);
+                       attr->atype = XML_ATTRIBUTE_ID;
                    }
+               }
+           }
+           goto done;
+        case XML_SCHEMAS_IDREF:
+           ret = xmlValidateNCName(value, 1);
+           if ((ret == 0) && (val != NULL)) {
+               TODO;
+           }
+           if ((ret == 0) && (node != NULL) &&
+               (node->type == XML_ATTRIBUTE_NODE)) {
+               xmlAttrPtr attr = (xmlAttrPtr) node;
+               xmlChar *strip;
+
+               strip = xmlSchemaStrip(value);
+               if (strip != NULL) {
+                   xmlAddRef(NULL, node->doc, strip, attr);
+                   xmlFree(strip);
+               } else
+                   xmlAddRef(NULL, node->doc, value, attr);
+               attr->atype = XML_ATTRIBUTE_IDREF;
+           }
+           goto done;
+        case XML_SCHEMAS_IDREFS:
+           ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef,
+                                            value, val, node);
+           if (ret < 0)
+               ret = 2;
+           else
+               ret = 0;
+           if ((ret == 0) && (node != NULL) &&
+               (node->type == XML_ATTRIBUTE_NODE)) {
+               xmlAttrPtr attr = (xmlAttrPtr) node;
+
+               attr->atype = XML_ATTRIBUTE_IDREFS;
+           }
+           goto done;
+        case XML_SCHEMAS_ENTITY: {
+           xmlChar *strip;
+           ret = xmlValidateNCName(value, 1);
+           if ((node == NULL) || (node->doc == NULL))
+               ret = 3;
+           if (ret == 0) {
+               xmlEntityPtr ent;
+
+               strip = xmlSchemaStrip(value);
+               if (strip != NULL) {
+                   ent = xmlGetDocEntity(node->doc, strip);
+                   xmlFree(strip);
                } else {
-                   return(-1);
+                   ent = xmlGetDocEntity(node->doc, value);
                }
+               if ((ent == NULL) ||
+                   (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY))
+                   ret = 4;
            }
+           if ((ret == 0) && (val != NULL)) {
+               TODO;
+           }
+           if ((ret == 0) && (node != NULL) &&
+               (node->type == XML_ATTRIBUTE_NODE)) {
+               xmlAttrPtr attr = (xmlAttrPtr) node;
+
+               attr->atype = XML_ATTRIBUTE_ENTITY;
+           }
+           goto done;
        }
-       return(0);
-    } else if (type == xmlSchemaTypeNameDef) {
-       ret = xmlValidateName(value, 1);
-       if ((ret == 0) && (val != NULL)) {
-           TODO;
-       }
-       return(ret);
-    } else if (type == xmlSchemaTypeQNameDef) {
-       ret = xmlValidateQName(value, 1);
-       if ((ret == 0) && (val != NULL)) {
-           TODO;
-       }
-       return(ret);
-    } else if (type == xmlSchemaTypeNCNameDef) {
-       ret = xmlValidateNCName(value, 1);
-       if ((ret == 0) && (val != NULL)) {
-           TODO;
+        case XML_SCHEMAS_ENTITIES:
+           if ((node == NULL) || (node->doc == NULL))
+               goto return3;
+           ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef,
+                                            value, val, node);
+           if (ret <= 0)
+               ret = 1;
+           else
+               ret = 0;
+           if ((ret == 0) && (node != NULL) &&
+               (node->type == XML_ATTRIBUTE_NODE)) {
+               xmlAttrPtr attr = (xmlAttrPtr) node;
+
+               attr->atype = XML_ATTRIBUTE_ENTITIES;
+           }
+           goto done;
+        case XML_SCHEMAS_NOTATION: {
+           xmlChar *uri = NULL;
+           xmlChar *local = NULL;
+
+           ret = xmlValidateQName(value, 1);
+           if ((ret == 0) && (node != NULL)) {
+               xmlChar *prefix;
+               local = xmlSplitQName2(value, &prefix);
+               if (prefix != NULL) {
+                   xmlNsPtr ns;
+
+                   ns = xmlSearchNs(node->doc, node, prefix);
+                   if (ns == NULL)
+                       ret = 1;
+                   else if (val != NULL)
+                       uri = xmlStrdup(ns->href);
+               }
+               if ((local != NULL) && ((val == NULL) || (ret != 0)))
+                   xmlFree(local);
+               if (prefix != NULL)
+                   xmlFree(prefix);
+           }
+           if ((node == NULL) || (node->doc == NULL))
+               ret = 3;
+           if (ret == 0) {
+               ret = xmlValidateNotationUse(NULL, node->doc, value);
+               if (ret == 1)
+                   ret = 0;
+               else
+                   ret = 1;
+           }
+           if ((ret == 0) && (val != NULL)) {
+               v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
+               if (v != NULL) {
+                   if (local != NULL)
+                       v->value.qname.name = local;
+                   else
+                       v->value.qname.name = xmlStrdup(value);
+                   if (uri != NULL)
+                       v->value.qname.uri = uri;
+                   
+                   *val = v;
+               } else {
+                   if (local != NULL)
+                       xmlFree(local);
+                   if (uri != NULL)
+                       xmlFree(uri);
+                   goto error;
+               }
+           }
+           goto done;
        }
-       return(ret);
-    } else if (type == xmlSchemaTypeAnyURIDef) {
-       xmlURIPtr uri;
+        case XML_SCHEMAS_ANYURI: {
+           xmlURIPtr uri;
 
-       uri = xmlParseURI((const char *) value);
-       if (uri == NULL)
-           return(1);
-       if (val != NULL) {
-           TODO;
+           uri = xmlParseURI((const char *) value);
+           if (uri == NULL)
+               goto return1;
+           if (val != NULL) {
+               TODO;
+           }
+           xmlFreeURI(uri);
+           goto return0;
        }
-       xmlFreeURI(uri);
-       return(0);
-    } else if (type == xmlSchemaTypeBooleanDef) {
-       const xmlChar *cur = value;
-
-       if ((cur[0] == '0') && (cur[1] == 0))
-           ret = 0;
-       else if ((cur[0] == '1') && (cur[1] == 0))
-           ret = 1;
-       else if ((cur[0] == 't') && (cur[1] == 'r') && (cur[2] == 'u') &&
-                (cur[3] == 'e') && (cur[4] == 0))
-           ret = 1;
-       else if ((cur[0] == 'f') && (cur[1] == 'a') && (cur[2] == 'l') &&
-                (cur[3] == 's') && (cur[4] == 'e') && (cur[5] == 0))
-           ret = 0;
-       else 
-           return(1);
-       if (val != NULL) {
-           v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN);
-           if (v != NULL) {
-               v->value.b = ret;
+        case XML_SCHEMAS_HEXBINARY: {
+           const xmlChar *cur = value;
+           xmlChar *base;
+            int total, i = 0;
+
+            if (cur == NULL)
+                goto return1;
+
+            while (((*cur >= '0') && (*cur <= '9')) ||
+                   ((*cur >= 'A') && (*cur <= 'F')) ||
+                   ((*cur >= 'a') && (*cur <= 'f'))) {
+               i++;cur++;
+            }
+
+           if (*cur != 0)
+               goto return1;
+            if ((i % 2) != 0)
+               goto return1;
+
+           if (val != NULL) {
+
+               v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY);
+               if (v == NULL)
+                   goto error;
+
+               cur = xmlStrdup(value);
+                   if (cur == NULL) {
+                   xmlFree(v);
+                    goto return1;
+               }
+
+               total = i / 2;          /* number of octets */
+
+               base = (xmlChar *)cur;
+               while (i-- > 0) {
+                    if (*base >= 'a')
+                       *base = *base - ('a' - 'A');
+                   base++;
+               }
+
+               v->value.hex.str   = (xmlChar *)cur;
+               v->value.hex.total = total;
                *val = v;
-           } else {
-               return(-1);
+            }
+           goto return0;
+        }
+        case XML_SCHEMAS_INTEGER:
+        case XML_SCHEMAS_PINTEGER:
+        case XML_SCHEMAS_NPINTEGER:
+        case XML_SCHEMAS_NINTEGER:
+        case XML_SCHEMAS_NNINTEGER: {
+           const xmlChar *cur = value;
+           unsigned long lo, mi, hi;
+           int sign = 0;
+           if (cur == NULL)
+               goto return1;
+           if (*cur == '-') {
+               sign = 1;
+               cur++;
+           } else if (*cur == '+')
+               cur++;
+           ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
+           if (ret == 0)
+               goto return1;
+           if (*cur != 0)
+               goto return1;
+           if (type->flags == XML_SCHEMAS_NPINTEGER) {
+               if ((sign == 0) &&
+                   ((hi != 0) || (mi != 0) || (lo != 0)))
+                   goto return1;
+           } else if (type->flags == XML_SCHEMAS_PINTEGER) {
+               if (sign == 1)
+                   goto return1;
+               if ((hi == 0) && (mi == 0) && (lo == 0))
+                   goto return1;
+           } else if (type->flags == XML_SCHEMAS_NINTEGER) {
+               if (sign == 0)
+                   goto return1;
+               if ((hi == 0) && (mi == 0) && (lo == 0))
+                   goto return1;
+           } else if (type->flags == XML_SCHEMAS_NNINTEGER) {
+               if ((sign == 1) &&
+                   ((hi != 0) || (mi != 0) || (lo != 0)))
+                   goto return1;
+           }
+           /*
+            * We can store a value only if no overflow occured
+            */
+           if ((ret > 0) && (val != NULL)) {
+               v = xmlSchemaNewValue(type->flags);
+               if (v != NULL) {
+                   v->value.decimal.lo = lo;
+                   v->value.decimal.mi = lo;
+                   v->value.decimal.hi = lo;
+                   v->value.decimal.sign = sign;
+                   v->value.decimal.frac = 0;
+                   v->value.decimal.total = cur - value;
+                   *val = v;
+               }
            }
+           goto return0;
+       }
+        case XML_SCHEMAS_LONG:
+        case XML_SCHEMAS_BYTE:
+        case XML_SCHEMAS_SHORT:
+        case XML_SCHEMAS_INT: {
+           const xmlChar *cur = value;
+           unsigned long lo, mi, hi;
+           int total = 0;
+           int sign = 0;
+           if (cur == NULL)
+               goto return1;
+           if (*cur == '-') {
+               sign = 1;
+               cur++;
+           } else if (*cur == '+')
+               cur++;
+           ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
+           if (ret <= 0)
+               goto return1;
+           if (*cur != 0)
+               goto return1;
+           if (type->flags == XML_SCHEMAS_LONG) {
+               if (hi >= 922) {
+                   if (hi > 922)
+                       goto return1;
+                   if (mi >= 33720368) {
+                       if (mi > 33720368)
+                           goto return1;
+                       if ((sign == 0) && (lo > 54775807))
+                           goto return1;
+                       if ((sign == 1) && (lo > 54775808))
+                           goto return1;
+                   }
+               }
+           } else if (type->flags == XML_SCHEMAS_INT) {
+               if (hi != 0)
+                   goto return1;
+               if (mi >= 21) {
+                   if (mi > 21)
+                       goto return1;
+                   if ((sign == 0) && (lo > 47483647))
+                       goto return1;
+                   if ((sign == 1) && (lo > 47483648))
+                       goto return1;
+               }
+           } else if (type->flags == XML_SCHEMAS_SHORT) {
+               if ((mi != 0) || (hi != 0))
+                   goto return1;
+               if ((sign == 1) && (lo > 32768))
+                   goto return1;
+               if ((sign == 0) && (lo > 32767))
+                   goto return1;
+           } else if (type->flags == XML_SCHEMAS_BYTE) {
+               if ((mi != 0) || (hi != 0))
+                   goto return1;
+               if ((sign == 1) && (lo > 128))
+                   goto return1;
+               if ((sign == 0) && (lo > 127))
+                   goto return1;
+           }
+           if (val != NULL) {
+               v = xmlSchemaNewValue(type->flags);
+               if (v != NULL) {
+                   v->value.decimal.lo = lo;
+                   v->value.decimal.mi = lo;
+                   v->value.decimal.hi = lo;
+                   v->value.decimal.sign = sign;
+                   v->value.decimal.frac = 0;
+                   v->value.decimal.total = total;
+                   *val = v;
+               }
+           }
+           goto return0;
+       }
+        case XML_SCHEMAS_UINT:
+        case XML_SCHEMAS_ULONG:
+        case XML_SCHEMAS_USHORT:
+        case XML_SCHEMAS_UBYTE: {
+           const xmlChar *cur = value;
+           unsigned long lo, mi, hi;
+           int total = 0;
+           if (cur == NULL)
+               goto return1;
+           ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
+           if (ret <= 0)
+               goto return1;
+           if (*cur != 0)
+               goto return1;
+           if (type->flags == XML_SCHEMAS_ULONG) {
+               if (hi >= 1844) {
+                   if (hi > 1844)
+                       goto return1;
+                   if (mi >= 67440737) {
+                       if (mi > 67440737)
+                           goto return1;
+                       if (lo > 9551615)
+                           goto return1;
+                   }
+               }
+           } else if (type->flags == XML_SCHEMAS_UINT) {
+               if (hi != 0)
+                   goto return1;
+               if (mi >= 42) {
+                   if (mi > 42)
+                       goto return1;
+                   if (lo > 94967295)
+                       goto return1;
+               }
+           } else if (type->flags == XML_SCHEMAS_USHORT) {
+               if ((mi != 0) || (hi != 0))
+                   goto return1;
+               if (lo > 65535)
+                   goto return1;
+           } else if (type->flags == XML_SCHEMAS_UBYTE) {
+               if ((mi != 0) || (hi != 0))
+                   goto return1;
+               if (lo > 255)
+                   goto return1;
+           }
+           if (val != NULL) {
+               v = xmlSchemaNewValue(type->flags);
+               if (v != NULL) {
+                   v->value.decimal.lo = lo;
+                   v->value.decimal.mi = mi;
+                   v->value.decimal.hi = hi;
+                   v->value.decimal.sign = 0;
+                   v->value.decimal.frac = 0;
+                   v->value.decimal.total = total;
+                   *val = v;
+               }
+           }
+           goto return0;
        }
-       return(0);
-    } else {
-       TODO
-       return(0);
     }
+
+done:
+    if (norm != NULL) xmlFree(norm);
+    return(ret);
+return3:
+    if (norm != NULL) xmlFree(norm);
+    return(3);
+return1:
+    if (norm != NULL) xmlFree(norm);
+    return(1);
+return0:
+    if (norm != NULL) xmlFree(norm);
+    return(0);
+error:
+    if (norm != NULL) xmlFree(norm);
     return(-1);
 }
 
 /**
+ * xmlSchemaValPredefTypeNode:
+ * @type: the predefined type
+ * @value: the value to check
+ * @val:  the return computed value
+ * @node:  the node containing the value
+ *
+ * Check that a value conforms to the lexical space of the predefined type.
+ * if true a value is computed and returned in @val.
+ *
+ * Returns 0 if this validates, a positive error code number otherwise
+ *         and -1 in case of internal or API error.
+ */
+int
+xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value,
+                          xmlSchemaValPtr *val, xmlNodePtr node) {
+    return(xmlSchemaValAtomicType(type, value, val, node, 0));
+}
+
+/**
+ * xmlSchemaValidatePredefinedType:
+ * @type: the predefined type
+ * @value: the value to check
+ * @val:  the return computed value
+ *
+ * Check that a value conforms to the lexical space of the predefined type.
+ * if true a value is computed and returned in @val.
+ *
+ * Returns 0 if this validates, a positive error code number otherwise
+ *         and -1 in case of internal or API error.
+ */
+int
+xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
+                               xmlSchemaValPtr *val) {
+    return(xmlSchemaValPredefTypeNode(type, value, val, NULL));
+}
+
+/**
  * xmlSchemaCompareDecimals:
  * @x:  a first decimal value
  * @y:  a second decimal value
@@ -1350,19 +2233,40 @@ static int
 xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
 {
     xmlSchemaValPtr swp;
-    int order = 1;
+    int order = 1, p;
     unsigned long tmp;
 
-    if ((x->value.decimal.sign) && (x->value.decimal.sign))
-        order = -1;
-    else if (x->value.decimal.sign)
-        return (-1);
-    else if (y->value.decimal.sign)
+    if ((x->value.decimal.sign) && 
+       ((x->value.decimal.lo != 0) ||
+        (x->value.decimal.mi != 0) ||
+        (x->value.decimal.hi != 0))) {
+       if ((y->value.decimal.sign) &&
+           ((y->value.decimal.lo != 0) ||
+            (y->value.decimal.mi != 0) ||
+            (y->value.decimal.hi != 0)))
+           order = -1;
+       else
+           return (-1);
+    } else if ((y->value.decimal.sign) &&
+              ((y->value.decimal.lo != 0) ||
+               (y->value.decimal.mi != 0) ||
+               (y->value.decimal.hi != 0))) {
         return (1);
+    }
     if (x->value.decimal.frac == y->value.decimal.frac) {
-        if (x->value.decimal.base < y->value.decimal.base)
-            return (-1);
-        return (x->value.decimal.base > y->value.decimal.base);
+       if (x->value.decimal.hi < y->value.decimal.hi)
+           return (-order);
+       if (x->value.decimal.hi < y->value.decimal.hi)
+           return (order);
+       if (x->value.decimal.mi < y->value.decimal.mi)
+           return (-order);
+       if (x->value.decimal.mi < y->value.decimal.mi)
+           return (order);
+        if (x->value.decimal.lo < y->value.decimal.lo)
+            return (-order);
+        if (x->value.decimal.lo > y->value.decimal.lo)
+           return(order);
+       return(0);
     }
     if (y->value.decimal.frac > x->value.decimal.frac) {
         swp = y;
@@ -1370,19 +2274,16 @@ xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
         x = swp;
         order = -order;
     }
-    tmp =
-        x->value.decimal.base / powten[x->value.decimal.frac -
-                                       y->value.decimal.frac];
-    if (tmp > y->value.decimal.base)
+    p = powten[x->value.decimal.frac - y->value.decimal.frac];
+    tmp = x->value.decimal.lo / p;
+    if (tmp > y->value.decimal.lo)
         return (order);
-    if (tmp < y->value.decimal.base)
+    if (tmp < y->value.decimal.lo)
         return (-order);
-    tmp =
-        y->value.decimal.base * powten[x->value.decimal.frac -
-                                       y->value.decimal.frac];
-    if (x->value.decimal.base < tmp)
+    tmp = y->value.decimal.lo * p;
+    if (x->value.decimal.lo < tmp)
         return (-order);
-    if (x->value.decimal.base == tmp)
+    if (x->value.decimal.lo == tmp)
         return (0);
     return (order);
 }
@@ -1402,7 +2303,8 @@ xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
 {
     long carry, mon, day;
     double sec;
-    long xmon, xday, myear, lyear, minday, maxday;
+    int invert = 1;
+    long xmon, xday, myear, minday, maxday;
     static const long dayRange [2][12] = {
         { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
         { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
@@ -1446,23 +2348,31 @@ xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
     } else if ((day <= 0) && (sec <= 0.0)) {
         return -1;
     } else {
+       invert = -1;
         xmon = -mon;
         xday = day;
     }
 
     myear = xmon / 12;
-    lyear = myear / 4;
-    minday = (myear * 365) + (lyear != 0 ? lyear - 1 : 0);
-    maxday = (myear * 365) + (lyear != 0 ? lyear + 1 : 0);
-        
+    if (myear == 0) {
+       minday = 0;
+       maxday = 0;
+    } else {
+       maxday = 366 * ((myear + 3) / 4) +
+                365 * ((myear - 1) % 4);
+       minday = maxday - 1;
+    }
+
     xmon = xmon % 12;
     minday += dayRange[0][xmon];
     maxday += dayRange[1][xmon];
 
+    if ((maxday == minday) && (maxday == xday))
+       return(0); /* can this really happen ? */
     if (maxday < xday)
-        return 1;
-    else if (minday > xday)
-        return -1;
+        return(-invert);
+    if (minday > xday)
+        return(invert);
 
     /* indeterminate */
     return 2;
@@ -1704,7 +2614,9 @@ _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt)
  */
 #define TIME_TO_NUMBER(dt)                              \
     ((double)((dt->value.date.hour * SECS_PER_HOUR) +   \
-              (dt->value.date.min * SECS_PER_MIN)) + dt->value.date.sec)
+              (dt->value.date.min * SECS_PER_MIN) +    \
+              (dt->value.date.tzo * SECS_PER_MIN)) +   \
+               dt->value.date.sec)
 
 /**
  * xmlSchemaCompareDates:
@@ -1794,18 +2706,24 @@ xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
                 p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
                 p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
 
-               xmlSchemaFreeValue(p1);
-               xmlSchemaFreeValue(q1);
-               xmlSchemaFreeValue(p2);
-                if (p2d > q1d)
+                if (p2d > q1d) {
+                   xmlSchemaFreeValue(p1);
+                   xmlSchemaFreeValue(q1);
+                   xmlSchemaFreeValue(p2);
                     return 1;
-                else if (p2d == q1d) {
+               } else if (p2d == q1d) {
                     sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
+                   xmlSchemaFreeValue(p1);
+                   xmlSchemaFreeValue(q1);
+                   xmlSchemaFreeValue(p2);
                     if (sec > 0.0)
                         return 1;
                     else
                         return 2; /* indeterminate */
                 }
+               xmlSchemaFreeValue(p1);
+               xmlSchemaFreeValue(q1);
+               xmlSchemaFreeValue(p2);
             }
        } else {
            xmlSchemaFreeValue(p1);
@@ -1961,6 +2879,131 @@ xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
 }
 
 /**
+ * xmlSchemaCompareNormStrings:
+ * @x:  a first string value
+ * @y:  a second string value
+ *
+ * Compare 2 string for their normalized values.
+ *
+ * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
+ * case of error
+ */
+static int
+xmlSchemaCompareNormStrings(xmlSchemaValPtr x, xmlSchemaValPtr y) {
+    const xmlChar *utf1;
+    const xmlChar *utf2;
+    int tmp;
+
+    if ((x == NULL) || (y == NULL))
+       return(-2);
+    utf1 = x->value.str;
+    utf2 = y->value.str;
+    
+    while (IS_BLANK(*utf1)) utf1++;
+    while (IS_BLANK(*utf2)) utf2++;
+    while ((*utf1 != 0) && (*utf2 != 0)) {
+       if (IS_BLANK(*utf1)) {
+           if (!IS_BLANK(*utf2)) {
+               tmp = *utf1 - *utf2;
+               return(tmp);
+           }
+           while (IS_BLANK(*utf1)) utf1++;
+           while (IS_BLANK(*utf2)) utf2++;
+       } else {
+           tmp = *utf1++ - *utf2++;
+           if (tmp < 0)
+               return(-1);
+           if (tmp > 0)
+               return(1);
+       }
+    }
+    if (*utf1 != 0) {
+       while (IS_BLANK(*utf1)) utf1++;
+       if (*utf1 != 0)
+           return(1);
+    }
+    if (*utf2 != 0) {
+       while (IS_BLANK(*utf2)) utf2++;
+       if (*utf2 != 0)
+           return(-1);
+    }
+    return(0);
+}
+
+/**
+ * xmlSchemaCompareFloats:
+ * @x:  a first float or double value
+ * @y:  a second float or double value
+ *
+ * Compare 2 values
+ *
+ * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
+ * case of error
+ */
+static int
+xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) {
+    double d1, d2;
+
+    if ((x == NULL) || (y == NULL))
+       return(-2);
+
+    /*
+     * Cast everything to doubles.
+     */
+    if (x->type == XML_SCHEMAS_DOUBLE)
+       d1 = x->value.d;
+    else if (x->type == XML_SCHEMAS_FLOAT)
+       d1 = x->value.f;
+    else
+       return(-2);
+
+    if (y->type == XML_SCHEMAS_DOUBLE)
+       d2 = y->value.d;
+    else if (y->type == XML_SCHEMAS_FLOAT)
+       d2 = y->value.f;
+    else
+       return(-2);
+
+    /*
+     * Check for special cases.
+     */
+    if (xmlXPathIsNaN(d1)) {
+       if (xmlXPathIsNaN(d2))
+           return(0);
+       return(1);
+    }
+    if (xmlXPathIsNaN(d2))
+       return(-1);
+    if (d1 == xmlXPathPINF) {
+       if (d2 == xmlXPathPINF)
+           return(0);
+        return(1);
+    }
+    if (d2 == xmlXPathPINF)
+        return(-1);
+    if (d1 == xmlXPathNINF) {
+       if (d2 == xmlXPathNINF)
+           return(0);
+        return(-1);
+    }
+    if (d2 == xmlXPathNINF)
+        return(1);
+
+    /*
+     * basic tests, the last one we should have equality, but
+     * portability is more important than speed and handling
+     * NaN or Inf in a portable way is always a challenge, so ...
+     */
+    if (d1 < d2)
+       return(-1);
+    if (d1 > d2)
+       return(1);
+    if (d1 == d2)
+       return(0);
+    return(2);
+}
+
+/**
  * xmlSchemaCompareValues:
  * @x:  a first value
  * @y:  a second value
@@ -1970,16 +3013,44 @@ xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
  * case of error
  */
-static int
+int
 xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
     if ((x == NULL) || (y == NULL))
        return(-2);
 
     switch (x->type) {
-       case XML_SCHEMAS_STRING:
-           TODO
+       case XML_SCHEMAS_UNKNOWN:
+           return(-2);
+        case XML_SCHEMAS_INTEGER:
+        case XML_SCHEMAS_NPINTEGER:
+        case XML_SCHEMAS_NINTEGER:
+        case XML_SCHEMAS_NNINTEGER:
+        case XML_SCHEMAS_PINTEGER:
+        case XML_SCHEMAS_INT:
+        case XML_SCHEMAS_UINT:
+        case XML_SCHEMAS_LONG:
+        case XML_SCHEMAS_ULONG:
+        case XML_SCHEMAS_SHORT:
+        case XML_SCHEMAS_USHORT:
+        case XML_SCHEMAS_BYTE:
+        case XML_SCHEMAS_UBYTE:
        case XML_SCHEMAS_DECIMAL:
-           if (y->type == XML_SCHEMAS_DECIMAL)
+           if (y->type == x->type)
+               return(xmlSchemaCompareDecimals(x, y));
+           if ((y->type == XML_SCHEMAS_DECIMAL) ||
+               (y->type == XML_SCHEMAS_INTEGER) ||
+               (y->type == XML_SCHEMAS_NPINTEGER) ||
+               (y->type == XML_SCHEMAS_NINTEGER) ||
+               (y->type == XML_SCHEMAS_NNINTEGER) ||
+               (y->type == XML_SCHEMAS_PINTEGER) ||
+               (y->type == XML_SCHEMAS_INT) ||
+               (y->type == XML_SCHEMAS_UINT) ||
+               (y->type == XML_SCHEMAS_LONG) ||
+               (y->type == XML_SCHEMAS_ULONG) ||
+               (y->type == XML_SCHEMAS_SHORT) ||
+               (y->type == XML_SCHEMAS_USHORT) ||
+               (y->type == XML_SCHEMAS_BYTE) ||
+               (y->type == XML_SCHEMAS_UBYTE))
                return(xmlSchemaCompareDecimals(x, y));
            return(-2);
         case XML_SCHEMAS_DURATION:
@@ -2003,15 +3074,127 @@ xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
                 (y->type == XML_SCHEMAS_DATE)      ||
                 (y->type == XML_SCHEMAS_GYEARMONTH))
                 return (xmlSchemaCompareDates(x, y));
+            return (-2);
+        case XML_SCHEMAS_NORMSTRING:
+        case XML_SCHEMAS_TOKEN:
+        case XML_SCHEMAS_LANGUAGE:
+        case XML_SCHEMAS_NMTOKEN:
+        case XML_SCHEMAS_NAME:
+        case XML_SCHEMAS_NCNAME:
+        case XML_SCHEMAS_ID:
+        case XML_SCHEMAS_IDREF:
+        case XML_SCHEMAS_ENTITY:
+        case XML_SCHEMAS_NOTATION:
+        case XML_SCHEMAS_ANYURI:
+            if ((y->type == XML_SCHEMAS_NORMSTRING) ||
+                (y->type == XML_SCHEMAS_TOKEN) ||
+                (y->type == XML_SCHEMAS_LANGUAGE) ||
+                (y->type == XML_SCHEMAS_NMTOKEN) ||
+                (y->type == XML_SCHEMAS_NAME) ||
+                (y->type == XML_SCHEMAS_QNAME) ||
+                (y->type == XML_SCHEMAS_NCNAME) ||
+                (y->type == XML_SCHEMAS_ID) ||
+                (y->type == XML_SCHEMAS_IDREF) ||
+                (y->type == XML_SCHEMAS_ENTITY) ||
+                (y->type == XML_SCHEMAS_NOTATION) ||
+                (y->type == XML_SCHEMAS_ANYURI))
+                return (xmlSchemaCompareNormStrings(x, y));
+            return (-2);
+        case XML_SCHEMAS_QNAME:
+            if (y->type == XML_SCHEMAS_QNAME) {
+               if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) &&
+                   (xmlStrEqual(x->value.qname.uri, y->value.qname.uri)))
+                   return(0);
+               return(2);
+           }
+           return (-2);
+        case XML_SCHEMAS_FLOAT:
+        case XML_SCHEMAS_DOUBLE:
+            if ((y->type == XML_SCHEMAS_FLOAT) ||
+                (y->type == XML_SCHEMAS_DOUBLE))
+                return (xmlSchemaCompareFloats(x, y));
+            return (-2);
+        case XML_SCHEMAS_BOOLEAN:
+            if (y->type == XML_SCHEMAS_BOOLEAN) {
+               if (x->value.b == y->value.b)
+                   return(0);
+               if (x->value.b == 0)
+                   return(-1);
+               return(1);
+           }
+           return (-2);
+        case XML_SCHEMAS_HEXBINARY:
+            if (y->type == XML_SCHEMAS_HEXBINARY) {
+               if (x->value.hex.total == y->value.hex.total) {
+                   int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str);
+                   if (ret > 0)
+                       return(1);
+                   else if (ret == 0)
+                       return(0);
+               }
+               else if (x->value.hex.total > y->value.hex.total)
+                   return(1);
 
+               return(-1);
+            }
             return (-2);
-       default:
+        case XML_SCHEMAS_STRING:
+        case XML_SCHEMAS_IDREFS:
+        case XML_SCHEMAS_ENTITIES:
+        case XML_SCHEMAS_NMTOKENS:
            TODO
+           break;
     }
     return -2;
 }
 
 /**
+ * xmlSchemaNormLen:
+ * @value:  a string
+ *
+ * Computes the UTF8 length of the normalized value of the string
+ *
+ * Returns the length or -1 in case of error.
+ */
+static int
+xmlSchemaNormLen(const xmlChar *value) {
+    const xmlChar *utf;
+    int ret = 0;
+
+    if (value == NULL)
+       return(-1);
+    utf = value;
+    while (IS_BLANK(*utf)) utf++;
+    while (*utf != 0) {
+       if (utf[0] & 0x80) {
+           if ((utf[1] & 0xc0) != 0x80)
+               return(-1);
+           if ((utf[0] & 0xe0) == 0xe0) {
+               if ((utf[2] & 0xc0) != 0x80)
+                   return(-1);
+               if ((utf[0] & 0xf0) == 0xf0) {
+                   if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
+                       return(-1);
+                   utf += 4;
+               } else {
+                   utf += 3;
+               }
+           } else {
+               utf += 2;
+           }
+       } else if (IS_BLANK(*utf)) {
+           while (IS_BLANK(*utf)) utf++;
+           if (*utf == 0)
+               break;
+       } else {
+           utf++;
+       }
+       ret++;
+    }
+    return(ret);
+}
+
+/**
  * xmlSchemaValidateFacet:
  * @base:  the base type
  * @facet:  the facet to check
@@ -2036,14 +3219,14 @@ xmlSchemaValidateFacet(xmlSchemaTypePtr base ATTRIBUTE_UNUSED,
            if (ret == 1)
                return(0);
            if (ret == 0) {
-               TODO /* error code */
+               /* TODO error code */
                return(1);
            }
            return(ret);
        case XML_SCHEMA_FACET_MAXEXCLUSIVE:
            ret = xmlSchemaCompareValues(val, facet->val);
            if (ret == -2) {
-               TODO /* error code */
+               /* TODO error code */
                return(-1);
            }
            if (ret == -1)
@@ -2053,7 +3236,7 @@ xmlSchemaValidateFacet(xmlSchemaTypePtr base ATTRIBUTE_UNUSED,
        case XML_SCHEMA_FACET_MAXINCLUSIVE:
            ret = xmlSchemaCompareValues(val, facet->val);
            if (ret == -2) {
-               TODO /* error code */
+               /* TODO error code */
                return(-1);
            }
            if ((ret == -1) || (ret == 0))
@@ -2063,7 +3246,7 @@ xmlSchemaValidateFacet(xmlSchemaTypePtr base ATTRIBUTE_UNUSED,
        case XML_SCHEMA_FACET_MINEXCLUSIVE:
            ret = xmlSchemaCompareValues(val, facet->val);
            if (ret == -2) {
-               TODO /* error code */
+               /* TODO error code */
                return(-1);
            }
            if (ret == 1)
@@ -2073,7 +3256,7 @@ xmlSchemaValidateFacet(xmlSchemaTypePtr base ATTRIBUTE_UNUSED,
        case XML_SCHEMA_FACET_MININCLUSIVE:
            ret = xmlSchemaCompareValues(val, facet->val);
            if (ret == -2) {
-               TODO /* error code */
+               /* TODO error code */
                return(-1);
            }
            if ((ret == 1) || (ret == 0))
@@ -2081,32 +3264,97 @@ xmlSchemaValidateFacet(xmlSchemaTypePtr base ATTRIBUTE_UNUSED,
            /* error code */
            return(1);
        case XML_SCHEMA_FACET_WHITESPACE:
-           TODO /* whitespaces */
+           /* TODO whitespaces */
            return(0);
-       case XML_SCHEMA_FACET_MAXLENGTH:
-           if ((facet->val != NULL) &&
-               (facet->val->type == XML_SCHEMAS_DECIMAL) &&
-               (facet->val->value.decimal.frac == 0)) {
-               unsigned int len;
-
-               if (facet->val->value.decimal.sign == 1)
-                   return(1);
-                len = xmlUTF8Strlen(value);
-               if (len > facet->val->value.decimal.base)
-                   return(1);
-               return(0);
-           }
-           TODO /* error code */
-           return(1);
        case  XML_SCHEMA_FACET_ENUMERATION:
            if ((facet->value != NULL) &&
                (xmlStrEqual(facet->value, value)))
                return(0);
            return(1);
+       case XML_SCHEMA_FACET_LENGTH:
+       case XML_SCHEMA_FACET_MAXLENGTH:
+       case XML_SCHEMA_FACET_MINLENGTH: {
+           unsigned int len = 0;
+
+           if ((facet->val == NULL) ||
+               ((facet->val->type != XML_SCHEMAS_DECIMAL) &&
+                (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
+               (facet->val->value.decimal.frac != 0)) {
+               return(-1);
+           }
+           if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
+               len = val->value.hex.total;
+           else { 
+               switch (base->flags) {
+                   case XML_SCHEMAS_IDREF:
+                   case XML_SCHEMAS_NORMSTRING:
+                   case XML_SCHEMAS_TOKEN:
+                   case XML_SCHEMAS_LANGUAGE:
+                   case XML_SCHEMAS_NMTOKEN:
+                   case XML_SCHEMAS_NAME:
+                   case XML_SCHEMAS_NCNAME:
+                   case XML_SCHEMAS_ID:
+                       len = xmlSchemaNormLen(value);
+                       break;
+                   case XML_SCHEMAS_STRING:
+                       len = xmlUTF8Strlen(value);
+                       break;
+                   default:
+                       TODO
+               }
+           }
+           if (facet->type == XML_SCHEMA_FACET_LENGTH) {
+               if (len != facet->val->value.decimal.lo)
+                   return(1);
+           } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
+               if (len < facet->val->value.decimal.lo)
+                   return(1);
+           } else {
+               if (len > facet->val->value.decimal.lo)
+                   return(1);
+           }
+           break;
+       }
+       case XML_SCHEMA_FACET_TOTALDIGITS:
+       case XML_SCHEMA_FACET_FRACTIONDIGITS:
+
+           if ((facet->val == NULL) ||
+               ((facet->val->type != XML_SCHEMAS_DECIMAL) &&
+                (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
+               (facet->val->value.decimal.frac != 0)) {
+               return(-1);
+           }
+           if ((val == NULL) ||
+               ((val->type != XML_SCHEMAS_DECIMAL) &&
+                (val->type != XML_SCHEMAS_INTEGER) &&
+                (val->type != XML_SCHEMAS_NPINTEGER) &&
+                (val->type != XML_SCHEMAS_NINTEGER) &&
+                (val->type != XML_SCHEMAS_NNINTEGER) &&
+                (val->type != XML_SCHEMAS_PINTEGER) &&
+                (val->type != XML_SCHEMAS_INT) &&
+                (val->type != XML_SCHEMAS_UINT) &&
+                (val->type != XML_SCHEMAS_LONG) &&
+                (val->type != XML_SCHEMAS_ULONG) &&
+                (val->type != XML_SCHEMAS_SHORT) &&
+                (val->type != XML_SCHEMAS_USHORT) &&
+                (val->type != XML_SCHEMAS_BYTE) &&
+                (val->type != XML_SCHEMAS_UBYTE))) {
+               return(-1);
+           }
+           if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
+               if (val->value.decimal.total > facet->val->value.decimal.lo)
+                   return(1);
+
+           } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) {
+               if (val->value.decimal.frac > facet->val->value.decimal.lo)
+                   return(1);
+           }
+           break;
        default:
            TODO
     }
     return(0);
+
 }
 
 #endif /* LIBXML_SCHEMAS_ENABLED */