added param support for relaxng type checking, started to increment the

* relaxng.c xmlschemas.c xmlschemastypes.c
  include/libxml/xmlschemastypes.h: added param support for relaxng
  type checking, started to increment the pool of simple types
  registered, still much work to be done on simple types and
  facets checkings.
Daniel
diff --git a/ChangeLog b/ChangeLog
index 15ba9fb..f0b78a9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Thu Feb 27 18:40:04 CET 2003 Daniel Veillard <daniel@veillard.com>
+
+	* relaxng.c xmlschemas.c xmlschemastypes.c
+	  include/libxml/xmlschemastypes.h: added param support for relaxng
+	  type checking, started to increment the pool of simple types
+	  registered, still much work to be done on simple types and
+	  facets checkings.
+
 Wed Feb 26 16:45:39 CET 2003 Daniel Veillard <daniel@veillard.com>
 
 	* entities.c: fixes again one of the problem raised by
diff --git a/include/libxml/xmlschemastypes.h b/include/libxml/xmlschemastypes.h
index a758c12..992232e 100644
--- a/include/libxml/xmlschemastypes.h
+++ b/include/libxml/xmlschemastypes.h
@@ -16,6 +16,7 @@
 #ifdef LIBXML_SCHEMAS_ENABLED
 
 #include <libxml/schemasInternals.h>
+#include <libxml/xmlschemas.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -33,6 +34,12 @@
 						 const xmlChar *value,
 						 xmlSchemaValPtr val);
 void		xmlSchemaFreeValue		(xmlSchemaValPtr val);
+xmlSchemaFacetPtr xmlSchemaNewFacet		(void);
+int		xmlSchemaCheckFacet		(xmlSchemaFacetPtr facet,
+						 xmlSchemaTypePtr typeDecl,
+						 xmlSchemaParserCtxtPtr ctxt,
+						 const xmlChar *name);
+void		xmlSchemaFreeFacet		(xmlSchemaFacetPtr facet);
 
 #ifdef __cplusplus
 }
diff --git a/relaxng.c b/relaxng.c
index 29db131..ff11f3e 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -332,13 +332,40 @@
  * @data:  data needed for the library
  * @type:  the type name
  * @value:  the value to check
+ * @result:  place to store the result if needed
  *
  * Function provided by a type library to check if a value match a type
  *
  * Returns 1 if yes, 0 if no and -1 in case of error.
  */
 typedef int (*xmlRelaxNGTypeCheck) (void *data, const xmlChar *type,
-	                            const xmlChar *value);
+	                            const xmlChar *value, void **result);
+
+/**
+ * xmlRelaxNGFacetCheck:
+ * @data:  data needed for the library
+ * @type:  the type name
+ * @facet:  the facet name
+ * @val:  the facet value
+ * @strval:  the string value
+ * @value:  the value to check
+ *
+ * Function provided by a type library to check a value facet
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+typedef int (*xmlRelaxNGFacetCheck) (void *data, const xmlChar *type,
+	                             const xmlChar *facet, const xmlChar *val,
+				     const xmlChar *strval, void *value);
+
+/**
+ * xmlRelaxNGTypeFree:
+ * @data:  data needed for the library
+ * @result:  the value to free
+ *
+ * Function provided by a type library to free a returned result
+ */
+typedef void (*xmlRelaxNGTypeFree) (void *data, void *result);
 
 /**
  * xmlRelaxNGTypeCompare:
@@ -363,6 +390,8 @@
     xmlRelaxNGTypeHave      have;	/* the export function */
     xmlRelaxNGTypeCheck    check;	/* the checking function */
     xmlRelaxNGTypeCompare   comp;	/* the compare function */
