Fixed comparison for default/fixed attribute values, if the type was

* xmlschemas.c: Fixed comparison for default/fixed attribute
  values, if the type was 'xsd:string'. Changed the comparison
  for IDCs to use the whitespace aware comparison function.
* xmlschemastypes.c include/libxml/xmlschemastypes.h:
  Added xmlSchemaGetCanonValue, xmlSchemaNewStringValue and
  xmlSchemaCompareValuesWhtsp to the API. Added functions
  to compare strings with whitespace combinations of "preserve",
  "replace" and "collapse".
diff --git a/ChangeLog b/ChangeLog
index e54a26a..f108bbe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Thu Feb 17 12:03:46 CET 2005 Kasimier Buchcik <libxml2-cvs@cazic.net>
+
+	* xmlschemas.c: Fixed comparison for default/fixed attribute
+	  values, if the type was 'xsd:string'. Changed the comparison
+	  for IDCs to use the whitespace aware comparison function.
+	* xmlschemastypes.c include/libxml/xmlschemastypes.h:
+	  Added xmlSchemaGetCanonValue, xmlSchemaNewStringValue and
+	  xmlSchemaCompareValuesWhtsp to the API. Added functions
+	  to compare strings with whitespace combinations of "preserve",
+	  "replace" and "collapse".
+
 Wed Feb 16 13:24:35 CET 2005 Kasimier Buchcik <libxml2-cvs@cazic.net>
 
 	* xmlschemas.c: Further work on IDCs, especially evaluation for
diff --git a/include/libxml/xmlschemastypes.h b/include/libxml/xmlschemastypes.h
index 86010c0..119604e 100644
--- a/include/libxml/xmlschemastypes.h
+++ b/include/libxml/xmlschemastypes.h
@@ -23,6 +23,13 @@
 extern "C" {
 #endif
 
+typedef enum {
+    XML_SCHEMA_WHITESPACE_UNKNOWN = 0,
+    XML_SCHEMA_WHITESPACE_PRESERVE = 1,
+    XML_SCHEMA_WHITESPACE_REPLACE = 2,
+    XML_SCHEMA_WHITESPACE_COLLAPSE = 3
+} xmlSchemaWhitespaceValueType;
+
 XMLPUBFUN void XMLCALL		
     		xmlSchemaInitTypes		(void);
 XMLPUBFUN void XMLCALL		
@@ -87,6 +94,17 @@
 						 const xmlChar *value,
 						 xmlSchemaValPtr *val, 
 						 xmlNodePtr node);
+XMLPUBFUN int XMLCALL
+		xmlSchemaGetCanonValue		(xmlSchemaValPtr val,
+						 const xmlChar **retValue);
+XMLPUBFUN xmlSchemaValPtr XMLCALL
+		xmlSchemaNewStringValue		(xmlSchemaValType type,
+						 const xmlChar *value);
+XMLPUBFUN int XMLCALL
+		xmlSchemaCompareValuesWhtsp	(xmlSchemaValPtr x,
+						 xmlSchemaWhitespaceValueType xws,
+						 xmlSchemaValPtr y,
+						 xmlSchemaWhitespaceValueType yws); 
 
 #ifdef __cplusplus
 }
diff --git a/xmlschemas.c b/xmlschemas.c
index 7aa5cbe..4852b6c 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -7,7 +7,7 @@
  * Daniel Veillard <veillard@redhat.com>
  */
 
-/*
+/* 
  * TODO:
  *   - when types are redefined in includes, check that all
  *     types in the redef list are equal
@@ -54,7 +54,7 @@
 
 #define ELEM_INFO_ENABLED 1 
 
-/* #define IDC_ENABLED 1 */
+/*  #define IDC_ENABLED 1 */
 
 /* #define IDC_VALUE_SUPPORT 1 */
 
@@ -117,9 +117,11 @@
      ((item->type == XML_SCHEMA_TYPE_BASIC) &&     \
       (item->builtInType != XML_SCHEMAS_ANYTYPE))) 
 
+/*
 #define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
 #define XML_SCHEMAS_VAL_WTSP_REPLACE  1
 #define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
+*/
 
 #define XML_SCHEMAS_PARSE_ERROR		1
 
