Hopefully finished validation against facets to use the normalized value

* xmlschemas.c xmlschemastypes.c include/libxml/xmlschemastypes.h:
  Hopefully finished validation against facets to use the normalized
  value of both, the facets and instance values. Added
  xmlSchemaValidateLengthFacetWhtsp(), xmlSchemaValidateFacetWhtsp()
  and xmlSchemaGetValType() to the schema API.
diff --git a/ChangeLog b/ChangeLog
index c2883e6..ec79f46 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Wed Mar 16 17:20:25 CET 2005 Kasimier Buchcik <libxml2-cvs@cazic.net>
+
+	* xmlschemas.c xmlschemastypes.c include/libxml/xmlschemastypes.h:
+	  Hopefully finished validation against facets to use the normalized
+	  value of both, the facets and instance values. Added 
+	  xmlSchemaValidateLengthFacetWhtsp(), xmlSchemaValidateFacetWhtsp()
+	  and xmlSchemaGetValType() to the schema API.
+
 Wed Mar 16 13:55:31 CET 2005 Daniel Veillard <daniel@veillard.com>
 
 	* libxml.spec.in: do not package .la files
diff --git a/include/libxml/xmlschemastypes.h b/include/libxml/xmlschemastypes.h
index 05e9ebe..18014fe 100644
--- a/include/libxml/xmlschemastypes.h
+++ b/include/libxml/xmlschemastypes.h
@@ -51,15 +51,13 @@
 						 xmlSchemaFacetPtr facet,
 						 const xmlChar *value,
 						 xmlSchemaValPtr val);
-#if 0
 XMLPUBFUN int XMLCALL
 		xmlSchemaValidateFacetWhtsp	(xmlSchemaFacetPtr facet,
 						 xmlSchemaWhitespaceValueType fws,
-						 xmlSchemaValType valType,
-						 xmlSchemaValPtr val,
+						 xmlSchemaValType valType,						 
 						 const xmlChar *value,
+						 xmlSchemaValPtr val,
 						 xmlSchemaWhitespaceValueType ws);
-#endif
 XMLPUBFUN void XMLCALL		
 		xmlSchemaFreeValue		(xmlSchemaValPtr val);
 XMLPUBFUN xmlSchemaFacetPtr XMLCALL 
@@ -97,7 +95,14 @@
 						 xmlSchemaFacetPtr facet,
 						 const xmlChar *value,
 						 xmlSchemaValPtr val,
-						 unsigned long *length) ;
+						 unsigned long *length);
+XMLPUBFUN int XMLCALL
+		xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,
+						  xmlSchemaValType valType,
+						  const xmlChar *value,
+						  xmlSchemaValPtr val,						  
+						  unsigned long *length,
+						  xmlSchemaWhitespaceValueType ws);
 XMLPUBFUN int XMLCALL
 		xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, 
 						 const xmlChar *value,
@@ -120,6 +125,8 @@
 						 xmlSchemaWhitespaceValueType yws);
 XMLPUBFUN xmlSchemaValPtr XMLCALL
 		xmlSchemaCopyValue		(xmlSchemaValPtr val);
+XMLPUBFUN xmlSchemaValType XMLCALL
+		xmlSchemaGetValType		(xmlSchemaValPtr val);
 
 #ifdef __cplusplus
 }
diff --git a/xmlschemas.c b/xmlschemas.c
index 41add1c..3835ada 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -562,6 +562,15 @@
                        xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
 static void
 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
+static int
+xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
+		       xmlSchemaTypePtr type,
+		       const xmlChar *value,
+		       xmlSchemaValPtr *val);
+static xmlSchemaTypePtr
+xmlSchemaGetSimpleContentType(xmlSchemaTypePtr complexType);
+static int
+xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
 
 /************************************************************************
  *									*
@@ -1192,6 +1201,56 @@
 }
 
 /**
+ * xmlSchemaGetCanonValueWhtsp:
+ * @val: the precomputed value
+ * @retValue: the returned value
+ * @ws: the whitespace type of the value
+ *
+ * Get a the cononical representation of the value.
+ * The caller has to free the returned retValue.
+ *
+ * Returns 0 if the value could be built and -1 in case of
+ *         API errors or if the value type is not supported yet.
+ */
+static int
+xmlSchemaGetCanonValueWhtsp(const xmlChar *value,
+			    xmlSchemaValPtr val,
+			    xmlSchemaWhitespaceValueType ws,
+			    const xmlChar **retValue)
+{
+    xmlSchemaValType valType;
+
+    if ((retValue == NULL) || (value == NULL) || (val == NULL))
+	return (-1);
+    *retValue = NULL;
+    valType = xmlSchemaGetValType(val);    
+    switch (valType) {
+	case XML_SCHEMAS_STRING:
+	    if (value == NULL)
+		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
+	    else
+		*retValue = 
+		    BAD_CAST xmlStrdup(value);
+	    break;
+	case XML_SCHEMAS_NORMSTRING:
+	    if (value == NULL)
+		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
+	    else {
+		if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
+		    *retValue = xmlSchemaCollapseString(value);
+		else
+		    *retValue = xmlSchemaWhiteSpaceReplace(value);
+		if ((*retValue) == NULL)
+		    *retValue = BAD_CAST xmlStrdup(value);
+	    }
+	    break;
+	default:
+	    return (xmlSchemaGetCanonValue(val, retValue));
+    }    
+    return (0);
+}
+
+/**
  * xmlSchemaFormatFacetEnumSet:
  * @buf: the string buffer
  * @type: the type holding the enumeration facets
@@ -1203,11 +1262,61 @@
 static const xmlChar *
 xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
 {
-    xmlSchemaFacetLinkPtr link;
+    xmlSchemaFacetPtr facet;
+    xmlSchemaWhitespaceValueType ws;
+    const xmlChar *value;
+    int res;
 
     if (*buf != NULL)
 	xmlFree(*buf);    
     *buf = NULL;
+
+    do {
+	/*
+	* Use the whitespace type of the base type.
+	*/
+	if (type->type == XML_SCHEMA_TYPE_COMPLEX)
+	    /* TODO: Get rid of this case. */
+	    ws = (xmlSchemaWhitespaceValueType)
+		xmlSchemaGetWhiteSpaceFacetValue(
+		xmlSchemaGetSimpleContentType(type));
+	else
+	    ws = (xmlSchemaWhitespaceValueType)
+		xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
+	for (facet = type->facets; facet != NULL; facet = facet->next) {
+	    if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
+		continue;
+	    res = xmlSchemaGetCanonValueWhtsp(facet->value, facet->val,
+		ws, &value);
+	    if (res == -1) {
+		xmlSchemaVErr(NULL, NULL,
+		    XML_SCHEMAV_INTERNAL,
+		    "Internal error: xmlSchemaFormatFacetEnumSet, failed to "
+		    "compute the canonical lexical representation.\n",
+		    NULL, NULL);
+		if (*buf != NULL)
+		    xmlFree(*buf);
+		*buf = NULL;
+		return (NULL);
+	    }
+	    if (*buf == NULL) {
+		*buf = xmlStrdup(BAD_CAST "'");
+		*buf = xmlStrcat(*buf, value);
+		*buf = xmlStrcat(*buf, BAD_CAST "'");
+	    } else {
+		*buf = xmlStrcat(*buf, BAD_CAST ", '");
+		*buf = xmlStrcat(*buf, value);
+		*buf = xmlStrcat(*buf, BAD_CAST "'");
+	    }
+	}
+	if (type->type == XML_SCHEMA_TYPE_COMPLEX)
+	    /* TODO: Get rid of this case. */
+	    type = xmlSchemaGetSimpleContentType(type);
+	else
+	    type = type->baseType;
+    } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
+
+#if 0
     for (link = type->facetSet; link != NULL; link = link->next) {
 	if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
 	    if (*buf == NULL) {
@@ -1221,6 +1330,7 @@
 	    }
 	}
     }