+    xmlRelaxNGFacetCheck   facet;	/* the facet check function */
+    xmlRelaxNGTypeFree     freef;	/* the freeing function */
 };
 
 /************************************************************************
@@ -1440,7 +1469,8 @@
 static int
 xmlRelaxNGSchemaTypeCheck(void *data ATTRIBUTE_UNUSED,
 	                  const xmlChar *type,
-			  const xmlChar *value) {
+			  const xmlChar *value,
+			  void **result) {
     xmlSchemaTypePtr typ;
     int ret;
 
@@ -1456,7 +1486,8 @@
 	       BAD_CAST "http://www.w3.org/2001/XMLSchema");
     if (typ == NULL)
 	return(-1);
-    ret = xmlSchemaValidatePredefinedType(typ, value, NULL);
+    ret = xmlSchemaValidatePredefinedType(typ, value,
+	                                  (xmlSchemaValPtr *) result);
     if (ret == 0)
 	return(1);
     if (ret > 0)
@@ -1465,6 +1496,79 @@
 }
 
 /**
+ * xmlRelaxNGSchemaFacetCheck:
+ * @data:  data needed for the library
+ * @type:  the type name
+ * @facet:  the facet name
+ * @val:  the facet value
+ * @strval:  the string value
+ * @value:  the value to check
+ *
+ * Function provided by a type library to check a value facet
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGSchemaFacetCheck (void *data, const xmlChar *type,
+	                    const xmlChar *facetname, const xmlChar *val,
+			    const xmlChar *strval, void *value) {
+    xmlSchemaFacetPtr facet;
+    xmlSchemaTypePtr typ;
+    int ret;
+
+    if ((type == NULL) || (strval == NULL))
+	return(-1);
+    typ = xmlSchemaGetPredefinedType(type, 
+	       BAD_CAST "http://www.w3.org/2001/XMLSchema");
+    if (typ == NULL)
+	return(-1);
+
+    facet = xmlSchemaNewFacet();
+    if (facet == NULL)
+	return(-1);
+
+    if (xmlStrEqual(facetname, BAD_CAST "minInclusive"))  {
+        facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
+    } else if (xmlStrEqual(facetname, BAD_CAST "minExclusive"))  {
+        facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
+    } else if (xmlStrEqual(facetname, BAD_CAST "maxInclusive"))  {
+        facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
+    } else if (xmlStrEqual(facetname, BAD_CAST "maxExclusive"))  {
+        facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
+    } else if (xmlStrEqual(facetname, BAD_CAST "totalDigits"))  {
+        facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
+    } else if (xmlStrEqual(facetname, BAD_CAST "fractionDigits"))  {
+        facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
+    } else if (xmlStrEqual(facetname, BAD_CAST "pattern"))  {
+        facet->type = XML_SCHEMA_FACET_PATTERN;
+    } else if (xmlStrEqual(facetname, BAD_CAST "enumeration"))  {
+        facet->type = XML_SCHEMA_FACET_ENUMERATION;
+    } else if (xmlStrEqual(facetname, BAD_CAST "whiteSpace"))  {
+        facet->type = XML_SCHEMA_FACET_WHITESPACE;
+    } else if (xmlStrEqual(facetname, BAD_CAST "length"))  {
+        facet->type = XML_SCHEMA_FACET_LENGTH;
+    } else if (xmlStrEqual(facetname, BAD_CAST "maxLength"))  {
+        facet->type = XML_SCHEMA_FACET_MAXLENGTH;
+    } else if (xmlStrEqual(facetname, BAD_CAST "minLength")) {
+        facet->type = XML_SCHEMA_FACET_MINLENGTH;
+    } else {
+	xmlSchemaFreeFacet(facet);
+	return(-1);
+    }
+    facet->value = xmlStrdup(val);
+    ret = xmlSchemaCheckFacet(facet, typ, NULL, type);
+    if (ret != 0) {
+	xmlSchemaFreeFacet(facet);
+	return(-1);
+    }
+    ret = xmlSchemaValidateFacet(typ, facet, strval, value);
+    xmlSchemaFreeFacet(facet);
+    if (ret != 0)
+	return(-1);
+    return(0);
+}
+
+/**
  * xmlRelaxNGSchemaTypeCompare:
  * @data:  data needed for the library
  * @type:  the type name
@@ -1520,21 +1624,13 @@
 static int
 xmlRelaxNGDefaultTypeCheck(void *data ATTRIBUTE_UNUSED,
 	                   const xmlChar *type ATTRIBUTE_UNUSED,
-			  const xmlChar *value ATTRIBUTE_UNUSED) {
+			   const xmlChar *value ATTRIBUTE_UNUSED,
+			   void **result ATTRIBUTE_UNUSED) {
     if (value == NULL)
 	return(-1);
     if (xmlStrEqual(type, BAD_CAST "string"))
 	return(1);
     if (xmlStrEqual(type, BAD_CAST "token")) {
-#if 0
-	const xmlChar *cur = value;
-
-	while (*cur != 0) {
-	    if (!IS_BLANK(*cur))
-		return(1);
-	    cur++;
-	}
-#endif
 	return(1);
     }
 
@@ -1624,7 +1720,8 @@
 static int
 xmlRelaxNGRegisterTypeLibrary(const xmlChar *namespace, void *data,
     xmlRelaxNGTypeHave have, xmlRelaxNGTypeCheck check,
-    xmlRelaxNGTypeCompare comp) {
+    xmlRelaxNGTypeCompare comp, xmlRelaxNGFacetCheck facet,
+    xmlRelaxNGTypeFree freef) {
     xmlRelaxNGTypeLibraryPtr lib;
     int ret;
 
@@ -1650,6 +1747,8 @@
     lib->have = have;
     lib->comp = comp;
     lib->check = check;
+    lib->facet = facet;
+    lib->freef = freef;
     ret = xmlHashAddEntry(xmlRelaxNGRegisteredTypes, namespace, lib);
     if (ret < 0) {
 	xmlGenericError(xmlGenericErrorContext,
@@ -1683,13 +1782,17 @@
 	    NULL,
 	    xmlRelaxNGSchemaTypeHave,
 	    xmlRelaxNGSchemaTypeCheck,
-	    xmlRelaxNGSchemaTypeCompare);
+	    xmlRelaxNGSchemaTypeCompare,
+	    xmlRelaxNGSchemaFacetCheck,
+	    (xmlRelaxNGTypeFree) xmlSchemaFreeValue);
     xmlRelaxNGRegisterTypeLibrary(
 	    xmlRelaxNGNs,
 	    NULL,
 	    xmlRelaxNGDefaultTypeHave,
 	    xmlRelaxNGDefaultTypeCheck,
-	    xmlRelaxNGDefaultTypeCompare);
+	    xmlRelaxNGDefaultTypeCompare,
+	    NULL,
+	    NULL);
     xmlRelaxNGTypeInitialized = 1;
     return(0);
 }
@@ -2009,6 +2112,8 @@
 		    lastparam->next = param;
 		    lastparam = param;
 		}
+		if (lib != NULL) {
+		}
 	    }
 	    content = content->next;
 	}
@@ -2960,11 +3065,6 @@
 	}
     } else if (IS_RELAXNG(node, "data")) {
 	def = xmlRelaxNGParseData(ctxt, node);
-#if 0
-    } else if (IS_RELAXNG(node, "define")) {
-	xmlRelaxNGParseDefine(ctxt, node);
-	def = NULL;
-#endif
     } else if (IS_RELAXNG(node, "value")) {
 	def = xmlRelaxNGParseValue(ctxt, node);
     } else if (IS_RELAXNG(node, "list")) {
@@ -5835,29 +5935,47 @@
 static int
 xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar *value,
 	                   xmlRelaxNGDefinePtr define) {
-    int ret;
+    int ret, tmp;
     xmlRelaxNGTypeLibraryPtr lib;
+    void *result = NULL;
+    xmlRelaxNGDefinePtr cur;
 
     if ((define == NULL) || (define->data == NULL)) {
 	return(-1);
     }
     lib = (xmlRelaxNGTypeLibraryPtr) define->data;
-    if (lib->check != NULL)
-	ret = lib->check(lib->data, define->name, value);
-    else 
+    if (lib->check != NULL) {
+	if ((define->attrs != NULL) &&
+	    (define->attrs->type == XML_RELAXNG_PARAM)) {
+	    ret = lib->check(lib->data, define->name, value, &result);
+	} else {
+	    ret = lib->check(lib->data, define->name, value, NULL);
+	}
+    } else 
 	ret = -1;
     if (ret < 0) {
 	VALID_CTXT();
-	VALID_ERROR2("Internal: failed to validate type %s\n", define->name);
+	VALID_ERROR2("failed to validate type %s\n", define->name);
+	if ((result != NULL) && (lib != NULL) && (lib->freef != NULL))
+	    lib->freef(lib->data, result);
 	return(-1);
     } else if (ret == 1) {
 	ret = 0;
     } else {
 	VALID_CTXT();
 	VALID_ERROR3("Type %s doesn't allow value %s\n", define->name, value);
-	return(-1);
 	ret = -1;
     }
+    cur = define->attrs;
+    while ((ret == 0) && (cur != NULL) && (cur->type == XML_RELAXNG_PARAM)) {
+	if (lib->facet != NULL) {
+	    tmp = lib->facet(lib->data, define->name, cur->name,
+		             cur->value, value, result);
+            if (tmp != 0)
+	        ret = -1;
+	}
+	cur = cur->next;
+    }
     if ((ret == 0) && (define->content != NULL)) {
 	const xmlChar *oldvalue, *oldendvalue;
 
@@ -5869,6 +5987,8 @@
 	ctxt->state->value = (xmlChar *) oldvalue;
 	ctxt->state->endvalue = (xmlChar *) oldendvalue;
     }
+    if ((result != NULL) && (lib != NULL) && (lib->freef != NULL))
+	lib->freef(lib->data, result);
     return(ret);
 }
 
@@ -6998,7 +7118,7 @@
 	    ret = xmlRelaxNGValidateDatatype(ctxt, content, define);
 	    if (ret == -1) {
 		VALID_CTXT();
-		VALID_ERROR2("internal error validating %s\n", define->name);
+		VALID_ERROR2("Error validating %s\n", define->name);
 	    } else if (ret == 0) {
 		ctxt->state->seq = NULL;
 	    }
diff --git a/xmlschemas.c b/xmlschemas.c
index 9bafb2d..018b0b2 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -172,15 +172,13 @@
  *
  * Returns the newly allocated structure or NULL in case or error
  */