@@ -384,9 +386,6 @@
     xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
                                          elements */
     int sizeKeySeqs;
-    xmlSchemaPSVIIDCKeyPtr **refKeySeqs;
-    int nbRefKeySeqs;
-    int sizeRefKeySeqs;
     int targetDepth;
 };
 
@@ -10268,7 +10267,7 @@
 }
 
 /**
- * xmlSchemaIsDerivedFromBuiltInType:
+ * xmlSchemaGetPrimitiveType:
  * @type:  the simpleType definition
  *
  * Returns the primitive type of the given type or
@@ -10286,6 +10285,25 @@
     return (NULL);
 }
 
+/**
+ * xmlSchemaGetBuiltInTypeAncestor:
+ * @type:  the simpleType definition
+ *
+ * Returns the primitive type of the given type or
+ * NULL in case of error.
+ */
+static xmlSchemaTypePtr
+xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
+{
+    while (type != NULL) {
+	if (type->type == XML_SCHEMA_TYPE_BASIC)
+	    return (type);
+	type = type->baseType;
+    }
+
+    return (NULL);
+}
+
 
 /**
  * xmlSchemaBuildAttributeUsesOwned:
@@ -14763,8 +14781,6 @@
     return ("Internal Error");
 }
 
-
-
 static int
 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
 {
@@ -14776,24 +14792,24 @@
     */
     if (type->type == XML_SCHEMA_TYPE_BASIC) {
 	if (type->builtInType == XML_SCHEMAS_STRING)
-	    return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
+	    return(XML_SCHEMAS_FACET_PRESERVE);
 	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
-	    return(XML_SCHEMAS_VAL_WTSP_REPLACE);
+	    return(XML_SCHEMAS_FACET_REPLACE);
 	else {
 	    /*
 	    * For all ·atomic· datatypes other than string (and types ·derived· 
 	    * by ·restriction· from it) the value of whiteSpace is fixed to 
 	    * collapse
 	    */
-	    return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
+	    return(XML_SCHEMAS_FACET_COLLAPSE);
 	}		   	    
     } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
 	/*
 	* For list types the facet "whiteSpace" is fixed to "collapse". 
 	*/
-	return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
+	return (XML_SCHEMAS_FACET_COLLAPSE);
     } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
-	return (-1);
+	return (XML_SCHEMAS_FACET_UNKNOWN);
     } else if (type->facetSet != NULL) {
 	xmlSchemaTypePtr anyST;
 	xmlSchemaFacetLinkPtr lin;
@@ -14815,14 +14831,7 @@
 		lin = type->facetSet;
 		do {
 		    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
-			if (lin->facet->whitespace == 
-			    XML_SCHEMAS_FACET_COLLAPSE) {
-			    return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);  
-			} else if (lin->facet->whitespace == 
-			    XML_SCHEMAS_FACET_REPLACE) { 
-			    return(XML_SCHEMAS_VAL_WTSP_REPLACE);
-			} else
-			    return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
+			return(lin->facet->whitespace);
 			break;
 		    }
 		    lin = lin->next;
@@ -14831,7 +14840,7 @@
 	    }
 	    anc = anc->baseType;
 	} while (anc != anyST);
-	return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);	
+	return (XML_SCHEMAS_FACET_COLLAPSE);
     }  
     return (-1);
 }