+#endif
     return ((const xmlChar *) *buf);
 }
 
@@ -8350,15 +8460,9 @@
 		*/
 		if (xmlStrEqual(schema->targetNamespace,
 		    include->targetNamespace)) {
-		    fprintf(stderr, "already included chameleon '%s', TNS '%s'\n",
-			include->schemaLocation,
-			include->origTargetNamespace);
 		    goto check_targetNamespace;
 		}
 	    } else {
-		fprintf(stderr, "already included '%s', TNS '%s'\n",
-		    include->schemaLocation,
-		    include->origTargetNamespace);
 		goto check_targetNamespace;
 	    }
 	}
@@ -10738,6 +10842,9 @@
 static xmlSchemaTypePtr
 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
 {
+    if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
+	(type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))
+	return (0);
     while (type != NULL) {
 	if (type->type == XML_SCHEMA_TYPE_BASIC)
 	    return (type);
@@ -10748,7 +10855,6 @@
 }
 #endif
 
-
 /**
  * xmlSchemaBuildAttributeUsesOwned:
  * @ctxt:  the schema parser context
@@ -13403,7 +13509,7 @@
 	xmlSchemaPCustomErr(ctxt,
 	    XML_SCHEMAP_INTERNAL,
 	    NULL, type, NULL,
-	    "Internal error: xmlSchemaGetContentType, "
+	    "Internal error: xmlSchemaComputeContentType, "
 	    "the complex type '%s' has no base type", type->name);
 	return (-1);
     }   
@@ -13453,7 +13559,7 @@
 			xmlSchemaPCustomErr(ctxt,
 			    XML_SCHEMAP_INTERNAL,
 			    NULL, type, NULL,
-			    "Internal error: xmlSchemaGetContentType, "
+			    "Internal error: xmlSchemaComputeContentType, "
 			    "CT '%s' (restricting): <simpleContent> has no "
 			    "<restriction>",
 			    type->name);
@@ -13465,7 +13571,7 @@
 			xmlSchemaPCustomErr(ctxt,
 			    XML_SCHEMAP_INTERNAL,
 			    NULL, type, NULL,
-			    "Internal error: xmlSchemaGetContentType, "
+			    "Internal error: xmlSchemaComputeContentType, "
 			    "CT '%s' (restricting): <restriction> has no "
 			    "mandatory <simpleType>",
 			    type->name);
@@ -13477,7 +13583,7 @@
 			xmlSchemaPCustomErr(ctxt,
 			    XML_SCHEMAP_INTERNAL,
 			    NULL, type, NULL,
-			    "Internal error: xmlSchemaGetContentType, "
+			    "Internal error: xmlSchemaComputeContentType, "
 			    "CT '%s' (restricting), the base type has no "
 			    "content type", type->name);
 			return (-1);
@@ -13494,7 +13600,7 @@
 			    xmlSchemaPCustomErr(ctxt,
 				XML_SCHEMAP_INTERNAL,
 				NULL, type, NULL,
-				"Internal error: xmlSchemaGetContentType, "
+				"Internal error: xmlSchemaComputeContentType, "
 				"CT '%s' (restricting): <simpleType> has no "
 				"<restriction>", type->name);
 			    return (-1);
@@ -13538,7 +13644,7 @@
 		    xmlSchemaPCustomErr(ctxt,
 			XML_SCHEMAP_INTERNAL,
 			NULL, type, NULL,
-			"Internal error: xmlSchemaGetContentType, "
+			"Internal error: xmlSchemaComputeContentType, "
 			"CT '%s' (extending), the base type has no content "
 			"type", type->name);
 		    return (-1);
@@ -13547,7 +13653,7 @@
 		    xmlSchemaPCustomErr(ctxt,
 			XML_SCHEMAP_INTERNAL,
 			NULL, type, NULL,
-			"Internal error: xmlSchemaGetContentType, "
+			"Internal error: xmlSchemaComputeContentType, "
 			"CT '%s' (extending), the content type of the "
 			"base is not a simple type", type->name);
 		    return (-1);
@@ -13568,7 +13674,7 @@
 	    xmlSchemaPCustomErr(ctxt,
 		XML_SCHEMAP_INTERNAL,
 		NULL, type, NULL,
-		"Internal error: xmlSchemaGetContentType, "
+		"Internal error: xmlSchemaComputeContentType, "
 		"'%s', the content type could not be determined", 
 		type->name);
 	    return (-1);
@@ -14179,8 +14285,9 @@
 		*/
 		/*
 		* This function is intended to deliver a compiled value
-		* on the facet. In XML Schemas the type holding a facet, 
-		* cannot be a built-in type. Thus to ensure that other API
+		* on the facet. In this implementation of XML Schemata the
+		* type holding a facet, won't be a built-in type. 
+		* Thus to ensure that other API
 		* calls (relaxng) do work, if the given type is a built-in 
 		* type, we will assume that the given built-in type *is
 		* already* the base type.		
@@ -14231,21 +14338,23 @@
 		* of the facet.
 		*/
 		ret = xmlSchemaValidateSimpleTypeValue(vctxt, base, 
-		    facet->value, 0, 1, 1, 0);
-		facet->val = vctxt->value;
-		vctxt->value = NULL;		
+		    facet->value, 0, 1, 1, 0);				
                 if (ret > 0) {
                     /* error code */
                     if (ctxt != NULL) {
-                        xmlSchemaPErrExt(ctxt, facet->node,
-			    XML_SCHEMAP_INVALID_FACET, 
-			    NULL, NULL, NULL,
-			    "Type definition '%s': The value '%s' of the "
-			    "facet '%s' is not valid.\n",
-			    name, facet->value, 
-			    xmlSchemaFacetTypeToString(facet->type), 
-			    NULL, NULL);
+			xmlChar *str = NULL;
+
+                        xmlSchemaPCustomErrExt(ctxt,
+			    XML_SCHEMAP_INVALID_FACET_VALUE,
+			    NULL, (xmlSchemaTypePtr) facet, facet->node,
+			    "The value '%s' of the facet does not validate "
+			    "against the base type '%s'",
+			    facet->value, 
+			    xmlSchemaFormatQName(&str, 
+				base->targetNamespace, base->name), NULL);
+			FREE_AND_NULL(str)
                     }
+		    /* xmlSchemaFacetTypeToString(facet->type), */
                     ret = -1;
                 } else if (ret < 0) {
 		    xmlSchemaPErrExt(ctxt, facet->node,
@@ -14258,7 +14367,30 @@
 			xmlSchemaFacetTypeToString(facet->type),
 			base->name, NULL, NULL); 
 		    ret = -1;
-		}   
+		} else {
+		    if (vctxt->value != NULL) {
+			facet->val = vctxt->value;
+			vctxt->value = NULL;
+		    } else {			
+			xmlChar *str;
+			/*
+			* Ensure computed values even for type string.
+			* TODO OPTIMIZE MEMORY: The value will be hold twice,
+			* by the facet->value and by the computed value.
+			*/
+			str = xmlStrdup(facet->value);
+			if (xmlSchemaPostCreateVal(vctxt, typeDecl,
+			    BAD_CAST str, &(facet->val)) == -1) {
+			    FREE_AND_NULL(str)
+			    xmlSchemaPErr(ctxt, typeDecl->node,
+				XML_SCHEMAP_INTERNAL,
+				"Internal error: xmlSchemaCheckFacet, "
+				"post-creating a computed value.\n",
+				NULL, NULL);
+			    /* Note that we don't return a failure yet.*/
+			}
+		    }
+		}		
 		if (reuseValCtxt == 0)
 		    xmlSchemaFreeValidCtxt(vctxt);
                 break;