-static xmlSchemaFacetPtr
-xmlSchemaNewFacet(xmlSchemaParserCtxtPtr ctxt)
+xmlSchemaFacetPtr
+xmlSchemaNewFacet(void)
 {
     xmlSchemaFacetPtr ret;
 
     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
     if (ret == NULL) {
-        if ((ctxt != NULL) && (ctxt->error != NULL))
-            ctxt->error(ctxt->userData, "Out of memory\n");
         return (NULL);
     }
     memset(ret, 0, sizeof(xmlSchemaFacet));
@@ -317,7 +315,7 @@
  *
  * Deallocate a Schema Facet structure.
  */
-static void
+void
 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
 {
     if (facet == NULL)
@@ -1338,7 +1336,7 @@
     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
         return (NULL);
 
-    facet = xmlSchemaNewFacet(ctxt);
+    facet = xmlSchemaNewFacet();
     if (facet == NULL)
 	return (NULL);
     facet->node = node;
@@ -3708,6 +3706,149 @@
 }
 
 /**
+ * xmlSchemaCheckFacet:
+ * @facet:  the facet
+ * @typeDecl:  the schema type definition
+ * @ctxt:  the schema parser context or NULL
+ * @name: name of the type
+ *
+ * Checks the default values types, especially for facets 
+ *
+ * Returns 0 if okay or -1 in cae of error
+ */
+int
+xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
+	            xmlSchemaTypePtr typeDecl,
+		    xmlSchemaParserCtxtPtr ctxt,
+		    const xmlChar *name)
+{
+    static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
+    int ret = 0;
+
+    if (nonNegativeIntegerType == NULL) {
+	nonNegativeIntegerType = xmlSchemaGetPredefinedType(
+		BAD_CAST "nonNegativeInteger", xmlSchemaNs);
+    }
+    switch (facet->type) {
+	case XML_SCHEMA_FACET_MININCLUSIVE:
+	case XML_SCHEMA_FACET_MINEXCLUSIVE:
+	case XML_SCHEMA_FACET_MAXINCLUSIVE:
+	case XML_SCHEMA_FACET_MAXEXCLUSIVE: {
+	    /*
+	     * Okay we need to validate the value
+	     * at that point.
+	     */
+	    xmlSchemaValidCtxtPtr vctxt;
+
+	    vctxt = xmlSchemaNewValidCtxt(NULL);
+	    if (vctxt == NULL)
+		break;
+	    xmlSchemaValidateSimpleValue(vctxt, typeDecl,
+					 facet->value);
+	    facet->val = vctxt->value;
+	    vctxt->value = NULL;
+	    if (facet->val == NULL) {
+		/* error code */
+		if (ctxt != NULL) {
+		    xmlSchemaErrorContext(ctxt, NULL,
+			    facet->node, NULL);
+		    ctxt->error(ctxt->userData,
+		    "Schemas: type %s facet value %s invalid\n",
+				name, facet->value);
+		}
+		ret = -1;
+	    }
+	    xmlSchemaFreeValidCtxt(vctxt);
+	    break;
+	}
+	case XML_SCHEMA_FACET_ENUMERATION: {
+	    /*
+	     * Okay we need to validate the value
+	     * at that point.
+	     */
+	    xmlSchemaValidCtxtPtr vctxt;
+	    int tmp;
+
+	    vctxt = xmlSchemaNewValidCtxt(NULL);
+	    if (vctxt == NULL)
+		break;
+	    tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
+					 facet->value);
+	    if (tmp != 0) {
+		if (ctxt != NULL) {
+		    xmlSchemaErrorContext(ctxt, NULL,
+			    facet->node, NULL);
+		    ctxt->error(ctxt->userData,
+		    "Schemas: type %s enumeration value %s invalid\n",
+				name, facet->value);
+		}
+		ret = -1;
+	    }
+	    xmlSchemaFreeValidCtxt(vctxt);
+	    break;
+	}
+	case XML_SCHEMA_FACET_PATTERN:
+	    facet->regexp = xmlRegexpCompile(facet->value);
+	    if (facet->regexp == NULL) {
+		/* error code */
+		if (ctxt != NULL) {
+		    ctxt->error(ctxt->userData,
+		"Schemas: type %s facet regexp %s invalid\n",
+				name, facet->value);
+		}
+		ret = -1;
+	    }
+	    break;
+	case XML_SCHEMA_FACET_TOTALDIGITS:
+	case XML_SCHEMA_FACET_FRACTIONDIGITS:
+	case XML_SCHEMA_FACET_LENGTH:
+	case XML_SCHEMA_FACET_MAXLENGTH:
+	case XML_SCHEMA_FACET_MINLENGTH: {
+	    int tmp;
+
+	    tmp = xmlSchemaValidatePredefinedType(
+			 nonNegativeIntegerType, facet->value,
+			 &facet->val);
+	    if (tmp != 0) {
+		/* error code */
+		if (ctxt != NULL) {
+		    xmlSchemaErrorContext(ctxt, NULL,
+			    facet->node, NULL);
+		    ctxt->error(ctxt->userData,
+		    "Schemas: type %s facet value %s invalid\n",
+				name, facet->value);
+		}
+		ret = -1;
+	    }
+	    break;
+	}
+	case XML_SCHEMA_FACET_WHITESPACE: {
+	    if (xmlStrEqual(facet->value, BAD_CAST"preserve")) {
+		facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
+	    } else if (xmlStrEqual(facet->value,
+			BAD_CAST"replace")) {
+		facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
+	    } else if (xmlStrEqual(facet->value,
+			BAD_CAST"collapse")) {
+		facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
+	    } else {
+		if (ctxt != NULL) {
+		    xmlSchemaErrorContext(ctxt, NULL,
+			    facet->node, NULL);
+		    ctxt->error(ctxt->userData,
+		    "Schemas: type %s whiteSpace value %s invalid\n",
+				name, facet->value);
+		}
+		ret = -1;
+	    }
+	}
+	default:
+	    break;
+    }
+    return(ret);
+}
+
+/**
  * xmlSchemaCheckDefaults:
  * @typeDecl:  the schema type definition
  * @ctxt:  the schema parser context
@@ -3719,118 +3860,13 @@
 		   xmlSchemaParserCtxtPtr ctxt,
 		   const xmlChar *name)
 {
-    static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
     if (name == NULL)
 	name = typeDecl->name;
-    if (nonNegativeIntegerType == NULL) {
-	nonNegativeIntegerType = xmlSchemaGetPredefinedType(
-		BAD_CAST "nonNegativeInteger", xmlSchemaNs);
-    }
     if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
 	if (typeDecl->facets != NULL) {
 	    xmlSchemaFacetPtr facet = typeDecl->facets;
 	    while (facet != NULL) {
-		switch (facet->type) {
-		    case XML_SCHEMA_FACET_MININCLUSIVE:
-		    case XML_SCHEMA_FACET_MINEXCLUSIVE:
-		    case XML_SCHEMA_FACET_MAXINCLUSIVE:
-		    case XML_SCHEMA_FACET_MAXEXCLUSIVE: {
-			/*
-			 * Okay we need to validate the value
-			 * at that point.
-			 */
-			xmlSchemaValidCtxtPtr vctxt;
-
-			vctxt = xmlSchemaNewValidCtxt(NULL);
-			if (vctxt == NULL)
-			    break;
-			xmlSchemaValidateSimpleValue(vctxt, typeDecl,
-						     facet->value);
-			facet->val = vctxt->value;
-			vctxt->value = NULL;
-			if (facet->val == NULL) {
-			    /* error code */
-			    xmlSchemaErrorContext(ctxt, NULL,
-				    facet->node, NULL);
-			    ctxt->error(ctxt->userData,
-			    "Schemas: type %s facet value %s invalid\n",
-					name, facet->value);
-			}
-			xmlSchemaFreeValidCtxt(vctxt);
-			break;
-		    }
-		    case XML_SCHEMA_FACET_ENUMERATION: {
-			/*
-			 * Okay we need to validate the value
-			 * at that point.
-			 */
-			xmlSchemaValidCtxtPtr vctxt;
-			int ret;
-
-			vctxt = xmlSchemaNewValidCtxt(NULL);
-			if (vctxt == NULL)
-			    break;
-			ret = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
-						     facet->value);
-			if (ret != 0) {
-			    xmlSchemaErrorContext(ctxt, NULL,
-				    facet->node, NULL);
-			    ctxt->error(ctxt->userData,
-			    "Schemas: type %s enumeration value %s invalid\n",
-					name, facet->value);
-			}
-			xmlSchemaFreeValidCtxt(vctxt);
-			break;
-		    }
-		    case XML_SCHEMA_FACET_PATTERN:
-			facet->regexp = xmlRegexpCompile(facet->value);
-			if (facet->regexp == NULL) {
-			    /* error code */
-			    ctxt->error(ctxt->userData,
-			"Schemas: type %s facet regexp %s invalid\n",
-					name, facet->value);
-			}
-			break;
-		    case XML_SCHEMA_FACET_TOTALDIGITS:
-		    case XML_SCHEMA_FACET_FRACTIONDIGITS:
-		    case XML_SCHEMA_FACET_LENGTH:
-		    case XML_SCHEMA_FACET_MAXLENGTH:
-		    case XML_SCHEMA_FACET_MINLENGTH: {
-			int ret;
-
-			ret = xmlSchemaValidatePredefinedType(
-				     nonNegativeIntegerType, facet->value,
-				     &facet->val);
-			if (ret != 0) {
-			    /* error code */
-			    xmlSchemaErrorContext(ctxt, NULL,
-				    facet->node, NULL);
-			    ctxt->error(ctxt->userData,
-			    "Schemas: type %s facet value %s invalid\n",
-					name, facet->value);
-			}
-			break;
-		    }
-		    case XML_SCHEMA_FACET_WHITESPACE: {
-			if (xmlStrEqual(facet->value, BAD_CAST"preserve")) {
-			    facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
-			} else if (xmlStrEqual(facet->value,
-				    BAD_CAST"replace")) {
-			    facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
-			} else if (xmlStrEqual(facet->value,
-				    BAD_CAST"collapse")) {
-			    facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
-			} else {
-			    xmlSchemaErrorContext(ctxt, NULL,
-				    facet->node, NULL);
-			    ctxt->error(ctxt->userData,
-			    "Schemas: type %s whiteSpace value %s invalid\n",
-					name, facet->value);
-			}
-		    }
-		    default:
-			break;
-		}
+		xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
 		facet = facet->next;
 	    }
 	}