@@ -15667,11 +15676,11 @@
     * Normalize the value.
     */
     if (normalize && 
-	(ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
+	(ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
 	int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
 	
 	if ((norm != -1) && (norm > ctxt->valueWS)) {
-	    if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
+	    if (norm == XML_SCHEMAS_FACET_COLLAPSE)
 		normValue = xmlSchemaCollapseString(value);
 	    else
 		normValue = xmlSchemaWhiteSpaceReplace(value);
@@ -15992,7 +16001,7 @@
 	    }
 	    mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
 	    if (mws > ctxt->valueWS) {
-		if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
+		if (mws == XML_SCHEMAS_FACET_COLLAPSE)
 		    normValue = xmlSchemaCollapseString(value);
 		else
 		    normValue = xmlSchemaWhiteSpaceReplace(value);
@@ -16636,7 +16645,14 @@
     {	
 #ifdef IDC_VALUE_SUPPORT
 	int ret;
-	ret = xmlSchemaCompareValues(a, b);
+	int aws, bws;
+
+	aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
+	bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
+
+	ret = xmlSchemaCompareValuesWhtsp(
+	    a, (xmlSchemaWhitespaceValueType) aws,
+	    b, (xmlSchemaWhitespaceValueType) bws);
 	if (ret == 0) 
 	    return(1);
 	else if (ret == -2) {
@@ -16962,11 +16978,19 @@
 		* Failed to provide the normalized value; maby
 		* the value was invalid.
 		*/ 
-		xmlSchemaVErr(vctxt, NULL, 
+		xmlSchemaVCustomErr(vctxt,
+		    XML_SCHEMAV_CVC_IDC,
+		    vctxt->nodeInfo->node,
+		    (xmlSchemaTypePtr) sto->matcher->aidc->def,
+		    "Warning: No precomputed value available, the value "
+		    "was either invalid or something strange happend", NULL);
+		/*
+		xmlSchemaVErr(vctxt, vctxt->nodeInfo->node, 
 		    XML_SCHEMAV_INTERNAL,
 		    "Internal error: xmlSchemaXPathProcessHistory, "
 		    "computed value not available.\n",
 		    NULL, NULL);
+		*/
 		sto->nbHistory--;
 		goto deregister_check;
 	    } else {
@@ -18308,7 +18332,7 @@
 		XML_SCHEMAV_INTERNAL, 
 		elem, actualType,
 		"Internal error: xmlSchemaValidateElementByDeclaration, "
-		"validating a default value", NULL);
+		"calling validation by type", NULL);
 	    return (-1);
 	}
 	/*
@@ -19083,7 +19107,6 @@
 	return (ret);
 }
 
-
 static int
 xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
 			       xmlSchemaAttrStatePtr state)
@@ -19126,6 +19149,10 @@
 	if (xmlSchemaGetEffectiveValueConstraint(
 	    (xmlSchemaAttributePtr) ctxt->attrInfo->decl, 
 	    &fixed, &defValue, &defVal) && (fixed == 1)) {
+
+	    int ws = xmlSchemaGetWhiteSpaceFacetValue(
+		ctxt->attrInfo->typeDef);	   
+
 	    /*
 	    * cvc-au : Attribute Locally Valid (Use)
 	    * For an attribute information item to be·valid· 
@@ -19142,12 +19169,45 @@
 	    * TODO: Use the *normalized* value and the *canonical* fixed
 	    * value.
 	    */
-	    if (((ctxt->value != NULL) && 
-		(xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
-		((ctxt->value == NULL) &&
-		(! xmlStrEqual(defValue, BAD_CAST value)))) {
+	    if (ctxt->value != NULL) {
+		if (defVal == NULL) {
+		    xmlSchemaTypePtr prim;
+		    /*
+		    * Oops, the value was not computed.
+		    */
+		    prim = xmlSchemaGetPrimitiveType(ctxt->attrInfo->typeDef);
+		    if (prim->builtInType == XML_SCHEMAS_STRING) {
+			xmlSchemaTypePtr builtIn;
+			
+			builtIn = xmlSchemaGetBuiltInTypeAncestor(
+			    ctxt->attrInfo->typeDef);
+			defVal = xmlSchemaNewStringValue(
+			    builtIn->builtInType, value);			
+			((xmlSchemaAttributePtr) ctxt->attrInfo->decl)->defVal =
+			    defVal;
+			value = NULL;
+		    } else {
+			 xmlSchemaVErr(ctxt, ctxt->attrInfo->node, 
+			     XML_SCHEMAV_INTERNAL,
+			     "Internal error: xmlSchemaCheckAttrLocallyValid, "
+			     "could not aquire a precomputed vale",
+			     NULL, NULL);
+		    }
+		}
+		if (defVal != NULL) {
+		    if (xmlSchemaCompareValuesWhtsp(ctxt->value,
+			(xmlSchemaWhitespaceValueType) ws,
+			defVal, (xmlSchemaWhitespaceValueType) ws) != 0)
+		    state->state = 
+			XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
+		}
+	    } else if (! xmlStrEqual(defValue, BAD_CAST value)) {
+		/*
+		* TODO: Remove this and ensure computed values to be
+		* existent.
+		*/
 		state->state = 
-		    XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;			
+		    XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
 	    }
 	}
     }  
diff --git a/xmlschemastypes.c b/xmlschemastypes.c
index 3ff8acf..83aaa7b 100644
--- a/xmlschemastypes.c
+++ b/xmlschemastypes.c
@@ -45,6 +45,11 @@
 #define XML_SCHEMAS_NAMESPACE_NAME \
     (const xmlChar *)"http://www.w3.org/2001/XMLSchema"
 
+#define IS_WSP_REPLACE_CH(c)	((((c) == 0x9) || ((c) == 0xa)) || \
+				 ((c) == 0xd))
+
+#define IS_WSP_SPACE_CH(c)	((c) == 0x20)
+
 
 static unsigned long powten[10] = {
     1, 10, 100, 1000, 10000, 100000, 1000000, 10000000L,
@@ -677,6 +682,34 @@
 }
 
 /**
+ * xmlSchemaNewStringValue:
+ * @type:  the value type
+ *
+ * Allocate a new simple type value. The type can be 
+ * of XML_SCHEMAS_STRING.
+ *
+ * Returns a pointer to the new value or NULL in case of error
+ */
+xmlSchemaValPtr
+xmlSchemaNewStringValue(xmlSchemaValType type,
+			const xmlChar *value)
+{
+    xmlSchemaValPtr val;
+
+    if (type != XML_SCHEMAS_STRING)
+	return(NULL);
+    val = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
+    if (val == NULL) {
+	return(NULL);
+    }
+    memset(val, 0, sizeof(xmlSchemaVal));
+    val->type = type;
+    val->value.str = (xmlChar *) value;
+    return(val);
+}
+
+
+/**
  * xmlSchemaFreeValue:
  * @value:  the value to free
  *
@@ -2210,7 +2243,11 @@
         case XML_SCHEMAS_IDREF:
             ret = xmlValidateNCName(value, 1);
             if ((ret == 0) && (val != NULL)) {
-                TODO;
+		v = xmlSchemaNewValue(XML_SCHEMAS_IDREF);
+		if (v == NULL)
+		    goto error;
+		v->value.str = xmlStrdup(value);
+		*val = v;
             }
             if ((ret == 0) && (node != NULL) &&
                 (node->type == XML_ATTRIBUTE_NODE)) {
@@ -3478,6 +3515,333 @@
 }
 
 /**
+ * xmlSchemaComparePreserveReplaceStrings:
+ * @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.
+ * @x is a string with whitespace of "preserve", @y is
+ * a string with a whitespace of "replace". I.e. @x could
+ * be an "xsd:string" and @y an "xsd:normalizedString".
+ *
+ * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
+ * case of error
+ */
+static int
+xmlSchemaComparePreserveReplaceStrings(xmlSchemaValPtr x, xmlSchemaValPtr y,
+				       int invert)
+{
+    const xmlChar *utf1;
+    const xmlChar *utf2;
+    int tmp;
+
+    if ((x == NULL) || (y == NULL))
+	return(-2);
+    utf1 = x->value.str;
+    utf2 = y->value.str;
+    
+    while ((*utf1 != 0) && (*utf2 != 0)) {
+	if (IS_WSP_REPLACE_CH(*utf2)) {
+	    if (! IS_WSP_SPACE_CH(*utf1)) {
+		if ((*utf1 - 0x20) < 0) {
+		    if (invert)
+			return(1);
+		    else
+			return(-1);
+		} else {
+		    if (invert)
+			return(-1);
+		    else
+			return(1);
+		}
+	    }	    
+	} else {
+	    tmp = *utf1 - *utf2;
+	    if (tmp < 0) {
+		if (invert)
+		    return(1);
+		else
+		    return(-1);
+	    }
+	    if (tmp > 0) {
+		if (invert)
+		    return(-1);
+		else
+		    return(1);
+	    }
+	}
+	utf1++;
+	utf2++;
+    }
+    if (*utf1 != 0) {
+	if (invert)
+	    return(-1);
+	else
+	    return(1);
+    }
+    if (*utf2 != 0) {
+	if (invert)
+	    return(1);
+	else
+	    return(-1);
+    }
+    return(0);
+}
+
+/**
+ * xmlSchemaComparePreserveCollapseStrings:
+ * @x:  a first string value
+ * @y:  a second string value
+ *
+ * Compare 2 string for their normalized values.
+ * @x is a string with whitespace of "preserve", @y is
+ * a string with a whitespace of "collapse". I.e. @x could
+ * be an "xsd:string" and @y an "xsd:normalizedString".
+ *
+ * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
+ * case of error
+ */
+static int
+xmlSchemaComparePreserveCollapseStrings(xmlSchemaValPtr x, xmlSchemaValPtr y,
+					int invert)
+{
+    const xmlChar *utf1;
+    const xmlChar *utf2;
+    int tmp;
+
+    if ((x == NULL) || (y == NULL))
+	return(-2);
+    utf1 = x->value.str;
+    utf2 = y->value.str;
+
+    /* 
+    * Skip leading blank chars of the collapsed string.
+    */
+    while (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2))
+	utf2++;
+
+    while ((*utf1 != 0) && (*utf2 != 0)) {
+	if (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2)) {
+	    if (! IS_WSP_SPACE_CH(*utf1)) {
+		/*
+		* The utf2 character would have been replaced to 0x20.
+		*/
+		if ((*utf1 - 0x20) < 0) {
+		    if (invert)
+			return(1);
+		    else
+			return(-1);
+		} else {
+		    if (invert)
+			return(-1);
+		    else
+			return(1);
+		}
+	    }
+	    utf1++;
+	    utf2++;
+	    /*
+	    * Skip contiguous blank chars of the collapsed string.
+	    */
+	    while (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2))
+		utf2++;
+	} else {
+	    tmp = *utf1++ - *utf2++;
+	    if (tmp < 0) {
+		if (invert)
+		    return(1);
+		else
+		    return(-1);
+	    }
+	    if (tmp > 0) {
+		if (invert)
+		    return(-1);
+		else
+		    return(1);
+	    }
+	}
+    }
+    if (*utf1 != 0) {
+	 if (invert)
+	     return(-1);
+	 else
+	     return(1);
+    }
+    if (*utf2 != 0) {
+	/*
+	* Skip trailing blank chars of the collapsed string.
+	*/
+	while (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2))
+	    utf2++;
+	if (*utf2 != 0) {
+	    if (invert)
+		return(1);
+	    else
+		return(-1);
+	}
+    }
+    return(0);
+}
+
+/**
+ * xmlSchemaComparePreserveCollapseStrings:
+ * @x:  a first string value
+ * @y:  a second string value
+ *
+ * Compare 2 string for their normalized values.
+ * @x is a string with whitespace of "preserve", @y is
+ * a string with a whitespace of "collapse". I.e. @x could
+ * be an "xsd:string" and @y an "xsd:normalizedString".
+ *
+ * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
+ * case of error
+ */
+static int
+xmlSchemaCompareReplaceCollapseStrings(xmlSchemaValPtr x, xmlSchemaValPtr y,
+				       int invert)
+{
+    const xmlChar *utf1;
+    const xmlChar *utf2;
+    int tmp;
+
+    if ((x == NULL) || (y == NULL))
+	return(-2);
+    utf1 = x->value.str;
+    utf2 = y->value.str;
+
+    /* 
+    * Skip leading blank chars of the collapsed string.
+    */
+    while (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2))
+	utf2++;
+    
+    while ((*utf1 != 0) && (*utf2 != 0)) {
+	if (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2)) {
+	    if (! (IS_WSP_SPACE_CH(*utf1) || IS_WSP_REPLACE_CH(*utf1))) {
+		/*
+		* The utf2 character would have been replaced to 0x20.
+		*/
+		if ((*utf1 - 0x20) < 0) {
+		    if (invert)
+			return(1);
+		    else
+			return(-1);
+		} else {
+		    if (invert)
+			return(-1);
+		    else
+			return(1);
+		}
+	    }
+	    utf1++;
+	    utf2++;	    
+	    /* 
+	    * Skip contiguous blank chars of the collapsed string.
+	    */
+	    while (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2))
+		utf2++;
+	} else {
+	    if (IS_WSP_SPACE_CH(*utf1) || IS_WSP_REPLACE_CH(*utf1)) {
+		/*
+		* The utf1 character would have been replaced to 0x20.
+		*/
+		if ((0x20 - *utf2) < 0) {
+		    if (invert)
+			return(1);
+		    else
+			return(-1);
+		} else {
+		    if (invert)
+			return(-1);
+		    else
+			return(1);
+		}
+	    }
+	    tmp = *utf1++ - *utf2++;
+	    if (tmp < 0)
+		return(-1);
+	    if (tmp > 0)
+		return(1);
+	}
+    }
+    if (*utf1 != 0) {
+	 if (invert)
+	     return(-1);
+	 else
+	     return(1);
+    }   
+    if (*utf2 != 0) {
+	/*
+	* Skip trailing blank chars of the collapsed string.
+	*/
+	while (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2))
+	    utf2++;
+	if (*utf2 != 0) {
+	    if (invert)
+		return(1);
+	    else
+		return(-1);
+	}
+    }
+    return(0);
+}
+
+
+/**
+ * xmlSchemaCompareReplacedStrings:
+ * @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
+xmlSchemaCompareReplacedStrings(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 ((*utf1 != 0) && (*utf2 != 0)) {
+	if (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2)) {
+	    if (! (IS_WSP_SPACE_CH(*utf1) || IS_WSP_REPLACE_CH(*utf1))) {
+		if ((*utf1 - 0x20) < 0)
+    		    return(-1);
+		else
+		    return(1);
+	    }	    
+	} else {
+	    if (IS_WSP_SPACE_CH(*utf1) || IS_WSP_REPLACE_CH(*utf1)) {
+		if ((0x20 - *utf2) < 0)
+    		    return(-1);
+		else
+		    return(1);
+	    }
+	    tmp = *utf1 - *utf2;
+	    if (tmp < 0)
+    		return(-1);
+	    if (tmp > 0)
+    		return(1);
+	}
+	utf1++;
+	utf2++;
+    }
+    if (*utf1 != 0)
+        return(1);
+    if (*utf2 != 0)
+        return(-1);
+    return(0);
+}
+
+/**
  * xmlSchemaCompareNormStrings:
  * @x:  a first string value
  * @y:  a second string value
@@ -3605,15 +3969,20 @@
 /**
  * xmlSchemaCompareValues:
  * @x:  a first value
+ * @xwtsp: the whitespace type
  * @y:  a second value
+ * @ywtsp: the whitespace type
  *
  * 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
  */