@@ -14288,14 +14420,11 @@
                 if (tmp != 0) {
                     /* error code */
                     if (ctxt != NULL) {
-                        xmlSchemaPErrExt(ctxt, facet->node,
+                        xmlSchemaPCustomErr(ctxt,
 			    XML_SCHEMAP_INVALID_FACET_VALUE,
-			    NULL, NULL, NULL,
-			    "Type definition '%s': The value '%s' of the "
-			    "facet '%s' is not valid.\n",
-			    name, facet->value, 
-			    xmlSchemaFacetTypeToString(facet->type),
-			    NULL, NULL);
+			    NULL, (xmlSchemaTypePtr)  facet, facet->node,
+			    "The value '%s' of the facet is not a valid "
+			    "nonNegativeInteger", facet->value);
                     }
                     ret = -1;
                 }
@@ -14310,11 +14439,12 @@
                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
                 } else {
                     if (ctxt != NULL) {
-                        xmlSchemaPErr(ctxt, facet->node,
-			    XML_SCHEMAP_INVALID_WHITE_SPACE,
-			    "Type definition '%s': The value '%s' of the "
-			    "facet 'whiteSpace' is not valid.\n",
-			    name, facet->value);
+			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
+			xmlSchemaPCustomErr(ctxt,
+			    XML_SCHEMAP_INVALID_FACET_VALUE,
+			    NULL, (xmlSchemaTypePtr) facet, facet->node,
+			    "The value '%s' of the facet is not a valid",
+			    facet->value);
                     }
                     ret = -1;
                 }
@@ -15301,8 +15431,8 @@
 	    * by ·restriction· from it) the value of whiteSpace is fixed to 
 	    * collapse
 	    */
-	    if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
-		(anc->builtInType == XML_SCHEMAS_STRING)) {
+	    if ((anc->builtInType == XML_SCHEMAS_STRING) || 
+		(anc->builtInType == XML_SCHEMAS_NORMSTRING)) {
 		
 		lin = type->facetSet;
 		do {
@@ -15311,8 +15441,11 @@
 			break;
 		    }
 		    lin = lin->next;
-		} while (lin != NULL);	
-		break;
+		} while (lin != NULL);
+		if (anc->builtInType == XML_SCHEMAS_NORMSTRING)
+		    return (XML_SCHEMAS_FACET_REPLACE);
+		else
+		    return (XML_SCHEMAS_FACET_PRESERVE);
 	    }
 	    anc = anc->baseType;
 	} while (anc != anyST);
@@ -15345,12 +15478,24 @@
 {
     int ret = 0;
     xmlNodePtr node;
-    xmlSchemaTypePtr  biType; /* The build-in type. */
+    xmlSchemaTypePtr biType; /* The build-in type. */
     xmlSchemaTypePtr tmpType;
     xmlSchemaFacetLinkPtr facetLink;
     int retFacet;
     xmlSchemaFacetPtr facet;
     unsigned long len = 0;
+    xmlSchemaWhitespaceValueType ws;
+    
+    if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
+	xmlSchemaTypePtr tp;
+	/*
+	* TODO: Get rid of this case: the complex type still holds facets in some
+	* cases.
+	*/
+	tp = xmlSchemaGetSimpleContentType(type);
+	ws = (xmlSchemaWhitespaceValueType) xmlSchemaGetWhiteSpaceFacetValue(tp);
+    } else
+	ws = (xmlSchemaWhitespaceValueType) xmlSchemaGetWhiteSpaceFacetValue(type);
 
 #ifdef DEBUG_UNION_VALIDATION
     printf("Facets of type: '%s'\n", (const char *) type->name);
@@ -15393,15 +15538,20 @@
 		case XML_SCHEMA_FACET_MAXLENGTH: 
 		    if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
 			ret = xmlSchemaValidateListSimpleTypeFacet(facet,
-			    value, length, 0);
+			    value, length, NULL);
 			len = length;
 		    } else
-			ret = xmlSchemaValidateLengthFacet(biType, facet,
-			    value, ctxt->value, &len);
+			ret = xmlSchemaValidateLengthFacetWhtsp(facet,
+			    (xmlSchemaValType) biType->builtInType,
+			    value, ctxt->value, &len, ws);
 		    break;
 		default:
-		    ret = xmlSchemaValidateFacet(biType, facet, value, 
-			ctxt->value);
+		    ret = xmlSchemaValidateFacetWhtsp(facet, ws,
+			biType->builtInType, value, ctxt->value, ws);
+		    /*
+		    * ret = xmlSchemaValidateFacet(biType, facet, value, 
+		    *	ctxt->value);
+		    */
 	    }
 	    if (ret < 0) {
 		xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
@@ -15416,36 +15566,65 @@
 
 	    facetLink = facetLink->next;
 	}
-	if (ret >= 0) {
-	    /*
-	    * Process enumerations.
-	    */
-	    retFacet = 0;
-	    facetLink = type->facetSet;
-	    while (facetLink != NULL) {
-		if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
-		    retFacet = xmlSchemaValidateFacet(biType, facetLink->facet, 
-			value, ctxt->value);		
-		    if (retFacet <= 0)
-			break;
-		}
-		facetLink = facetLink->next;
-	    }
-	    if (retFacet > 0) {
-		ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
-		if (fireErrors)
-		    xmlSchemaVFacetErr(ctxt, ret, node,
-			value, 0, type, NULL, NULL, NULL, NULL, NULL);
-	    } else if (retFacet < 0) {
-		xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
-		    "Internal error: xmlSchemaValidateFacetsInternal, "
-		    "validating facet of type '%s'.\n",
-		    BAD_CAST "enumeration", NULL);
-		    ret = -1;		
-	    }		
-	}
+	
     }
     if (ret >= 0) {
+	xmlSchemaWhitespaceValueType fws;
+	/*
+	* Process enumerations. Facet values are in the value space
+	* of the defining type's base type. This seems to be a bug in the
+	* XML Schema 1.0 spec. For use, the normalized value is only
+	* significant for enumerations. We need to localize the base type for eatch
+	* enumeration facet, thus walk the ancestor type axis.
+	*/
+	tmpType = type;	
+	do {
+	    /*
+	    * Use the whitespace type of the base type.
+	    */
+	    if (tmpType->type == XML_SCHEMA_TYPE_COMPLEX)
+		/* TODO: Get rid of this case. */
+		fws = (xmlSchemaWhitespaceValueType)
+		    xmlSchemaGetWhiteSpaceFacetValue(
+			xmlSchemaGetSimpleContentType(tmpType));
+	    else
+		fws = (xmlSchemaWhitespaceValueType)
+		    xmlSchemaGetWhiteSpaceFacetValue(tmpType->baseType);
+	    retFacet = 0;
+	    for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
+		if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
+		    continue;		
+		retFacet = xmlSchemaValidateFacetWhtsp(facet, fws,
+		    biType->builtInType, value, ctxt->value, ws);
+		if (retFacet == 0) 
+		    break;
+		else if (retFacet < 0) {
+		    xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
+			"Internal error: xmlSchemaValidateFacetsInternal, "
+			"validating enumeration facet '%s' of type '%s'.\n",
+			facet->value, tmpType->name);
+		    ret = -1;
+		    break;
+		}
+	    }
+	    if (retFacet <= 0)
+		break;
+	    if (tmpType->type == XML_SCHEMA_TYPE_COMPLEX)
+		/* TODO: Get rid of this case. */
+		tmpType = xmlSchemaGetSimpleContentType(tmpType);
+	    else
+		tmpType = tmpType->baseType;
+	} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
+	if (retFacet > 0) {
+	    ret = XML_SCHEMAV_CVC_PATTERN_VALID;
+	    if (fireErrors) {
+		xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, NULL, 
+		    NULL, NULL, NULL, NULL);
+	    }
+	}		
+    }
+
+    if (ret >= 0) {
 	/*
 	* Process patters. Pattern facets are ORed at type level 
 	* and ANDed if derived. Walk the base type axis.
@@ -15474,8 +15653,12 @@
 		    facet = facetLink->facet;
 	    }
 	    if (retFacet != 0)
-		break;		    
-	    tmpType = tmpType->baseType;
+		break;
+	    if (tmpType->type == XML_SCHEMA_TYPE_COMPLEX)
+		/* TODO: Get rid of this case. */
+		tmpType = xmlSchemaGetSimpleContentType(tmpType);
+	    else
+		tmpType = tmpType->baseType;
 	} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
 	if (retFacet > 0) {
 	    ret = XML_SCHEMAV_CVC_PATTERN_VALID;
@@ -16179,6 +16362,34 @@
     return (ret);
 }
 