diff --git a/xmlschemastypes.c b/xmlschemastypes.c
index e19391f..051af8d 100644
--- a/xmlschemastypes.c
+++ b/xmlschemastypes.c
@@ -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,9 +56,33 @@
     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
 } xmlSchemaValType;
 
 unsigned long powten[10] = {
@@ -131,12 +155,9 @@
 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 xmlSchemaTypeAnyURIDef = NULL;
 
 /*
@@ -155,16 +176,27 @@
 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 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 +208,7 @@
     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);
@@ -196,45 +229,93 @@
     /*
      * 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);
 
     /*
      * 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("insignedShort",
+	    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);
+    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;
 }
 
@@ -1006,7 +1087,7 @@
 	return(0);
     } else if (type == xmlSchemaTypeAnySimpleTypeDef) {
 	return(0);
-    } else if (type == xmlSchemaTypeNmtoken) {
+    } else if (type == xmlSchemaTypeNmtokenDef) {
 	if (xmlValidateNmtokenValue(value))
 	    return(0);
 	return(1);
@@ -2036,14 +2117,14 @@
 	    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 +2134,7 @@
 	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 +2144,7 @@
 	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 +2154,7 @@
 	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,28 +2162,51 @@
 	    /* 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->value.decimal.frac != 0)) {
+		return(-1);
+	    }
+	    switch (base->flags) {
+		case XML_SCHEMAS_STRING:
+		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: {
+		    len = xmlUTF8Strlen(value);
+		    break;
+		}
+		default:
+		    TODO
+	    }
+	    if (facet->type == XML_SCHEMA_FACET_LENGTH) {
+		if (len != facet->val->value.decimal.base)
+		    return(1);
+	    } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
+		if (len < facet->val->value.decimal.base)
+		    return(1);
+	    } else {
+		if (len > facet->val->value.decimal.base)
+		    return(1);
+	    }
+	    break;
+	}
 	default:
 	    TODO
     }