-int
-xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
+static int
+xmlSchemaCompareValuesInternal(xmlSchemaValPtr x,
+			       xmlSchemaWhitespaceValueType xws,
+			       xmlSchemaValPtr y,
+			       xmlSchemaWhitespaceValueType yws) {
     if ((x == NULL) || (y == NULL))
 	return(-2);
 
@@ -3676,7 +4045,8 @@
                 (y->type == XML_SCHEMAS_GYEARMONTH))
                 return (xmlSchemaCompareDates(x, y));
             return (-2);
-        case XML_SCHEMAS_NORMSTRING:
+	case XML_SCHEMAS_STRING:
+        case XML_SCHEMAS_NORMSTRING:		
         case XML_SCHEMAS_TOKEN:
         case XML_SCHEMAS_LANGUAGE:
         case XML_SCHEMAS_NMTOKEN:
@@ -3687,19 +4057,60 @@
         case XML_SCHEMAS_ENTITY:
         case XML_SCHEMAS_NOTATION:
         case XML_SCHEMAS_ANYURI:
-            if ((y->type == XML_SCHEMAS_NORMSTRING) ||
+	    /*
+	    * TODO: Compare those against QName.
+	    */
+	    if (y->type == XML_SCHEMAS_QNAME) {
+		TODO
+		return (-2);
+	    }
+            if ((y->type == XML_SCHEMAS_STRING) ||
+		(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));
+                (y->type == XML_SCHEMAS_ANYURI)) {
+
+		if (xws == XML_SCHEMA_WHITESPACE_PRESERVE) {
+
+		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) {
+			/* TODO: What about x < y or x > y. */
+			if (xmlStrEqual(x->value.str, y->value.str))
+			    return (0);
+			else 
+			    return (2);
+		    } else if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
+			return (xmlSchemaComparePreserveReplaceStrings(x, y, 0));
+		    else if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
+			return (xmlSchemaComparePreserveCollapseStrings(x, y, 0));
+
+		} else if (xws == XML_SCHEMA_WHITESPACE_REPLACE) {
+
+		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
+			return (xmlSchemaComparePreserveReplaceStrings(y, x, 1));
+		    if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
+			return (xmlSchemaCompareReplacedStrings(x, y));
+		    if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
+			return (xmlSchemaCompareReplaceCollapseStrings(x, y, 0));
+
+		} else if (xws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
+
+		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
+			return (xmlSchemaComparePreserveCollapseStrings(y, x, 1));
+		    if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
+			return (xmlSchemaCompareReplaceCollapseStrings(y, x, 1));
+		    if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
+			return (xmlSchemaCompareNormStrings(x, y));
+		} else
+		    return (-2);
+                
+	    }
             return (-2);
         case XML_SCHEMAS_QNAME:
             if (y->type == XML_SCHEMAS_QNAME) {
@@ -3754,8 +4165,7 @@
                 else
                     return(-1);
             }
