added xsd:include support, fixed testSchemas behaviour when a schemas

* include/libxml/schemasInternals.h include/libxml/xmlerror.h
  testSchemas.c xmlschemas.c: added xsd:include support, fixed
  testSchemas behaviour when a schemas failed to parse.
* test/schemas/vdv-* result/schemas/vdv-first5_0_0*: added one
  test for xsd:include from Eric Van der Vlist
Daniel
diff --git a/xmlschemas.c b/xmlschemas.c
index feafab9..91e53c6 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -60,6 +60,8 @@
 
 #define XML_SCHEMAS_PARSE_ERROR		1
 
+#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
+
 struct _xmlSchemaParserCtxt {
     void *userData;             /* user specific data block */
     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
@@ -149,6 +151,18 @@
     xmlSchemaPtr schema;
 };
 
+/*
+ * These are the entries associated to includes in a schemas
+ */
+typedef struct _xmlSchemaInclude xmlSchemaInclude;
+typedef xmlSchemaInclude *xmlSchemaIncludePtr;
+struct _xmlSchemaInclude {
+    xmlSchemaIncludePtr next;
+
+    const xmlChar *schemaLocation;
+    xmlDocPtr doc;
+};
+
 /************************************************************************
  * 									*
  * 			Some predeclarations				*
@@ -158,6 +172,9 @@
                                         xmlSchemaTypePtr type,
                                         const xmlChar * value);
 
+static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
+                                 xmlSchemaPtr schema,
+                                 xmlNodePtr node);
 /************************************************************************
  *									*
  * 			Datatype error handlers				*
@@ -431,6 +448,40 @@
 }
 
 /**
+ * xmlSchemaFreeInclude:
+ * @include:  a schema include structure
+ *
+ * Deallocate an include structure
+ */
+static void
+xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
+{
+    if (include == NULL)
+        return;
+
+    xmlFreeDoc(include->doc);
+    xmlFree(include);
+}
+
+/**
+ * xmlSchemaFreeIncludeList:
+ * @includes:  a schema include list
+ *
+ * Deallocate an include structure
+ */
+static void
+xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
+{
+    xmlSchemaIncludePtr next;
+
+    while (includes != NULL) {
+        next = includes->next;
+	xmlSchemaFreeInclude(includes);
+	includes = next;
+    }
+}
+
+/**
  * xmlSchemaFreeNotation:
  * @schema:  a schema notation structure
  *
@@ -569,6 +620,9 @@
     if (schema->schemasImports != NULL)
 	xmlHashFree(schema->schemasImports,
 		    (xmlHashDeallocator) xmlSchemaFreeImport);
+    if (schema->includes != NULL) {
+        xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
+    }
     if (schema->annot != NULL)
         xmlSchemaFreeAnnot(schema->annot);
     if (schema->doc != NULL)
@@ -2516,12 +2570,18 @@
     xmlSchemaImportPtr import;
     xmlSchemaParserCtxtPtr newctxt;
 
-    newctxt = xmlSchemaNewParserCtxt((const char *) schemaLocation);
+    newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
     if (newctxt == NULL) {
-        xmlSchemaPErrMemory(NULL, "allocating parser context",
+        xmlSchemaPErrMemory(ctxt, "allocating schama parser context",
                             NULL);
         return (NULL);
     }
+    memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
+    /* Keep the same dictionnary for parsing, really */
+    xmlDictReference(ctxt->dict);
+    newctxt->dict = ctxt->dict;
+    newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
+
     xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
 	                     ctxt->userData);
 