+static xmlSchemaTypePtr
+xmlSchemaGetSimpleContentType(xmlSchemaTypePtr complexType)
+{
+    xmlSchemaTypePtr ret;
+
+    if (complexType->type != XML_SCHEMA_TYPE_COMPLEX)
+	return (NULL);
+    if (complexType->contentTypeDef != NULL)
+	return (complexType->contentTypeDef);
+    /*
+    * TODO: This is only a workaround until the simple content
+    * type is computed for complex types with simple content.
+    */
+    ret = complexType->baseType;
+    while (ret != NULL) {
+	if (IS_SIMPLE_TYPE(ret))
+	    return (ret);
+	if (ret->builtInType == XML_SCHEMAS_ANYTYPE)
+	    return (NULL);
+	if ((ret->type == XML_SCHEMA_TYPE_COMPLEX) &&
+	    (ret->contentTypeDef != NULL))
+	    ret = ret->contentTypeDef;
+	else
+	    ret = ret->baseType;
+    }
+    return (ret);
+}
+
 /**
  * xmlSchemaValidateSimpleTypeValue:
  * @ctxt:  a schema validation context
@@ -16289,18 +16500,20 @@
     }
 
     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
-	xmlSchemaTypePtr base, anyType;
+	xmlSchemaTypePtr simpType, anyType;
 
 	anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
 
-	base = type->baseType;
-	while ((base != NULL) && 
-	    (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
-	    (base->type != XML_SCHEMA_TYPE_BASIC) &&
-	    (base != anyType)) {
-	    base = base->baseType;
+	simpType = xmlSchemaGetSimpleContentType(type);
+	if (simpType == NULL) {
+	    xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
+		"Internal error: xmlSchemaValidateSimpleTypeValue, "
+		"failed to obtain the simple content type of the complex "
+		"type '%s'\n",
+		type->name, NULL);
+	    return (-1);
 	}
-	ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
+	ret = xmlSchemaValidateSimpleTypeValue(ctxt, simpType, value, 1, 0, 1, 0);
 	if (ret < 0) {
 	    xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
 		"Internal error: xmlSchemaValidateSimpleTypeValue, "
@@ -16309,15 +16522,14 @@
 	} else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
 	    /* 
 	    * Check facets.
-	    */	    
-	    /*
-	    * This is somehow not nice, since if an error occurs
+	    *
+	    * TODO: This is somehow not nice, since if an error occurs
 	    * the reported type will be the complex type; the spec
 	    * wants a simple type to be created on the complex type
 	    * if it has a simple content. For now we have to live with
 	    * it.
-	    */
-	    ret = xmlSchemaValidateFacetsInternal(ctxt, type, 
+	    */	    
+	    ret = xmlSchemaValidateFacetsInternal(ctxt, type,		
 		value, 0, fireErrors);
 	    if (ret < 0) {
 		xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
@@ -16393,8 +16605,8 @@
 	} else if ((applyFacets) && (type->facetSet != NULL)) {
 	    /* 
 	    * Check facets.
-	    */	    	    	    
-	    ret = xmlSchemaValidateFacetsInternal(ctxt, type, 
+	    */	    	   	    
+	    ret = xmlSchemaValidateFacetsInternal(ctxt, type,
 		value, 0, fireErrors);
 	    if (ret < 0) {
 		xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
@@ -16461,7 +16673,7 @@
 		"validating list simple type '%s'\n",
 		type->name, NULL);
 	} else if ((ret == 0) && (applyFacets)) {
-	    ret = xmlSchemaValidateFacetsInternal(ctxt, type, 
+	    ret = xmlSchemaValidateFacetsInternal(ctxt, type,
 		value, len, fireErrors);
 	    if (ret < 0) {
 		xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
@@ -16555,7 +16767,7 @@
 		    value = (const xmlChar *) normValue;
 	    }
 
-	    ret = xmlSchemaValidateFacetsInternal(ctxt, type, 
+	    ret = xmlSchemaValidateFacetsInternal(ctxt, type,
 		value, 0, fireErrors);
 	    if (ret < 0) {
 		xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
@@ -19539,7 +19751,12 @@
 		    ctxt->type = oldtype;
 		    return (-1);
 		}
-	    }	    
+	    }
+#if 0
+	    /* 
+	    * REMOVED since handled by xmlSchemaValidateSimpleTypeValue
+	    * already. 
+	    */
 	    if (ret == 0) {
 		/* 
 		* Apply facets of the complexType. Be sure to pass the 
@@ -19571,6 +19788,7 @@
 		    return (-1);
 		}
 	    }
+#endif
 	    if (value != NULL)
 		xmlFree(value);
 
@@ -19660,13 +19878,14 @@
 
 static int
 xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
+		       xmlSchemaTypePtr type,
 		       const xmlChar *value,
 		       xmlSchemaValPtr *val)
 {
     xmlSchemaTypePtr prim;
 
     if (val == NULL) {
-	xmlSchemaVErr(vctxt, vctxt->nodeInfo->node, 
+	xmlSchemaVErr(vctxt, NULL, 
 	    XML_SCHEMAV_INTERNAL,
 	    "Internal error: xmlSchemaPostCreateVal, "
 	    "bad arguments", NULL, NULL);
@@ -19675,13 +19894,10 @@
     /*
     * Only string or anySimpleType values are expected to be post-created.
     */
-    prim = xmlSchemaGetPrimitiveType(vctxt->nodeInfo->typeDef);
+    prim = xmlSchemaGetPrimitiveType(type);
     if ((prim->builtInType == XML_SCHEMAS_STRING) || 
 	(prim->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
     {
-#if 0
-	builtIn = xmlSchemaGetBuiltInTypeAncestor(vctxt->nodeInfo->typeDef);
-#endif
 	if (value == NULL)
 	    /* TODO: Can this happen at all? */
 	    *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
@@ -19689,7 +19905,7 @@
 	else
 	    *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING, value);
 	if ((*val) == NULL) {
-	    xmlSchemaVErr(vctxt, vctxt->nodeInfo->node, 
+	    xmlSchemaVErr(vctxt, NULL, 
 		XML_SCHEMAV_INTERNAL,
 		"Internal error: xmlSchemaPostCreateVal, "
 		"failed to create the value", NULL, NULL);
@@ -19697,7 +19913,7 @@
 	}
 	return (0);
     }
-    xmlSchemaVErr(vctxt, vctxt->nodeInfo->node, 
+    xmlSchemaVErr(vctxt, NULL, 
 	XML_SCHEMAV_INTERNAL,
 	"Internal error: xmlSchemaPostCreateVal, "
 	"the given type is not supported", NULL, NULL);
@@ -19771,7 +19987,8 @@
 		/*
 		* Post-create the value.
 		*/
-		if (xmlSchemaPostCreateVal(vctxt, value, &(vctxt->value)) == -1) {
+		if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
+		    value, &(vctxt->value)) == -1) {
 		    ret = -1;
 		    goto exit;
 		}
@@ -19787,7 +20004,8 @@
 		    str = xmlStrdup(BAD_CAST "");
 		else
 		    str = xmlStrdup(defValue);
-		if (xmlSchemaPostCreateVal(vctxt, str, &defVal) == -1) {
+		if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
+		    str, &defVal) == -1) {
 		    ret = -1;
 		    FREE_AND_NULL(str)
 		    goto exit;
@@ -20296,6 +20514,7 @@
 			xmlChar *str = xmlStrdup(attrDecl->defValue);
 
 			if (xmlSchemaPostCreateVal(ctxt,
+			    ctxt->attrInfo->typeDef,
 			    str,
 			    &(attrDecl->defVal)) == -1) {
 			    FREE_AND_NULL(str)
diff --git a/xmlschemastypes.c b/xmlschemastypes.c
index e6d2b9a..230928a 100644
--- a/xmlschemastypes.c
+++ b/xmlschemastypes.c
@@ -50,6 +50,8 @@
 
 #define IS_WSP_SPACE_CH(c)	((c) == 0x20)
 
+#define IS_WSP_BLANK_CH(c) IS_BLANK_CH(c)
+
 /* Date value */
 typedef struct _xmlSchemaValDate xmlSchemaValDate;
 typedef xmlSchemaValDate *xmlSchemaValDatePtr;
@@ -1766,33 +1768,33 @@
  */
 static int
 xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo,
-	           unsigned long *lmi, unsigned long *lhi) {
+                   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') {	/* ignore leading zeroes */
-	cur++;
+    while (*cur == '0') {        /* ignore leading zeroes */
+        cur++;
     }
     tmp = cur;
     while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) {
-	i++;tmp++;ret++;
+        i++;tmp++;ret++;
     }
     if (i > 24) {
-	*str = tmp;
-	return(-1);
+        *str = tmp;
+        return(-1);
     }
     while (i > 16) {
-	hi = hi * 10 + (*cur++ - '0');
-	i--;
+        hi = hi * 10 + (*cur++ - '0');
+        i--;
     }
     while (i > 8) {
-	mi = mi * 10 + (*cur++ - '0');
-	i--;
+        mi = mi * 10 + (*cur++ - '0');
+        i--;
     }
     while (i > 0) {
-	lo = lo * 10 + (*cur++ - '0');
-	i--;
+        lo = lo * 10 + (*cur++ - '0');
+        i--;
     }
 
     *str = cur;
@@ -1923,6 +1925,7 @@
 		}
 		if (*cur != 0)
 		    goto return1;	/* error if any extraneous chars */
+
                 if (val != NULL) {
                     v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
                     if (v != NULL) {
@@ -2687,7 +2690,7 @@
         case XML_SCHEMAS_BYTE:
         case XML_SCHEMAS_SHORT:
         case XML_SCHEMAS_INT:{
-                const xmlChar *cur = value;
+                 const xmlChar *cur = value;
                 unsigned long lo, mi, hi;
                 int sign = 0;
 
@@ -3687,8 +3690,8 @@
 
 /**
  * xmlSchemaComparePreserveReplaceStrings:
- * @xv:  a first string value
- * @yv:  a second string value
+ * @x:  a first string value
+ * @y:  a second string value
  * @invert: inverts the result if x < y or x > y.
  *
  * Compare 2 string for their normalized values.
@@ -3700,16 +3703,16 @@
  * case of error
  */
 static int
-xmlSchemaComparePreserveReplaceStrings(const xmlChar *xv,
-				       const xmlChar *yv,
+xmlSchemaComparePreserveReplaceStrings(const xmlChar *x,
+				       const xmlChar *y,
 				       int invert)
 {
     int tmp;
     
-    while ((*xv != 0) && (*yv != 0)) {
-	if (IS_WSP_REPLACE_CH(*yv)) {
-	    if (! IS_WSP_SPACE_CH(*xv)) {
-		if ((*xv - 0x20) < 0) {
+    while ((*x != 0) && (*y != 0)) {
+	if (IS_WSP_REPLACE_CH(*y)) {
+	    if (! IS_WSP_SPACE_CH(*x)) {
+		if ((*x - 0x20) < 0) {
 		    if (invert)
 			return(1);
 		    else
@@ -3722,7 +3725,7 @@
 		}
 	    }	    
 	} else {
-	    tmp = *xv - *yv;
+	    tmp = *x - *y;
 	    if (tmp < 0) {
 		if (invert)
 		    return(1);
@@ -3736,16 +3739,16 @@
 		    return(1);
 	    }
 	}
-	xv++;
-	yv++;
+	x++;
+	y++;
     }
-    if (*xv != 0) {
+    if (*x != 0) {
 	if (invert)
 	    return(-1);
 	else
 	    return(1);
     }
-    if (*yv != 0) {
+    if (*y != 0) {
 	if (invert)
 	    return(1);
 	else
@@ -3768,8 +3771,8 @@
  * case of error
  */
 static int
-xmlSchemaComparePreserveCollapseStrings(const xmlChar *xv,
-				        const xmlChar *yv,
+xmlSchemaComparePreserveCollapseStrings(const xmlChar *x,
+				        const xmlChar *y,
 					int invert)
 {
     int tmp;
@@ -3777,16 +3780,16 @@
     /* 
     * Skip leading blank chars of the collapsed string.
     */
-    while (IS_WSP_SPACE_CH(*yv) || IS_WSP_REPLACE_CH(*yv))
-	yv++;
+    while IS_WSP_BLANK_CH(*y)
+	y++;
 
-    while ((*xv != 0) && (*yv != 0)) {
-	if (IS_WSP_SPACE_CH(*yv) || IS_WSP_REPLACE_CH(*yv)) {
-	    if (! IS_WSP_SPACE_CH(*xv)) {
+    while ((*x != 0) && (*y != 0)) {
+	if IS_WSP_BLANK_CH(*y) {
+	    if (! IS_WSP_SPACE_CH(*x)) {
 		/*
-		* The utf2 character would have been replaced to 0x20.
+		* The yv character would have been replaced to 0x20.
 		*/
-		if ((*xv - 0x20) < 0) {
+		if ((*x - 0x20) < 0) {
 		    if (invert)
 			return(1);
 		    else
@@ -3798,15 +3801,15 @@
 			return(1);
 		}
 	    }
-	    xv++;
-	    yv++;
+	    x++;
+	    y++;
 	    /*
 	    * Skip contiguous blank chars of the collapsed string.
 	    */
-	    while (IS_WSP_SPACE_CH(*yv) || IS_WSP_REPLACE_CH(*yv))
-		yv++;
+	    while IS_WSP_BLANK_CH(*y)
+		y++;
 	} else {
-	    tmp = *xv++ - *yv++;
+	    tmp = *x++ - *y++;
 	    if (tmp < 0) {
 		if (invert)
 		    return(1);
@@ -3821,19 +3824,19 @@
 	    }
 	}
     }
-    if (*xv != 0) {
+    if (*x != 0) {
 	 if (invert)
 	     return(-1);
 	 else
 	     return(1);
     }
-    if (*yv != 0) {
+    if (*y != 0) {
 	/*
 	* Skip trailing blank chars of the collapsed string.
 	*/
-	while (IS_WSP_SPACE_CH(*yv) || IS_WSP_REPLACE_CH(*yv))
-	    yv++;
-	if (*yv != 0) {
+	while IS_WSP_BLANK_CH(*y)
+	    y++;
+	if (*y != 0) {
 	    if (invert)
 		return(1);
 	    else
@@ -3857,8 +3860,8 @@
  * case of error
  */
 static int
-xmlSchemaCompareReplaceCollapseStrings(const xmlChar *xv,
-				       const xmlChar *yv,
+xmlSchemaCompareReplaceCollapseStrings(const xmlChar *x,
+				       const xmlChar *y,
 				       int invert)
 {
     int tmp;
@@ -3866,16 +3869,16 @@
     /* 
     * Skip leading blank chars of the collapsed string.
     */
-    while (IS_WSP_SPACE_CH(*yv) || IS_WSP_REPLACE_CH(*yv))
-	yv++;
+    while IS_WSP_BLANK_CH(*y)
+	y++;
     
-    while ((*xv != 0) && (*yv != 0)) {
-	if (IS_WSP_SPACE_CH(*yv) || IS_WSP_REPLACE_CH(*yv)) {
-	    if (! (IS_WSP_SPACE_CH(*xv) || IS_WSP_REPLACE_CH(*xv))) {
+    while ((*x != 0) && (*y != 0)) {
+	if IS_WSP_BLANK_CH(*y) {
+	    if (! IS_WSP_BLANK_CH(*x)) {
 		/*
-		* The utf2 character would have been replaced to 0x20.
+		* The yv character would have been replaced to 0x20.
 		*/
-		if ((*xv - 0x20) < 0) {
+		if ((*x - 0x20) < 0) {
 		    if (invert)
 			return(1);
 		    else
@@ -3887,19 +3890,19 @@
 			return(1);
 		}
 	    }
-	    xv++;
-	    yv++;	    
+	    x++;
+	    y++;	    
 	    /* 
 	    * Skip contiguous blank chars of the collapsed string.
 	    */
-	    while (IS_WSP_SPACE_CH(*yv) || IS_WSP_REPLACE_CH(*yv))
-		yv++;
+	    while IS_WSP_BLANK_CH(*y)
+		y++;
 	} else {
-	    if (IS_WSP_SPACE_CH(*xv) || IS_WSP_REPLACE_CH(*xv)) {
+	    if IS_WSP_BLANK_CH(*x) {
 		/*
-		* The utf1 character would have been replaced to 0x20.
+		* The xv character would have been replaced to 0x20.
 		*/
-		if ((0x20 - *yv) < 0) {
+		if ((0x20 - *y) < 0) {
 		    if (invert)
 			return(1);
 		    else
@@ -3911,26 +3914,26 @@
 			return(1);
 		}
 	    }
-	    tmp = *xv++ - *yv++;
+	    tmp = *x++ - *y++;
 	    if (tmp < 0)
 		return(-1);
 	    if (tmp > 0)
 		return(1);
 	}
     }
-    if (*xv != 0) {
+    if (*x != 0) {
 	 if (invert)
 	     return(-1);
 	 else
 	     return(1);
     }   
-    if (*yv != 0) {
+    if (*y != 0) {
 	/*
 	* Skip trailing blank chars of the collapsed string.
 	*/
-	while (IS_WSP_SPACE_CH(*yv) || IS_WSP_REPLACE_CH(*yv))
-	    yv++;
-	if (*yv != 0) {
+	while IS_WSP_BLANK_CH(*y)
+	    y++;
+	if (*y != 0) {
 	    if (invert)
 		return(1);
 	    else
@@ -3952,38 +3955,38 @@
  * case of error
  */
 static int
-xmlSchemaCompareReplacedStrings(const xmlChar *xv,
-				const xmlChar *yv)
+xmlSchemaCompareReplacedStrings(const xmlChar *x,
+				const xmlChar *y)
 {
     int tmp;
    
-    while ((*xv != 0) && (*yv != 0)) {
-	if (IS_WSP_SPACE_CH(*yv) || IS_WSP_REPLACE_CH(*yv)) {
-	    if (! (IS_WSP_SPACE_CH(*xv) || IS_WSP_REPLACE_CH(*xv))) {
-		if ((*xv - 0x20) < 0)
+    while ((*x != 0) && (*y != 0)) {
+	if IS_WSP_BLANK_CH(*y) {
+	    if (! IS_WSP_BLANK_CH(*x)) {
+		if ((*x - 0x20) < 0)
     		    return(-1);
 		else
 		    return(1);
 	    }	    
 	} else {
-	    if (IS_WSP_SPACE_CH(*xv) || IS_WSP_REPLACE_CH(*xv)) {
-		if ((0x20 - *yv) < 0)
+	    if IS_WSP_BLANK_CH(*x) {
+		if ((0x20 - *y) < 0)
     		    return(-1);
 		else
 		    return(1);
 	    }
-	    tmp = *xv - *yv;
+	    tmp = *x - *y;
 	    if (tmp < 0)
     		return(-1);
 	    if (tmp > 0)
     		return(1);
 	}
-	xv++;
-	yv++;
+	x++;
+	y++;
     }
-    if (*xv != 0)
+    if (*x != 0)
         return(1);
-    if (*yv != 0)
+    if (*y != 0)
         return(-1);
     return(0);
 }
@@ -3999,36 +4002,36 @@
  * case of error
  */
 static int
-xmlSchemaCompareNormStrings(const xmlChar *xv,
-			    const xmlChar *yv) {
+xmlSchemaCompareNormStrings(const xmlChar *x,
+			    const xmlChar *y) {
     int tmp;
     
-    while (IS_BLANK_CH(*xv)) xv++;
-    while (IS_BLANK_CH(*yv)) yv++;
-    while ((*xv != 0) && (*yv != 0)) {
-	if (IS_BLANK_CH(*xv)) {
-	    if (!IS_BLANK_CH(*yv)) {
-		tmp = *xv - *yv;
+    while (IS_BLANK_CH(*x)) x++;
+    while (IS_BLANK_CH(*y)) y++;
+    while ((*x != 0) && (*y != 0)) {
+	if (IS_BLANK_CH(*x)) {
+	    if (!IS_BLANK_CH(*y)) {
+		tmp = *x - *y;
 		return(tmp);
 	    }
-	    while (IS_BLANK_CH(*xv)) xv++;
-	    while (IS_BLANK_CH(*yv)) yv++;
+	    while (IS_BLANK_CH(*x)) x++;
+	    while (IS_BLANK_CH(*y)) y++;
 	} else {
-	    tmp = *xv++ - *yv++;
+	    tmp = *x++ - *y++;
 	    if (tmp < 0)
 		return(-1);
 	    if (tmp > 0)
 		return(1);
 	}
     }
-    if (*xv != 0) {
-	while (IS_BLANK_CH(*xv)) xv++;
-	if (*xv != 0)
+    if (*x != 0) {
+	while (IS_BLANK_CH(*x)) x++;
+	if (*x != 0)
 	    return(1);
     }
-    if (*yv != 0) {
-	while (IS_BLANK_CH(*yv)) yv++;
-	if (*yv != 0)
+    if (*y != 0) {
+	while (IS_BLANK_CH(*y)) y++;
+	if (*y != 0)
 	    return(-1);
     }
     return(0);
@@ -4129,10 +4132,8 @@
 			       xmlSchemaValType ytype,
 			       xmlSchemaValPtr y,
 			       const xmlChar *yvalue,
-			       xmlSchemaWhitespaceValueType yws) {
-    if ((x == NULL) || (y == NULL))
-	return(-2);
-
+			       xmlSchemaWhitespaceValueType yws)
+{
     switch (xtype) {
 	case XML_SCHEMAS_UNKNOWN:
 	case XML_SCHEMAS_ANYTYPE:
@@ -4174,7 +4175,7 @@
         case XML_SCHEMAS_DURATION:
 	    if ((x == NULL) || (y == NULL))
 		return(-2);
-	    if (y->type == XML_SCHEMAS_DURATION)
+	    if (ytype == XML_SCHEMAS_DURATION)
                 return(xmlSchemaCompareDurations(x, y));
             return(-2);
         case XML_SCHEMAS_TIME:
@@ -4409,8 +4410,6 @@
 			    xmlSchemaValPtr y,
 			    xmlSchemaWhitespaceValueType yws)
 {
-    if ((x == NULL) || (y == NULL))
-        return(-2);
     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
 	y, NULL, yws));
 }
@@ -4532,19 +4531,19 @@
     */
     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
 	if (actualLen != facet->val->value.decimal.lo) {
-	    if (expectedLen != 0)
+	    if (expectedLen != NULL)
 		*expectedLen = facet->val->value.decimal.lo;
 	    return (XML_SCHEMAV_CVC_LENGTH_VALID);
 	}	
     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
 	if (actualLen < facet->val->value.decimal.lo) {
-	    if (expectedLen != 0)
+	    if (expectedLen != NULL)
 		*expectedLen = facet->val->value.decimal.lo;
 	    return (XML_SCHEMAV_CVC_MINLENGTH_VALID);
 	}
     } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) {
 	if (actualLen > facet->val->value.decimal.lo) {
-	    if (expectedLen != 0)
+	    if (expectedLen != NULL)
 		*expectedLen = facet->val->value.decimal.lo;
 	    return (XML_SCHEMAV_CVC_MAXLENGTH_VALID);
 	}
@@ -4564,6 +4563,114 @@
  * @facet:  the facet to check
  * @value:  the lexical repr. of the value to be validated
  * @val:  the precomputed value
+ * @ws: the whitespace type of the value
+ * @length: the actual length of the value
+ *
+ * Checka a value against a "length", "minLength" and "maxLength" 
+ * facet; sets @length to the computed length of @value.
+ *
+ * Returns 0 if the value is valid, a positive error code
+ * otherwise and -1 in case of an internal or API error.
+ */
+static int
+xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,
+				     xmlSchemaTypeType valType,
+				     const xmlChar *value,
+				     xmlSchemaValPtr val,				     
+				     unsigned long *length,
+				     xmlSchemaWhitespaceValueType ws)  
+{
+    unsigned int len = 0;
+
+    if ((length == NULL) || (facet == NULL))
+        return (-1);
+    *length = 0;
+    if ((facet->type != XML_SCHEMA_FACET_LENGTH) &&
+	(facet->type != XML_SCHEMA_FACET_MAXLENGTH) &&
+	(facet->type != XML_SCHEMA_FACET_MINLENGTH))
+	return (-1);
+	
+    /*
+    * TODO: length, maxLength and minLength must be of type
+    * nonNegativeInteger only. Check if decimal is used somehow.
+    */
+    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 if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
+	len = val->value.base64.total;
+    else {
+	switch (valType) {
+	    case XML_SCHEMAS_STRING:
+	    case XML_SCHEMAS_NORMSTRING:
+		if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
+		    /*
+		    * This is to ensure API compatibility with the old
+		    * xmlSchemaValidateLengthFacet(). Anyway, this was and
+		    * is not the correct handling.
+		    * TODO: Get rid of this case somehow.
+		    */
+		    if (valType == XML_SCHEMAS_STRING)
+			len = xmlUTF8Strlen(value);
+		    else
+			len = xmlSchemaNormLen(value);
+		} else if (value != NULL) {
+		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
+			len = xmlSchemaNormLen(value);
+		    else
+		    /* 
+		    * Should be OK for "preserve" as well.
+		    */
+		    len = xmlUTF8Strlen(value);
+		}
+		break;
+	    case XML_SCHEMAS_IDREF:
+	    case XML_SCHEMAS_TOKEN:
+	    case XML_SCHEMAS_LANGUAGE:
+	    case XML_SCHEMAS_NMTOKEN:
+	    case XML_SCHEMAS_NAME:
+	    case XML_SCHEMAS_NCNAME:
+	    case XML_SCHEMAS_ID:
+	    /*
+	    * FIXME: What exactly to do with anyURI?
+		*/
+	    case XML_SCHEMAS_ANYURI:
+		if (value != NULL)
+		    len = xmlSchemaNormLen(value);
+		break;
+	    default:
+		TODO
+	}
+    }
+    *length = (unsigned long) len;
+    /*
+    * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi".
+    */
+    if (facet->type == XML_SCHEMA_FACET_LENGTH) {
+	if (len != facet->val->value.decimal.lo)
+	    return(XML_SCHEMAV_CVC_LENGTH_VALID);
+    } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
+	if (len < facet->val->value.decimal.lo)
+	    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
+    } else {
+	if (len > facet->val->value.decimal.lo)
+	    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
+    }
+    
+    return (0);
+}
+
+/**
+ * xmlSchemaValidateLengthFacet:
+ * @type:  the built-in type
+ * @facet:  the facet to check
+ * @value:  the lexical repr. of the value to be validated
+ * @val:  the precomputed value
  * @length: the actual length of the value
  *
  * Checka a value against a "length", "minLength" and "maxLength" 
@@ -4579,71 +4686,46 @@
 			     xmlSchemaValPtr val,
 			     unsigned long *length)  
 {
-    unsigned int len = 0;
+    return (xmlSchemaValidateLengthFacetInternal(facet,
+	type->builtInType, value, val, length,
+	XML_SCHEMA_WHITESPACE_UNKNOWN));
+}
 
-    if ((length == NULL) || (facet == NULL) || (type == NULL))
-        return (-1);
-    *length = 0;
-    if ((facet->type != XML_SCHEMA_FACET_LENGTH) &&
-	(facet->type != XML_SCHEMA_FACET_MAXLENGTH) &&
-	(facet->type != XML_SCHEMA_FACET_MINLENGTH))
-	return (-1);
-	
-    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 if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
-	len = val->value.base64.total;
-    else {
-	switch (type->builtInType) {
-	    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:
-	    /*
-	    * FIXME: What exactly to do with anyURI?
-	    */
-	    case XML_SCHEMAS_ANYURI:
-		if (value != NULL)
-		    len = xmlUTF8Strlen(value);
-		break;
-	    default:
-		TODO
-	}
-    }
-    *length = (unsigned long) len;
-    if (facet->type == XML_SCHEMA_FACET_LENGTH) {
-	if (len != facet->val->value.decimal.lo)
-	    return(XML_SCHEMAV_CVC_LENGTH_VALID);
-    } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
-	if (len < facet->val->value.decimal.lo)
-	    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
-    } else {
-	if (len > facet->val->value.decimal.lo)
-	    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
-    }
-    
-    return (0);
+/**
+ * xmlSchemaValidateLengthFacetWhtsp: 
+ * @facet:  the facet to check
+ * @valType:  the built-in type
+ * @value:  the lexical repr. of the value to be validated
+ * @val:  the precomputed value
+ * @ws: the whitespace type of the value
+ * @length: the actual length of the value
+ *
+ * Checka a value against a "length", "minLength" and "maxLength" 
+ * facet; sets @length to the computed length of @value.
+ *
+ * Returns 0 if the value is valid, a positive error code
+ * otherwise and -1 in case of an internal or API error.
+ */
+int
+xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,
+				  xmlSchemaValType valType,
+				  const xmlChar *value,
+				  xmlSchemaValPtr val,
+				  unsigned long *length,
+				  xmlSchemaWhitespaceValueType ws)
+{
+    return (xmlSchemaValidateLengthFacetInternal(facet, valType, value, val,
+	length, ws));
 }
 
 /**
  * xmlSchemaValidateFacetInternal:
- * @base:  the base type
  * @facet:  the facet to check
+ * @fws: the whitespace type of the facet's value
+ * @valType: the built-in type of the value
  * @value:  the lexical repr of the value to validate
  * @val:  the precomputed value
+ * @ws: the whitespace type of the value
  *
  * Check a value against a facet condition
  *
@@ -4653,9 +4735,9 @@
 static int
 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
 			       xmlSchemaWhitespaceValueType fws,
-			       xmlSchemaValType valType,
-			       xmlSchemaValPtr val,
+			       xmlSchemaValType valType,			       
 			       const xmlChar *value,
+			       xmlSchemaValPtr val,
 			       xmlSchemaWhitespaceValueType ws)
 {
     int ret;
@@ -4714,7 +4796,12 @@
 	    */
 	    return(0);
 	case  XML_SCHEMA_FACET_ENUMERATION:
-	    if (fws == XML_SCHEMA_WHITESPACE_UNKNOWN) {	    
+	    if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
+		/*
+		* This is to ensure API compatibility with the old
+		* xmlSchemaValidateFacet().
+		* TODO: Get rid of this case.
+		*/
 		if ((facet->value != NULL) &&
 		    (xmlStrEqual(facet->value, value)))
 		    return(0);
@@ -4732,8 +4819,11 @@
 	case XML_SCHEMA_FACET_MAXLENGTH:
 	case XML_SCHEMA_FACET_MINLENGTH: {
 	    unsigned int len = 0;
-	    /* TODO: Take the whitespace of the value into account. */
 
+	    /*
+	    * TODO: length, maxLength and minLength must be of type
+	    * nonNegativeInteger only. Check if decimal is used somehow.
+	    */
 	    if ((facet->val == NULL) ||
 		((facet->val->type != XML_SCHEMAS_DECIMAL) &&
 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
@@ -4746,24 +4836,43 @@
 		len = val->value.base64.total;
 	    else {
 		switch (valType) {
-	    	    case XML_SCHEMAS_IDREF:
-		    case XML_SCHEMAS_NORMSTRING:
+		    case XML_SCHEMAS_STRING:
+		    case XML_SCHEMAS_NORMSTRING:			
+			if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
+			    /*
+			    * This is to ensure API compatibility with the old
+			    * xmlSchemaValidateFacet(). Anyway, this was and
+			    * is not the correct handling.
+			    * TODO: Get rid of this case somehow.
+			    */
+			    if (valType == XML_SCHEMAS_STRING)
+				len = xmlUTF8Strlen(value);
+			    else
+				len = xmlSchemaNormLen(value);
+			} else if (value != NULL) {
+			    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
+				len = xmlSchemaNormLen(value);
+			    else
+				/* 
+				* Should be OK for "preserve" as well.
+				*/
+				len = xmlUTF8Strlen(value);
+			}
+			break;
+	    	    case XML_SCHEMAS_IDREF:		    
 		    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:
 		    /*
 		    * FIXME: What exactly to do with anyURI?
 		    */
 		    case XML_SCHEMAS_ANYURI:
-		        if (value != NULL)
-			    len = xmlUTF8Strlen(value);
-		    	break;
+			if (value != NULL)
+		    	    len = xmlSchemaNormLen(value);
+		    	break;		   
 		    default:
 		        TODO
 	    	}
@@ -4835,7 +4944,7 @@
  *     number otherwise and -1 in case of internal or API error.
  */
 int
-xmlSchemaValidateFacet(xmlSchemaTypePtr base,
+xmlSchemaValidateFacet(xmlSchemaTypePtr base ATTRIBUTE_UNUSED,
 	               xmlSchemaFacetPtr facet,
 	               const xmlChar *value,
 		       xmlSchemaValPtr val)
@@ -4845,16 +4954,14 @@
     * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and
     * xmlSchemaValidateFacetWhtsp().
     */
-    if (val != NULL) {
+    if (base != NULL)
 	return(xmlSchemaValidateFacetInternal(facet,
-	    XML_SCHEMA_WHITESPACE_UNKNOWN, val->type, val, value,
+	    XML_SCHEMA_WHITESPACE_UNKNOWN, base->builtInType, value, val, 
 	    XML_SCHEMA_WHITESPACE_UNKNOWN));
-    } else if (base != NULL) {
+    else
 	return(xmlSchemaValidateFacetInternal(facet,
-	    XML_SCHEMA_WHITESPACE_UNKNOWN, base->builtInType, val, value,
-	    XML_SCHEMA_WHITESPACE_UNKNOWN));	
-    }
-    return(-1);
+	    XML_SCHEMA_WHITESPACE_UNKNOWN, XML_SCHEMAS_UNKNOWN, value, val, 
+	    XML_SCHEMA_WHITESPACE_UNKNOWN));
 }
 
 /**
@@ -4874,30 +4981,30 @@
  * Returns 0 if the element is schemas valid, a positive error code
  *     number otherwise and -1 in case of internal or API error.
  */
-#if 0
 int
 xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet,
 			    xmlSchemaWhitespaceValueType fws,
-			    xmlSchemaValType valType,
-			    xmlSchemaValPtr val,
+			    xmlSchemaValType valType,			    
 			    const xmlChar *value,
+			    xmlSchemaValPtr val,
 			    xmlSchemaWhitespaceValueType ws)
 {
      return(xmlSchemaValidateFacetInternal(facet, fws, valType,
-	 val, value, ws));
+	 value, val, ws));
 }
-#endif
 
 /**
  * xmlSchemaGetCanonValue:
  * @val: the precomputed value
  * @retValue: the returned value
  *
- * Get a the cononical representation of the value.
+ * Get a the cononical lexical representation of the value.
  * The caller has to free the returned retValue.
+ * WARNING: Some value types are not supported yet, resulting
+ * in a @retValue of "???".
  *
  * Returns 0 if the value could be built and -1 in case of
- *         API errors or if the value type is not supported yet.
+ *         API errors.
  */
 int
 xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue)
@@ -4906,32 +5013,66 @@
 	return (-1);
     *retValue = NULL;
     switch (val->type) {
-	case XML_SCHEMAS_STRING:	
+	case XML_SCHEMAS_STRING:
+	    if (val->value.str == NULL)
+		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
+	    else
+		*retValue = 
+		    BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
+	    break;
 	case XML_SCHEMAS_NORMSTRING:
-	/*
+	    if (val->value.str == NULL)
+		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
+	    else {
+		*retValue = xmlSchemaWhiteSpaceReplace(
+		    (const xmlChar *) val->value.str);
+		if ((*retValue) == NULL)
+		    *retValue = BAD_CAST xmlStrdup(
+			(const xmlChar *) val->value.str);
+	    }
+	    break;
 	case XML_SCHEMAS_TOKEN:
 	case XML_SCHEMAS_LANGUAGE:
 	case XML_SCHEMAS_NMTOKEN:
-	case XML_SCHEMAS_NAME:
-	case XML_SCHEMAS_QNAME:
+	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:
-	*/
+	case XML_SCHEMAS_ANYURI:	
 	    if (val->value.str == NULL)
-		*retValue = NULL;
-	    else
-		/* TODO: This is not yet correct for non-normalized values. */
-		*retValue = 
-		    BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
-	    return (0);
+		return (-1);
+	    *retValue = BAD_CAST xmlSchemaCollapseString(BAD_CAST val->value.str);
+	    break;
+	case XML_SCHEMAS_QNAME:
+	    /*
+	    * TODO: What exactly to do with QNames?
+	    */
+	    if (val->value.qname.uri == NULL) {
+		*retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.qname.name);
+		return (0);
+	    } else {
+		*retValue = BAD_CAST xmlStrdup(BAD_CAST "{");
+		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
+		    BAD_CAST val->value.qname.uri);
+		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
+		    BAD_CAST "}");
+		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
+		    BAD_CAST val->value.qname.uri);
+	    }
+	    break;
 	default:
-	    return (-1);
+	    *retValue = BAD_CAST xmlStrdup(BAD_CAST "???");
+	    break;
     }
-    return (-1);
+    return (0);
+}
+
+xmlSchemaValType
+xmlSchemaGetValType(xmlSchemaValPtr val)
+{
+    return (val->type);
 }
 
 #endif /* LIBXML_SCHEMAS_ENABLED */