-            return (-2);
-        case XML_SCHEMAS_STRING:
+            return (-2);    
         case XML_SCHEMAS_IDREFS:
         case XML_SCHEMAS_ENTITIES:
         case XML_SCHEMAS_NMTOKENS:
@@ -3766,6 +4176,57 @@
 }
 
 /**
+ * xmlSchemaCompareValues:
+ * @x:  a first value
+ * @y:  a second 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
+ */
+int
+xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
+    xmlSchemaWhitespaceValueType xws, yws;
+
+    if (x->type == XML_SCHEMAS_STRING)
+	xws = XML_SCHEMA_WHITESPACE_PRESERVE;
+    else if (x->type == XML_SCHEMAS_NORMSTRING)
+        xws = XML_SCHEMA_WHITESPACE_REPLACE;
+    else
+        xws = XML_SCHEMA_WHITESPACE_COLLAPSE;
+
+    if (y->type == XML_SCHEMAS_STRING)
+	yws = XML_SCHEMA_WHITESPACE_PRESERVE;
+    else if (x->type == XML_SCHEMAS_NORMSTRING)
+        yws = XML_SCHEMA_WHITESPACE_REPLACE;
+    else
+        yws = XML_SCHEMA_WHITESPACE_COLLAPSE;
+
+    return(xmlSchemaCompareValuesInternal(x, xws, y, yws));
+}
+
+/**
+ * xmlSchemaCompareValuesWhtsp:
+ * @x:  a first value
+ * @xws: the whitespace value of x
+ * @y:  a second value
+ * @yws: the whitespace value of y
+ *
+ * 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
+ */
+int
+xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,
+				 xmlSchemaWhitespaceValueType xws,
+				 xmlSchemaValPtr y,
+				 xmlSchemaWhitespaceValueType yws) {
+    return(xmlSchemaCompareValuesInternal(x, xws, y, yws));
+}
+
+/**
  * xmlSchemaNormLen:
  * @value:  a string
  *
@@ -4138,4 +4599,51 @@
 
 }
 
+/**
+ * xmlSchemaGetCanonValue:
+ * @val: the precomputed value
+ * @retValue: the returned value
+ *
+ * Returns a the cononical representation of the value.
+ * The called 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.
+ */
+int
+xmlSchemaGetCanonValue(xmlSchemaValPtr val,
+		       const xmlChar **retValue)
+{
+    if (retValue == NULL)
+	return (-1);
+    *retValue = NULL;
+    switch (val->type) {
+	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_QNAME:
+	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 (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);
+	default:
+	    return (-1);
+    }
+    return (-1);
+}
+
 #endif /* LIBXML_SCHEMAS_ENABLED */