@@ -2699,6 +2759,303 @@
 }
 
 /**
+ * xmlSchemaCleanupDoc:
+ * @ctxt:  a schema validation context
+ * @node:  the root of the document.
+ *
+ * removes unwanted nodes in a schemas document tree
+ */
+static void
+xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
+{
+    xmlNodePtr delete, cur;
+
+    if ((ctxt == NULL) || (root == NULL)) return;
+
+    /*
+     * Remove all the blank text nodes
+     */
+    delete = NULL;
+    cur = root;
+    while (cur != NULL) {
+        if (delete != NULL) {
+            xmlUnlinkNode(delete);
+            xmlFreeNode(delete);
+            delete = NULL;
+        }
+        if (cur->type == XML_TEXT_NODE) {
+            if (IS_BLANK_NODE(cur)) {
+                if (xmlNodeGetSpacePreserve(cur) != 1) {
+                    delete = cur;
+                }
+            }
+        } else if ((cur->type != XML_ELEMENT_NODE) &&
+                   (cur->type != XML_CDATA_SECTION_NODE)) {
+            delete = cur;
+            goto skip_children;
+        }
+
+        /*
+         * Skip to next node
+         */
+        if (cur->children != NULL) {
+            if ((cur->children->type != XML_ENTITY_DECL) &&
+                (cur->children->type != XML_ENTITY_REF_NODE) &&
+                (cur->children->type != XML_ENTITY_NODE)) {
+                cur = cur->children;
+                continue;
+            }
+        }
+      skip_children:
+        if (cur->next != NULL) {
+            cur = cur->next;
+            continue;
+        }
+
+        do {
+            cur = cur->parent;
+            if (cur == NULL)
+                break;
+            if (cur == root) {
+                cur = NULL;
+                break;
+            }
+            if (cur->next != NULL) {
+                cur = cur->next;
+                break;
+            }
+        } while (cur != NULL);
+    }
+    if (delete != NULL) {
+        xmlUnlinkNode(delete);
+        xmlFreeNode(delete);
+        delete = NULL;
+    }
+}
+
+/**
+ * xmlSchemaParseSchemaTopLevel:
+ * @ctxt:  a schema validation context
+ * @schema:  the schemas
+ * @nodes:  the list of top level nodes
+ *
+ * Returns the internal XML Schema structure built from the resource or
+ *         NULL in case of error
+ */
+static void
+xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
+                             xmlSchemaPtr schema, xmlNodePtr nodes)
+{
+    xmlNodePtr child;
+    xmlSchemaAnnotPtr annot;
+
+    if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
+        return;
+
+    child = nodes;
+    while ((IS_SCHEMA(child, "include")) ||
+	   (IS_SCHEMA(child, "import")) ||
+	   (IS_SCHEMA(child, "redefine")) ||
+	   (IS_SCHEMA(child, "annotation"))) {
+	if (IS_SCHEMA(child, "annotation")) {
+	    annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	    if (schema->annot == NULL)
+		schema->annot = annot;
+	    else
+		xmlSchemaFreeAnnot(annot);
+	} else if (IS_SCHEMA(child, "import")) {
+	    xmlSchemaParseImport(ctxt, schema, child);
+	} else if (IS_SCHEMA(child, "include")) {
+	    xmlSchemaParseInclude(ctxt, schema, child);
+	} else if (IS_SCHEMA(child, "redefine")) {
+	    TODO
+	}
+	child = child->next;
+    }
+    while (child != NULL) {
+	if (IS_SCHEMA(child, "complexType")) {
+	    xmlSchemaParseComplexType(ctxt, schema, child);
+	    child = child->next;
+	} else if (IS_SCHEMA(child, "simpleType")) {
+	    xmlSchemaParseSimpleType(ctxt, schema, child);
+	    child = child->next;
+	} else if (IS_SCHEMA(child, "element")) {
+	    xmlSchemaParseElement(ctxt, schema, child, 1);
+	    child = child->next;
+	} else if (IS_SCHEMA(child, "attribute")) {
+	    xmlSchemaParseAttribute(ctxt, schema, child);
+	    child = child->next;
+	} else if (IS_SCHEMA(child, "attributeGroup")) {
+	    xmlSchemaParseAttributeGroup(ctxt, schema, child);
+	    child = child->next;
+	} else if (IS_SCHEMA(child, "group")) {
+	    xmlSchemaParseGroup(ctxt, schema, child);
+	    child = child->next;
+	} else if (IS_SCHEMA(child, "notation")) {
+	    xmlSchemaParseNotation(ctxt, schema, child);
+	    child = child->next;
+	} else {
+	    xmlSchemaPErr2(ctxt, NULL, child,
+			   XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
+			   "Schemas: unexpected element %s here \n",
+			   child->name, NULL);
+	    child = child->next;
+	}
+	while (IS_SCHEMA(child, "annotation")) {
+	    annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	    if (schema->annot == NULL)
+		schema->annot = annot;
+	    else
+		xmlSchemaFreeAnnot(annot);
+	    child = child->next;
+	}
+    }
+}
+
+/**
+ * xmlSchemaParseInclude:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Include definition
+ *
+ * Returns -1 in case of error, 0 if the declaration is inproper and
+ *         1 in case of success.
+ */
+static int
+xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                      xmlNodePtr node)
+{
+    xmlNodePtr child = NULL;
+    const xmlChar *schemaLocation;
+    xmlURIPtr check;
+    xmlDocPtr doc;
+    xmlNodePtr root;
+    xmlSchemaIncludePtr include;
+
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (-1);
+
+    /*
+     * Preliminary step, extract the URI-Reference for the include and
+     * make an URI from the base.
+     */
+    schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
+    if (schemaLocation != NULL) {
+        xmlChar *base = NULL;
+        xmlChar *URI = NULL;
+        check = xmlParseURI((const char *) schemaLocation);
+        if (check == NULL) {
+            xmlSchemaPErr2(ctxt, node, child,
+                           XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
+		       "Include schemaLocation attribute is not an URI: %s\n",
+                           schemaLocation, NULL);
+            return (-1);
+        } else {
+            xmlFreeURI(check);
+        }
+	base = xmlNodeGetBase(node->doc, node);
+	if (base == NULL) {
+	    URI = xmlBuildURI(schemaLocation, node->doc->URL);
+	} else {
+	    URI = xmlBuildURI(schemaLocation, base);
+	    xmlFree(base);
+	}
+	if (URI != NULL) {
+	    schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
+	    xmlFree(URI);
+	}
+    } else {
+	xmlSchemaPErr2(ctxt, node, child,
+		       XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
+		   "Include schemaLocation attribute missing\n",
+		       NULL, NULL);
+	return (-1);
+    }
+
+    child = node->children;
+    while (IS_SCHEMA(child, "annotation")) {
+        /*
+         * the annotations here are simply discarded ...
+         */
+        child = child->next;
+    }
+    if (child != NULL) {
+        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
+                       "Include has unexpected content\n", NULL, NULL);
+        return (-1);
+    }
+
+    /*
+     * First step is to parse the input document into an DOM/Infoset
+     */
+    doc = xmlReadFile((const char *) schemaLocation, NULL,
+                      SCHEMAS_PARSE_OPTIONS);
+    if (doc == NULL) {
+	xmlSchemaPErr(ctxt, NULL,
+		      XML_SCHEMAP_FAILED_LOAD,
+		      "xmlSchemaParse: could not load %s\n",
+		      ctxt->URL, NULL);
+	return(-1);
+    }
+
+    /*
+     * Then extract the root of the schema
+     */
+    root = xmlDocGetRootElement(doc);
+    if (root == NULL) {
+	xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
+		      XML_SCHEMAP_NOROOT,
+		      "schemas %s has no root", schemaLocation, NULL);
+	xmlFreeDoc(doc);
+        return (-1);
+    }
+
+    /*
+     * Remove all the blank text nodes
+     */
+    xmlSchemaCleanupDoc(ctxt, root);
+
+    /*
+     * Check the schemas top level element
+     */
+    if (!IS_SCHEMA(root, "schema")) {
+	xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
+		      XML_SCHEMAP_NOT_SCHEMA,
+		      "File %s is not a schemas", schemaLocation, NULL);
+	xmlFreeDoc(doc);
+        return (-1);
+    }
+
+    /*
+     * register the include
+     */
+    include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
+    if (include == NULL) {
+        xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
+	xmlFreeDoc(doc);
+        return (-1);
+    }
+
+    memset(include, 0, sizeof(xmlSchemaInclude));
+    include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
+    include->doc = doc;
+    include->next = schema->includes;
+    schema->includes = include;
+
+
+    /*
+     * parse the declarations in the included file like if they
+     * were in the original file.
+     */
+    xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
+
+    return (1);
+}
+
+/**
  * xmlSchemaParseChoice:
  * @ctxt:  a schema validation context
  * @schema:  the schema being built
@@ -3240,7 +3597,6 @@
     return (type);
 }
 
-
 /**
  * xmlSchemaParseSchema:
  * @ctxt:  a schema validation context
@@ -3256,7 +3612,6 @@
 xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
 {
     xmlSchemaPtr schema = NULL;
-    xmlSchemaAnnotPtr annot;
     xmlNodePtr child = NULL;
     const xmlChar *val;
     int nberrors;
@@ -3303,62 +3658,22 @@
             }
         } 
 
-        child = node->children;
-        while ((IS_SCHEMA(child, "include")) ||
-               (IS_SCHEMA(child, "import")) ||
-               (IS_SCHEMA(child, "redefine")) ||
-               (IS_SCHEMA(child, "annotation"))) {
-            if (IS_SCHEMA(child, "annotation")) {
-                annot = xmlSchemaParseAnnotation(ctxt, schema, child);
-                if (schema->annot == NULL)
-                    schema->annot = annot;
-                else
-                    xmlSchemaFreeAnnot(annot);
-            } else if (IS_SCHEMA(child, "include")) {
-            TODO} else if (IS_SCHEMA(child, "import")) {
-                xmlSchemaParseImport(ctxt, schema, child);
-            } else if (IS_SCHEMA(child, "redefine")) {
-            TODO}
-            child = child->next;
-        }
-        while (child != NULL) {
-            if (IS_SCHEMA(child, "complexType")) {
-                xmlSchemaParseComplexType(ctxt, schema, child);
-                child = child->next;
-            } else if (IS_SCHEMA(child, "simpleType")) {
-                xmlSchemaParseSimpleType(ctxt, schema, child);
-                child = child->next;
-            } else if (IS_SCHEMA(child, "element")) {
-                xmlSchemaParseElement(ctxt, schema, child, 1);
-                child = child->next;
-            } else if (IS_SCHEMA(child, "attribute")) {
-                xmlSchemaParseAttribute(ctxt, schema, child);
-                child = child->next;
-            } else if (IS_SCHEMA(child, "attributeGroup")) {
-                xmlSchemaParseAttributeGroup(ctxt, schema, child);
-                child = child->next;
-            } else if (IS_SCHEMA(child, "group")) {
-                xmlSchemaParseGroup(ctxt, schema, child);
-                child = child->next;
-            } else if (IS_SCHEMA(child, "notation")) {
-                xmlSchemaParseNotation(ctxt, schema, child);
-                child = child->next;
-            } else {
-                xmlSchemaPErr2(ctxt, node, child,
-                               XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
-                               "Schemas: unexpected element %s here \n",
-                               child->name, NULL);
-                child = child->next;
-            }
-            while (IS_SCHEMA(child, "annotation")) {
-                annot = xmlSchemaParseAnnotation(ctxt, schema, child);
-                if (schema->annot == NULL)
-                    schema->annot = annot;
-                else
-                    xmlSchemaFreeAnnot(annot);
-                child = child->next;
-            }
-        }
+        xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
+    } else {
+        xmlDocPtr doc;
+
+	doc = node->doc;
+
+        if ((doc != NULL) && (doc->URL != NULL)) {
+	    xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
+		      XML_SCHEMAP_NOT_SCHEMA,
+		      "File %s is not a schemas", doc->URL, NULL);
+	} else {
+	    xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
+		      XML_SCHEMAP_NOT_SCHEMA,
+		      "File is not a schemas", NULL, NULL);
+	}
+	return(NULL);
     }
     if (ctxt->nberrors != 0) {
         if (schema != NULL) {
@@ -4492,7 +4807,7 @@
 {
     xmlSchemaPtr ret = NULL;
     xmlDocPtr doc;
-    xmlNodePtr root, cur, delete;
+    xmlNodePtr root;
     int nberrors;
 
     xmlSchemaInitTypes();
@@ -4509,7 +4824,8 @@
      * First step is to parse the input document into an DOM/Infoset
      */
     if (ctxt->URL != NULL) {
-        doc = xmlParseFile((const char *) ctxt->URL);
+        doc = xmlReadFile((const char *) ctxt->URL, NULL, 
+	                  SCHEMAS_PARSE_OPTIONS);
         if (doc == NULL) {
 	    xmlSchemaPErr(ctxt, NULL,
 			  XML_SCHEMAP_FAILED_LOAD,
@@ -4518,7 +4834,8 @@
             return (NULL);
         }
     } else if (ctxt->buffer != NULL) {
-        doc = xmlParseMemory(ctxt->buffer, ctxt->size);
+        doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
+	                    SCHEMAS_PARSE_OPTIONS);
         if (doc == NULL) {
 	    xmlSchemaPErr(ctxt, NULL,
 			  XML_SCHEMAP_FAILED_PARSE,
@@ -4553,62 +4870,7 @@
     /*
      * Remove all the blank text nodes
      */
-    delete = NULL;
-    cur = root;
-    while (cur != NULL) {
-        if (delete != NULL) {
-            xmlUnlinkNode(delete);
-            xmlFreeNode(delete);
-            delete = NULL;
-        }
-        if (cur->type == XML_TEXT_NODE) {
-            if (IS_BLANK_NODE(cur)) {
-                if (xmlNodeGetSpacePreserve(cur) != 1) {
-                    delete = cur;
-                }
-            }
-        } else if ((cur->type != XML_ELEMENT_NODE) &&
-                   (cur->type != XML_CDATA_SECTION_NODE)) {
-            delete = cur;
-            goto skip_children;
-        }
-
-        /*
-         * Skip to next node
-         */
-        if (cur->children != NULL) {
-            if ((cur->children->type != XML_ENTITY_DECL) &&
-                (cur->children->type != XML_ENTITY_REF_NODE) &&
-                (cur->children->type != XML_ENTITY_NODE)) {
-                cur = cur->children;
-                continue;
-            }
-        }
-      skip_children:
-        if (cur->next != NULL) {
-            cur = cur->next;
-            continue;
-        }
-
-        do {
-            cur = cur->parent;
-            if (cur == NULL)
-                break;
-            if (cur == root) {
-                cur = NULL;
-                break;
-            }
-            if (cur->next != NULL) {
-                cur = cur->next;
-                break;
-            }
-        } while (cur != NULL);
-    }
-    if (delete != NULL) {
-        xmlUnlinkNode(delete);
-        xmlFreeNode(delete);
-        delete = NULL;
-    }
+    xmlSchemaCleanupDoc(ctxt, root);
 
     /*
      * Then do the parsing for good