merged the current state of XML Schemas implementation, it is not

* Makefile.am TODO_SCHEMAS configure.in genUnicode.py testAutomata.c
 testRegexp.c testSchemas.c xmlregexp.c xmlschemas.c xmlschemastypes.c
 xmlunicode.c include/libxml/Makefile.am
 include/libxml/schemasInternals.h include/libxml/xmlautomata.h
 include/libxml/xmlregexp.h include/libxml/xmlschemas.h
 include/libxml/xmlschemastypes.h include/libxml/xmlunicode.h
 include/libxml/xmlversion.h.in : merged the current state of
 XML Schemas implementation, it is not configured in by default,
 a specific --schemas configure option has been added.
* test/automata test/regexp test/schemas Makefile.am
  result/automata result/regexp result/schemas:
  merged automata/regexp/schemas regression tests
Daniel
diff --git a/xmlschemas.c b/xmlschemas.c
new file mode 100644
index 0000000..f211095
--- /dev/null
+++ b/xmlschemas.c
@@ -0,0 +1,4941 @@
+/*
+ * schemas.c : implementation of the XML Schema handling and
+ *             schema validity checking
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel Veillard <veillard@redhat.com>
+ */
+
+#define IN_LIBXML
+#include "libxml.h"
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/hash.h>
+
+#include <libxml/xmlschemas.h>
+#include <libxml/schemasInternals.h>
+#include <libxml/xmlschemastypes.h>
+#include <libxml/xmlautomata.h>
+#include <libxml/xmlregexp.h>
+
+#define DEBUG 1                 /* very verobose output */
+/* #define DEBUG_CONTENT 1 */
+/* #define DEBUG_AUTOMATA 1 */
+
+#define UNBOUNDED (1 << 30)
+#define TODO 								\
+    xmlGenericError(xmlGenericErrorContext,				\
+	    "Unimplemented block at %s:%d\n",				\
+            __FILE__, __LINE__);
+
+/*
+ * The XML Schemas namespaces
+ */
+static const xmlChar *xmlSchemaNs = (const xmlChar *)
+    "http://www.w3.org/2001/XMLSchema";
+
+static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
+    "http://www.w3.org/2001/XMLSchema-instance";
+
+#define IS_SCHEMA(node, type)						\
+   ((node != NULL) && (node->ns != NULL) &&				\
+    (xmlStrEqual(node->name, (const xmlChar *) type)) &&		\
+    (xmlStrEqual(node->ns->href, xmlSchemaNs)))
+
+#define XML_SCHEMAS_PARSE_ERROR		1
+
+struct _xmlSchemaParserCtxt {
+    void *userData;			/* user specific data block */
+    xmlSchemaValidityErrorFunc error;	/* the callback in case of errors */
+    xmlSchemaValidityWarningFunc warning;/* the callback in case of warning */
+
+    xmlSchemaPtr       schema;        /* The schema in use */
+    xmlChar 	      *container;     /* the current element, group, ... */
+    int counter;
+
+    xmlChar	      *URL;
+    xmlDocPtr          doc;
+
+    /*
+     * Used to build complex element content models
+     */
+    xmlAutomataPtr     am;
+    xmlAutomataStatePtr start;
+    xmlAutomataStatePtr end;
+    xmlAutomataStatePtr state;
+};
+
+
+#define XML_SCHEMAS_ATTR_UNKNOWN 1
+#define XML_SCHEMAS_ATTR_CHECKED 2
+
+typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
+typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
+struct _xmlSchemaAttrState {
+    xmlAttrPtr       attr;
+    int              state;
+};
+
+/**
+ * xmlSchemaValidCtxt:
+ *
+ * A Schemas validation context
+ */
+
+struct _xmlSchemaValidCtxt {
+    void *userData;			/* user specific data block */
+    xmlSchemaValidityErrorFunc error;	/* the callback in case of errors */
+    xmlSchemaValidityWarningFunc warning;/* the callback in case of warning */
+
+    xmlSchemaPtr            schema;        /* The schema in use */
+    xmlDocPtr               doc;
+    xmlParserInputBufferPtr input;
+    xmlCharEncoding         enc;
+    xmlSAXHandlerPtr        sax;
+    void                   *user_data;
+
+    xmlDocPtr               myDoc;
+    int                     err;
+
+    xmlNodePtr              node;
+    xmlSchemaTypePtr        type;
+
+    xmlRegExecCtxtPtr       regexp;
+    xmlSchemaValPtr         value;
+
+    int                     attrNr;
+    int                     attrBase;
+    int                     attrMax;
+    xmlSchemaAttrStatePtr   attr;
+};
+
+
+/************************************************************************
+ * 									*
+ * 			Some predeclarations				*
+ * 									*
+ ************************************************************************/
+static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt, 
+			     xmlSchemaTypePtr type,
+	                     xmlChar *value);
+
+/************************************************************************
+ * 									*
+ * 			Allocation functions				*
+ * 									*
+ ************************************************************************/
+
+/**
+ * xmlSchemaNewSchema:
+ * @ctxt:  a schema validation context (optional)
+ *
+ * Allocate a new Schema structure.
+ *
+ * Returns the newly allocated structure or NULL in case or error
+ */
+static xmlSchemaPtr
+xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
+{
+    xmlSchemaPtr ret;
+
+    ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
+    if (ret == NULL) {
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Out of memory\n");
+        return (NULL);
+    }
+    memset(ret, 0, sizeof(xmlSchema));
+
+    return (ret);
+}
+
+/**
+ * xmlSchemaNewFacet:
+ * @ctxt:  a schema validation context (optional)
+ *
+ * Allocate a new Facet structure.
+ *
+ * Returns the newly allocated structure or NULL in case or error
+ */
+static xmlSchemaFacetPtr
+xmlSchemaNewFacet(xmlSchemaParserCtxtPtr ctxt)
+{
+    xmlSchemaFacetPtr ret;
+
+    ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
+    if (ret == NULL) {
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Out of memory\n");
+        return (NULL);
+    }
+    memset(ret, 0, sizeof(xmlSchemaFacet));
+
+    return (ret);
+}
+
+/**
+ * xmlSchemaNewAnnot:
+ * @ctxt:  a schema validation context (optional)
+ * @node:  a node
+ *
+ * Allocate a new annotation structure.
+ *
+ * Returns the newly allocated structure or NULL in case or error
+ */
+static xmlSchemaAnnotPtr
+xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
+{
+    xmlSchemaAnnotPtr ret;
+
+    ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
+    if (ret == NULL) {
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Out of memory\n");
+        return (NULL);
+    }
+    memset(ret, 0, sizeof(xmlSchemaAnnot));
+    ret->content = node;
+    return (ret);
+}
+
+/**
+ * xmlSchemaFreeNotation:
+ * @schema:  a schema notation structure
+ *
+ * Deallocate a Schema Notation structure.
+ */
+static void
+xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
+{
+    if (nota == NULL)
+        return;
+    if (nota->name != NULL)
+        xmlFree((xmlChar *) nota->name);
+    xmlFree(nota);
+}
+
+/**
+ * xmlSchemaFreeAttribute:
+ * @schema:  a schema attribute structure
+ *
+ * Deallocate a Schema Attribute structure.
+ */
+static void
+xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
+{
+    if (attr == NULL)
+        return;
+    if (attr->name != NULL)
+        xmlFree((xmlChar *) attr->name);
+    if (attr->ref != NULL)
+	xmlFree((xmlChar *) attr->ref);
+    if (attr->refNs != NULL)
+	xmlFree((xmlChar *) attr->refNs);
+    if (attr->typeName != NULL)
+	xmlFree((xmlChar *) attr->typeName);
+    if (attr->typeNs != NULL)
+	xmlFree((xmlChar *) attr->typeNs);
+    xmlFree(attr);
+}
+
+/**
+ * xmlSchemaFreeAttributeGroup:
+ * @schema:  a schema attribute group structure
+ *
+ * Deallocate a Schema Attribute Group structure.
+ */
+static void
+xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
+{
+    if (attr == NULL)
+        return;
+    if (attr->name != NULL)
+        xmlFree((xmlChar *) attr->name);
+    xmlFree(attr);
+}
+
+/**
+ * xmlSchemaFreeElement:
+ * @schema:  a schema element structure
+ *
+ * Deallocate a Schema Element structure.
+ */
+static void
+xmlSchemaFreeElement(xmlSchemaElementPtr elem)
+{
+    if (elem == NULL)
+        return;
+    if (elem->name != NULL)
+        xmlFree((xmlChar *) elem->name);
+    if (elem->namedType != NULL)
+        xmlFree((xmlChar *) elem->namedType);
+    if (elem->namedTypeNs != NULL)
+        xmlFree((xmlChar *) elem->namedTypeNs);
+    if (elem->ref != NULL)
+        xmlFree((xmlChar *) elem->ref);
+    if (elem->refNs != NULL)
+        xmlFree((xmlChar *) elem->refNs);
+    if (elem->contModel != NULL)
+	xmlRegFreeRegexp(elem->contModel);
+    xmlFree(elem);
+}
+
+/**
+ * xmlSchemaFreeFacet:
+ * @facet:  a schema facet structure
+ *
+ * Deallocate a Schema Facet structure.
+ */
+static void
+xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
+{
+    if (facet == NULL)
+        return;
+    if (facet->value != NULL)
+        xmlFree((xmlChar *) facet->value);
+    if (facet->id != NULL)
+        xmlFree((xmlChar *) facet->id);
+    if (facet->val != NULL)
+	xmlSchemaFreeValue(facet->val);
+    if (facet->regexp != NULL)
+	xmlRegFreeRegexp(facet->regexp);
+    xmlFree(facet);
+}
+
+/**
+ * xmlSchemaFreeType:
+ * @type:  a schema type structure
+ *
+ * Deallocate a Schema Type structure.
+ */
+void
+xmlSchemaFreeType(xmlSchemaTypePtr type)
+{
+    if (type == NULL)
+        return;
+    if (type->name != NULL)
+        xmlFree((xmlChar *) type->name);
+    if (type->base != NULL)
+        xmlFree((xmlChar *) type->base);
+    if (type->baseNs != NULL)
+        xmlFree((xmlChar *) type->baseNs);
+    if (type->annot != NULL)
+        xmlFree((xmlChar *) type->annot);
+    if (type->facets != NULL) {
+	xmlSchemaFacetPtr facet, next;
+
+	facet = type->facets;
+	while (facet != NULL) {
+	    next = facet->next;
+	    xmlSchemaFreeFacet(facet);
+	    facet = next;
+	}
+    }
+    xmlFree(type);
+}
+
+/**
+ * xmlSchemaFreeAnnot:
+ * @annot:  a schema type structure
+ *
+ * Deallocate a annotation structure
+ */
+static void
+xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
+{
+    if (annot == NULL)
+        return;
+    xmlFree(annot);
+}
+
+/**
+ * xmlSchemaFree:
+ * @schema:  a schema structure
+ *
+ * Deallocate a Schema structure.
+ */
+void
+xmlSchemaFree(xmlSchemaPtr schema)
+{
+    if (schema == NULL)
+        return;
+
+    if (schema->name != NULL)
+        xmlFree((xmlChar *) schema->name);
+    if (schema->notaDecl != NULL)
+        xmlHashFree(schema->notaDecl,
+                    (xmlHashDeallocator) xmlSchemaFreeNotation);
+    if (schema->attrDecl != NULL)
+        xmlHashFree(schema->attrDecl,
+                    (xmlHashDeallocator) xmlSchemaFreeAttribute);
+    if (schema->attrgrpDecl != NULL)
+        xmlHashFree(schema->attrgrpDecl,
+                    (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
+    if (schema->elemDecl != NULL)
+        xmlHashFree(schema->elemDecl,
+                    (xmlHashDeallocator) xmlSchemaFreeElement);
+    if (schema->typeDecl != NULL)
+        xmlHashFree(schema->typeDecl,
+                    (xmlHashDeallocator) xmlSchemaFreeType);
+    if (schema->annot != NULL)
+	xmlSchemaFreeAnnot(schema->annot);
+    if (schema->doc != NULL)
+	xmlFreeDoc(schema->doc);
+
+    xmlFree(schema);
+}
+
+/************************************************************************
+ * 									*
+ * 			Error functions					*
+ * 									*
+ ************************************************************************/
+
+/**
+ * xmlSchemaErrorContext:
+ * @ctxt:  the parsing context
+ * @schema:  the schema being built
+ * @node:  the node being processed
+ * @child:  the child being processed
+ *
+ * Dump a SchemaType structure
+ */
+static void
+xmlSchemaErrorContext(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                      xmlNodePtr node, xmlNodePtr child)
+{
+    int line = 0;
+    const xmlChar *file = NULL;
+    const xmlChar *name = NULL;
+    const char *type = "error";
+
+    if ((ctxt == NULL) || (ctxt->error == NULL))
+	return;
+
+    if (child != NULL)
+	node = child;
+
+    if (node != NULL)  {
+	if ((node->type == XML_DOCUMENT_NODE) ||
+	    (node->type == XML_HTML_DOCUMENT_NODE)) {
+	    xmlDocPtr doc = (xmlDocPtr) node;
+
+	    file = doc->URL;
+	} else {
+	    /*
+	     * Try to find contextual informations to report
+	     */
+	    if (node->type == XML_ELEMENT_NODE) {
+		line = (int) node->content;
+	    } else if ((node->prev != NULL) &&
+		       (node->prev->type == XML_ELEMENT_NODE)) {
+		line = (int) node->prev->content;
+	    } else if ((node->parent != NULL) &&
+		       (node->parent->type == XML_ELEMENT_NODE)) {
+		line = (int) node->parent->content;
+	    }
+	    if ((node->doc != NULL) && (node->doc->URL != NULL))
+		file = node->doc->URL;
+	    if (node->name != NULL)
+		name = node->name;
+	}
+    } 
+    
+    if (ctxt != NULL)
+	type = "compilation error";
+    else if (schema != NULL)
+	type = "runtime error";
+
+    if ((file != NULL) && (line != 0) && (name != NULL))
+	ctxt->error(ctxt->userData, "%s: file %s line %d element %s\n",
+		type, file, line, name);
+    else if ((file != NULL) && (name != NULL))
+	ctxt->error(ctxt->userData, "%s: file %s element %s\n",
+		type, file, name);
+    else if ((file != NULL) && (line != 0))
+	ctxt->error(ctxt->userData, "%s: file %s line %d\n", type, file, line);
+    else if (file != NULL)
+	ctxt->error(ctxt->userData, "%s: file %s\n", type, file);
+    else if (name != NULL)
+	ctxt->error(ctxt->userData, "%s: element %s\n", type, name);
+    else
+	ctxt->error(ctxt->userData, "%s\n", type);
+}
+
+/************************************************************************
+ * 									*
+ * 			Debug functions					*
+ * 									*
+ ************************************************************************/
+
+/**
+ * xmlSchemaElementDump:
+ * @elem:  an element
+ * @output:  the file output
+ *
+ * Dump the element
+ */
+static void
+xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
+		     ATTRIBUTE_UNUSED const xmlChar *name,
+		     ATTRIBUTE_UNUSED const xmlChar *context,
+		     ATTRIBUTE_UNUSED const xmlChar *namespace)
+{
+    if (elem == NULL)
+        return;
+
+    fprintf(output, "Element ");
+    if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
+	fprintf(output, "toplevel ");
+    fprintf(output, ": %s ", elem->name);
+    if (namespace != NULL)
+	fprintf(output, "namespace '%s' ", namespace);
+    
+    if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
+	fprintf(output, "nillable ");
+    if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
+	fprintf(output, "global ");
+    if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
+	fprintf(output, "default ");
+    if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
+	fprintf(output, "fixed ");
+    if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
+	fprintf(output, "abstract ");
+    if (elem->flags & XML_SCHEMAS_ELEM_REF)
+	fprintf(output, "ref '%s' ", elem->ref);
+    if (elem->id != NULL)
+	fprintf(output, "id '%s' ", elem->id);
+    fprintf(output, "\n");
+    if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
+	fprintf(output, "  ");
+	if (elem->minOccurs != 1)
+	    fprintf(output, "min: %d ", elem->minOccurs);
+	if (elem->maxOccurs >= UNBOUNDED)
+	    fprintf(output, "max: unbounded\n");
+	else if (elem->maxOccurs != 1)
+	    fprintf(output, "max: %d\n", elem->maxOccurs);
+	else
+	    fprintf(output, "\n");
+    }
+    if (elem->namedType != NULL) {
+	fprintf(output, "  type: %s", elem->namedType);
+	if (elem->namedTypeNs != NULL)
+	    fprintf(output, " ns %s\n", elem->namedTypeNs);
+	else
+	    fprintf(output, "\n");
+    }
+    if (elem->substGroup != NULL) {
+	fprintf(output, "  substitutionGroup: %s", elem->substGroup);
+	if (elem->substGroupNs != NULL)
+	    fprintf(output, " ns %s\n", elem->substGroupNs);
+	else
+	    fprintf(output, "\n");
+    }
+    if (elem->value != NULL)
+	fprintf(output, "  default: %s", elem->value);
+}
+
+/**
+ * xmlSchemaAnnotDump:
+ * @output:  the file output
+ * @annot:  a annotation
+ *
+ * Dump the annotation
+ */
+static void
+xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
+{
+    xmlChar *content;
+
+    if (annot == NULL)
+        return;
+
+    content = xmlNodeGetContent(annot->content);
+    if (content != NULL) {
+        fprintf(output, "  Annot: %s\n", content);
+        xmlFree(content);
+    } else
+        fprintf(output, "  Annot: empty\n");
+}
+
+/**
+ * xmlSchemaTypeDump:
+ * @output:  the file output
+ * @type:  a type structure
+ *
+ * Dump a SchemaType structure
+ */
+static void
+xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
+{
+    if (type == NULL) {
+        fprintf(output, "Type: NULL\n");
+        return;
+    }
+    fprintf(output, "Type: ");
+    if (type->name != NULL)
+        fprintf(output, "%s, ", type->name);
+    else
+        fprintf(output, "no name");
+    switch (type->type) {
+        case XML_SCHEMA_TYPE_BASIC:
+            fprintf(output, "basic ");
+            break;
+        case XML_SCHEMA_TYPE_SIMPLE:
+            fprintf(output, "simple ");
+            break;
+        case XML_SCHEMA_TYPE_COMPLEX:
+            fprintf(output, "complex ");
+            break;
+        case XML_SCHEMA_TYPE_SEQUENCE:
+            fprintf(output, "sequence ");
+            break;
+        case XML_SCHEMA_TYPE_CHOICE:
+            fprintf(output, "choice ");
+            break;
+        case XML_SCHEMA_TYPE_ALL:
+            fprintf(output, "all ");
+            break;
+        case XML_SCHEMA_TYPE_UR:
+            fprintf(output, "ur ");
+            break;
+        case XML_SCHEMA_TYPE_RESTRICTION:
+            fprintf(output, "restriction ");
+            break;
+        case XML_SCHEMA_TYPE_EXTENSION:
+            fprintf(output, "extension ");
+            break;
+        default:
+            fprintf(output, "unknowntype%d ", type->type);
+            break;
+    }
+    if (type->base != NULL) {
+	fprintf(output, "base %s, ", type->base);
+    }
+    switch (type->contentType) {
+	case XML_SCHEMA_CONTENT_UNKNOWN:
+	    fprintf(output, "unknown ");
+	    break;
+	case XML_SCHEMA_CONTENT_EMPTY:
+	    fprintf(output, "empty ");
+	    break;
+	case XML_SCHEMA_CONTENT_ELEMENTS:
+	    fprintf(output, "element ");
+	    break;
+	case XML_SCHEMA_CONTENT_MIXED:
+	    fprintf(output, "mixed ");
+	    break;
+	case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
+	    fprintf(output, "mixed_or_elems ");
+	    break;
+	case XML_SCHEMA_CONTENT_BASIC:
+	    fprintf(output, "basic ");
+	    break;
+	case XML_SCHEMA_CONTENT_SIMPLE:
+	    fprintf(output, "simple ");
+	    break;
+    }
+    fprintf(output, "\n");
+    if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
+	fprintf(output, "  ");
+	if (type->minOccurs != 1)
+	    fprintf(output, "min: %d ", type->minOccurs);
+	if (type->maxOccurs >= UNBOUNDED)
+	    fprintf(output, "max: unbounded\n");
+	else if (type->maxOccurs != 1)
+	    fprintf(output, "max: %d\n", type->maxOccurs);
+	else
+	    fprintf(output, "\n");
+    }
+    if (type->annot != NULL)
+        xmlSchemaAnnotDump(output, type->annot);
+    if (type->subtypes != NULL) {
+	xmlSchemaTypePtr sub = type->subtypes;
+
+	fprintf(output, "  subtypes: ");
+	while (sub != NULL) {
+	    fprintf(output, "%s ", sub->name);
+	    sub = sub->next;
+	}
+	fprintf(output, "\n");
+    }
+
+}
+
+/**
+ * xmlSchemaDump:
+ * @output:  the file output
+ * @schema:  a schema structure
+ *
+ * Dump a Schema structure.
+ */
+void
+xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
+{
+    if (schema == NULL) {
+        fprintf(output, "Schemas: NULL\n");
+        return;
+    }
+    fprintf(output, "Schemas: ");
+    if (schema->name != NULL)
+        fprintf(output, "%s, ", schema->name);
+    else
+        fprintf(output, "no name, ");
+    if (schema->targetNamespace != NULL)
+        fprintf(output, "%s", schema->targetNamespace);
+    else
+        fprintf(output, "no target namespace");
+    fprintf(output, "\n");
+    if (schema->annot != NULL)
+        xmlSchemaAnnotDump(output, schema->annot);
+
+    xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
+                output);
+    xmlHashScanFull(schema->elemDecl,
+	            (xmlHashScannerFull) xmlSchemaElementDump, output);
+}
+
+/************************************************************************
+ * 									*
+ * 			Parsing functions				*
+ * 									*
+ ************************************************************************/
+
+/**
+ * xmlSchemaGetType:
+ * @schema:  the schemas context
+ * @name:  the type name
+ * @ns:  the type namespace
+ *
+ * Lookup a type in the schemas or the predefined types
+ *
+ * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
+ */
+static xmlSchemaTypePtr
+xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
+	         const xmlChar * namespace) {
+    xmlSchemaTypePtr ret;
+
+    if (name == NULL)
+	return(NULL);
+    if (schema != NULL) {
+	ret = xmlHashLookup2(schema->typeDecl, name, namespace);
+	if (ret != NULL)
+	    return(ret);
+    }
+    ret = xmlSchemaGetPredefinedType(name, namespace);
+#ifdef DEBUG
+    if (ret == NULL) {
+	if (namespace == NULL)
+	    fprintf(stderr, "Unable to lookup type %s", name);
+	else
+	    fprintf(stderr, "Unable to lookup type %s:%s", name, namespace);
+    }
+#endif
+    return(ret);
+}
+
+/************************************************************************
+ * 									*
+ * 			Parsing functions				*
+ * 									*
+ ************************************************************************/
+
+#define IS_BLANK_NODE(n)						\
+    (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
+
+/**
+ * xmlSchemaIsBlank:
+ * @str:  a string
+ *
+ * Check if a string is ignorable
+ *
+ * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
+ */
+static int
+xmlSchemaIsBlank(xmlChar *str) {
+    if (str == NULL)
+	return(1);
+    while (*str != 0) {
+	if (!(IS_BLANK(*str))) return(0);
+	str++;
+    }
+    return(1);
+}
+
+/**
+ * xmlSchemaAddNotation:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @name:  the item name
+ *
+ * Add an XML schema Attrribute declaration
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the new struture or NULL in case of error
+ */
+static xmlSchemaNotationPtr
+xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                      const xmlChar * name)
+{
+    xmlSchemaNotationPtr ret = NULL;
+    int val;
+
+    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
+        return (NULL);
+
+    if (schema->notaDecl == NULL)
+        schema->notaDecl = xmlHashCreate(10);
+    if (schema->notaDecl == NULL)
+        return (NULL);
+
+    ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
+    if (ret == NULL) {
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Out of memory\n");
+        return (NULL);
+    }
+    memset(ret, 0, sizeof(xmlSchemaNotation));
+    ret->name = xmlStrdup(name);
+    val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
+                           ret);
+    if (val != 0) {
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Could not add notation %s\n",
+                        name);
+        xmlFree((char *) ret->name);
+        xmlFree(ret);
+        return (NULL);
+    }
+    return (ret);
+}
+
+
+/**
+ * xmlSchemaAddAttribute:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @name:  the item name
+ * @container:  the container's name
+ *
+ * Add an XML schema Attrribute declaration
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the new struture or NULL in case of error
+ */
+static xmlSchemaAttributePtr
+xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                      const xmlChar * name)
+{
+    xmlSchemaAttributePtr ret = NULL;
+    int val;
+
+    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
+        return (NULL);
+
+    if (schema->attrDecl == NULL)
+        schema->attrDecl = xmlHashCreate(10);
+    if (schema->attrDecl == NULL)
+        return (NULL);
+
+    ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
+    if (ret == NULL) {
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Out of memory\n");
+        return (NULL);
+    }
+    memset(ret, 0, sizeof(xmlSchemaAttribute));
+    ret->name = xmlStrdup(name);
+    val = xmlHashAddEntry3(schema->attrDecl, name,
+	                   schema->targetNamespace, ctxt->container, ret);
+    if (val != 0) {
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Could not add attribute %s\n",
+                        name);
+        xmlFree((char *) ret->name);
+        xmlFree(ret);
+        return (NULL);
+    }
+    return (ret);
+}
+
+/**
+ * xmlSchemaAddAttributeGroup:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @name:  the item name
+ *
+ * Add an XML schema Attrribute Group declaration
+ *
+ * Returns the new struture or NULL in case of error
+ */
+static xmlSchemaAttributeGroupPtr
+xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                           const xmlChar * name)
+{
+    xmlSchemaAttributeGroupPtr ret = NULL;
+    int val;
+
+    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
+        return (NULL);
+
+    if (schema->attrgrpDecl == NULL)
+        schema->attrgrpDecl = xmlHashCreate(10);
+    if (schema->attrgrpDecl == NULL)
+        return (NULL);
+
+    ret = (xmlSchemaAttributeGroupPtr) xmlMalloc(sizeof(xmlSchemaAttributeGroup));
+    if (ret == NULL) {
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Out of memory\n");
+        return (NULL);
+    }
+    memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
+    ret->name = xmlStrdup(name);
+    val = xmlHashAddEntry3(schema->attrgrpDecl, name,
+	                   schema->targetNamespace, ctxt->container, ret);
+    if (val != 0) {
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Could not add attribute group %s\n",
+                        name);
+        xmlFree((char *) ret->name);
+        xmlFree(ret);
+        return (NULL);
+    }
+    return (ret);
+}
+
+/**
+ * xmlSchemaAddElement:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @name:  the type name
+ * @namespace:  the type namespace
+ *
+ * Add an XML schema Element declaration
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the new struture or NULL in case of error
+ */
+static xmlSchemaElementPtr
+xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                    const xmlChar * name, const xmlChar * namespace)
+{
+    xmlSchemaElementPtr ret = NULL;
+    int val;
+
+    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
+        return (NULL);
+
+    if (schema->elemDecl == NULL)
+        schema->elemDecl = xmlHashCreate(10);
+    if (schema->elemDecl == NULL)
+        return (NULL);
+
+    ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
+    if (ret == NULL) {
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Out of memory\n");
+        return (NULL);
+    }
+    memset(ret, 0, sizeof(xmlSchemaElement));
+    ret->name = xmlStrdup(name);
+    val = xmlHashAddEntry3(schema->elemDecl, name,
+	                   namespace, ctxt->container, ret);
+    if (val != 0) {
+	char buf[100];
+
+	snprintf(buf, 99, "privatieelem%d", ctxt->counter++ + 1);
+	val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
+			       namespace, ret);
+	if (val != 0) {
+	    if ((ctxt != NULL) && (ctxt->error != NULL))
+		ctxt->error(ctxt->userData, "Could not add element %s\n",
+			    name);
+	    xmlFree((char *) ret->name);
+	    xmlFree(ret);
+	    return (NULL);
+	}
+    }
+    return (ret);
+}
+
+/**
+ * xmlSchemaAddType:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @name:  the item name
+ *
+ * Add an XML schema Simple Type definition
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the new struture or NULL in case of error
+ */
+static xmlSchemaTypePtr
+xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                 const xmlChar * name)
+{
+    xmlSchemaTypePtr ret = NULL;
+    int val;
+
+    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
+        return (NULL);
+
+    if (schema->typeDecl == NULL)
+        schema->typeDecl = xmlHashCreate(10);
+    if (schema->typeDecl == NULL)
+        return (NULL);
+
+    ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
+    if (ret == NULL) {
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Out of memory\n");
+        return (NULL);
+    }
+    memset(ret, 0, sizeof(xmlSchemaType));
+    ret->name = xmlStrdup(name);
+    val = xmlHashAddEntry2(schema->typeDecl, name, schema->targetNamespace,
+                           ret);
+    if (val != 0) {
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Could not add type %s\n", name);
+        xmlFree((char *) ret->name);
+        xmlFree(ret);
+        return (NULL);
+    }
+    ret->minOccurs = 1;
+    ret->maxOccurs = 1;
+
+    return (ret);
+}
+
+/************************************************************************
+ * 									*
+ *		Utilities for parsing					*
+ * 									*
+ ************************************************************************/
+
+/**
+ * xmlGetQNameProp:
+ * @ctxt:  a schema validation context
+ * @node:  a subtree containing XML Schema informations
+ * @name:  the attribute name
+ * @namespace:  the result namespace if any
+ *
+ * Extract a QName Attribute value
+ *
+ * Returns the NCName or NULL if not found, and also update @namespace
+ *    with the namespace URI
+ */
+static xmlChar *
+xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
+	        const char *name,
+		xmlChar **namespace) {
+    xmlChar *val, *ret, *prefix;
+    xmlNsPtr ns;
+
+
+    if (namespace != NULL)
+	*namespace = NULL;
+    val = xmlGetProp(node, (const xmlChar *) name);
+    if (val == NULL)
+	return(NULL);
+
+    ret = xmlSplitQName2(val, &prefix);
+    if (ret == NULL)
+	return(val);
+    xmlFree(val);
+
+    ns = xmlSearchNs(node->doc, node, prefix);
+    if (ns == NULL) {
+	xmlSchemaErrorContext(ctxt, NULL, node, NULL);
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData,
+		    "Attribute %s: the QName prefix %s is undefined\n",
+		        name, prefix);
+    } else {
+	*namespace = xmlStrdup(ns->href);
+    }
+    xmlFree(prefix);
+    return(ret);
+}
+
+/**
+ * xmlGetMaxOccurs:
+ * @ctxt:  a schema validation context
+ * @node:  a subtree containing XML Schema informations
+ *
+ * Get the maxOccurs property
+ *
+ * Returns the default if not found, or the value
+ */
+static int
+xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) {
+    xmlChar *val, *cur;
+    int ret = 0;
+
+    val = xmlGetProp(node, (const xmlChar *) "maxOccurs");
+    if (val == NULL)
+	return(1);
+
+    if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
+	xmlFree(val);
+	return(UNBOUNDED); /* encoding it with -1 might be another option */
+    }
+
+    cur = val;
+    while (IS_BLANK(*cur)) cur++;
+    while ((*cur >= '0') && (*cur <= '9')) {
+	ret = ret * 10 + (*cur - '0');
+	cur++;
+    }
+    while (IS_BLANK(*cur)) cur++;
+    if (*cur != 0) {
+	xmlSchemaErrorContext(ctxt, NULL, node, NULL);
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "invalid value for minOccurs: %s\n",
+		        val);
+	xmlFree(val);
+	return(1);
+    }
+    xmlFree(val);
+    return(ret);
+}
+
+/**
+ * xmlGetMinOccurs:
+ * @ctxt:  a schema validation context
+ * @node:  a subtree containing XML Schema informations
+ *
+ * Get the minOccurs property
+ *
+ * Returns the default if not found, or the value
+ */
+static int
+xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) {
+    xmlChar *val, *cur;
+    int ret = 0;
+
+    val = xmlGetProp(node, (const xmlChar *) "minOccurs");
+    if (val == NULL)
+	return(1);
+
+    cur = val;
+    while (IS_BLANK(*cur)) cur++;
+    while ((*cur >= '0') && (*cur <= '9')) {
+	ret = ret * 10 + (*cur - '0');
+	cur++;
+    }
+    while (IS_BLANK(*cur)) cur++;
+    if (*cur != 0) {
+	xmlSchemaErrorContext(ctxt, NULL, node, NULL);
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "invalid value for minOccurs: %s\n",
+		        val);
+	xmlFree(val);
+	return(1);
+    }
+    xmlFree(val);
+    return(ret);
+}
+
+/**
+ * xmlGetBooleanProp:
+ * @ctxt:  a schema validation context
+ * @node:  a subtree containing XML Schema informations
+ * @name:  the attribute name
+ * @def:  the default value
+ *
+ * Get is a bolean property is set
+ *
+ * Returns the default if not found, 0 if found to be false,
+ *         1 if found to be true
+ */
+static int
+xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
+	          const char *name, int def) {
+    xmlChar *val;
+
+    val = xmlGetProp(node, (const xmlChar *) name);
+    if (val == NULL)
+	return(def);
+
+    if (xmlStrEqual(val, BAD_CAST"true"))
+	def = 1;
+    else if (xmlStrEqual(val, BAD_CAST"false"))
+	def = 0;
+    else {
+	xmlSchemaErrorContext(ctxt, NULL, node, NULL);
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData,
+		    "Attribute %s: the value %s is not boolean\n",
+		        name, val);
+    }
+    xmlFree(val);
+    return(def);
+}
+
+/************************************************************************
+ * 									*
+ *		Shema extraction from an Infoset			*
+ * 									*
+ ************************************************************************/
+static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
+                                                 ctxt, xmlSchemaPtr schema,
+                                                 xmlNodePtr node);
+static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,
+                                                  xmlSchemaPtr schema,
+                                                  xmlNodePtr node);
+static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,
+                                                  xmlSchemaPtr schema,
+                                                  xmlNodePtr node,
+						  int simple);
+static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
+                                               xmlSchemaPtr schema,
+                                               xmlNodePtr node);
+static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
+                                          xmlSchemaPtr schema,
+                                          xmlNodePtr node);
+static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
+                                                     ctxt,
+                                                     xmlSchemaPtr schema,
+                                                     xmlNodePtr node);
+static xmlSchemaAttributeGroupPtr
+xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
+                             xmlSchemaPtr schema, xmlNodePtr node);
+static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
+                                             xmlSchemaPtr schema,
+                                             xmlNodePtr node);
+static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
+                                           xmlSchemaPtr schema,
+                                           xmlNodePtr node);
+static xmlSchemaAttributePtr
+xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                           xmlNodePtr node);
+
+/**
+ * xmlSchemaParseAttrDecls:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ * @type:  the hosting type
+ *
+ * parse a XML schema attrDecls declaration corresponding to
+ * <!ENTITY % attrDecls  
+ *       '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
+ */
+static xmlNodePtr
+xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                        xmlNodePtr child, xmlSchemaTypePtr type)
+{
+    xmlSchemaAttributePtr lastattr, attr;
+
+    lastattr = NULL;
+    while ((IS_SCHEMA(child, "attribute")) ||
+	   (IS_SCHEMA(child, "attributeGroup"))) {
+	attr = NULL;
+	if (IS_SCHEMA(child, "attribute")) {
+	    attr = xmlSchemaParseAttribute(ctxt, schema, child);
+	} else if (IS_SCHEMA(child, "attributeGroup")) {
+	    attr = (xmlSchemaAttributePtr)
+		xmlSchemaParseAttributeGroup(ctxt, schema, child);
+	}
+	if (attr != NULL) {
+	    if (lastattr == NULL) {
+		type->attributes = attr;
+		lastattr = attr
+		          ;
+	    } else {
+		lastattr->next = attr;
+		lastattr = attr;
+	    }
+	}
+	child = child->next;
+    }
+    if (IS_SCHEMA(child, "anyAttribute")) {
+	attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
+	if (attr != NULL) {
+	    if (lastattr == NULL) {
+		type->attributes = attr;
+		lastattr = attr
+		          ;
+	    } else {
+		lastattr->next = attr;
+		lastattr = attr;
+	    }
+	}
+	child = child->next;
+    }
+    return(child);
+}
+
+/**
+ * xmlSchemaParseAnnotation:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Attrribute declaration
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns -1 in case of error, 0 if the declaration is inproper and
+ *         1 in case of success.
+ */
+static xmlSchemaAnnotPtr
+xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                         xmlNodePtr node)
+{
+    xmlSchemaAnnotPtr ret;
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+    ret = xmlSchemaNewAnnot(ctxt, node);
+
+    return (ret);
+}
+
+/**
+ * xmlSchemaParseFacet:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Facet declaration
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the new type structure or NULL in case of error
+ */
+static xmlSchemaFacetPtr
+xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                  xmlNodePtr node)
+{
+    xmlSchemaFacetPtr facet;
+    xmlNodePtr child = NULL;
+    xmlChar *value;
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+
+    facet = xmlSchemaNewFacet(ctxt);
+    if (facet == NULL)
+	return (NULL);
+    facet->node = node;
+    value = xmlGetProp(node, (const xmlChar *) "value");
+    if (value == NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Facet %s has no value\n", node->name);
+	xmlSchemaFreeFacet(facet);
+        return (NULL);
+    }
+    if (IS_SCHEMA(node, "minInclusive"))  {
+        facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
+    } else if (IS_SCHEMA(node, "minExclusive"))  {
+        facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
+    } else if (IS_SCHEMA(node, "maxInclusive"))  {
+        facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
+    } else if (IS_SCHEMA(node, "maxExclusive"))  {
+        facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
+    } else if (IS_SCHEMA(node, "totalDigits"))  {
+        facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
+    } else if (IS_SCHEMA(node, "fractionDigits"))  {
+        facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
+    } else if (IS_SCHEMA(node, "pattern"))  {
+        facet->type = XML_SCHEMA_FACET_PATTERN;
+    } else if (IS_SCHEMA(node, "enumeration"))  {
+        facet->type = XML_SCHEMA_FACET_ENUMERATION;
+    } else if (IS_SCHEMA(node, "whiteSpace"))  {
+        facet->type = XML_SCHEMA_FACET_WHITESPACE;
+    } else if (IS_SCHEMA(node, "length"))  {
+        facet->type = XML_SCHEMA_FACET_LENGTH;
+    } else if (IS_SCHEMA(node, "maxLength"))  {
+        facet->type = XML_SCHEMA_FACET_MAXLENGTH;
+    } else if (IS_SCHEMA(node, "minLength")) {
+        facet->type = XML_SCHEMA_FACET_MINLENGTH;
+    } else {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Unknown facet type %s\n", node->name);
+	xmlSchemaFreeFacet(facet);
+	return(NULL);
+    }
+    facet->id = xmlGetProp(node, (const xmlChar *) "id");
+    facet->value = value;
+    child = node->children;
+
+    if (IS_SCHEMA(child, "annotation")) {
+	facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"Facet %s has unexpected child content\n",
+			node->name);
+    }
+    return (facet);
+}
+
+/**
+ * xmlSchemaParseAny:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Any declaration
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the new type structure or NULL in case of error
+ */
+static xmlSchemaTypePtr
+xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                  xmlNodePtr node)
+{
+    xmlSchemaTypePtr type;
+    xmlNodePtr child = NULL;
+    xmlChar name[30];
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+    snprintf((char *)name, 30, "any %d", ctxt->counter++ + 1);
+    type = xmlSchemaAddType(ctxt, schema, name);
+    if (type == NULL)
+	return (NULL);
+    type->node = node;
+    type->type = XML_SCHEMA_TYPE_ANY;
+    child = node->children;
+    type->minOccurs = xmlGetMinOccurs(ctxt, node);
+    type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
+
+    if (IS_SCHEMA(child, "annotation")) {
+	type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"Sequence %s has unexpected content\n",
+			type->name);
+    }
+
+    return (type);
+}
+
+/**
+ * xmlSchemaParseNotation:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Notation declaration
+ *
+ * Returns the new structure or NULL in case of error
+ */
+static xmlSchemaNotationPtr
+xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                        xmlNodePtr node)
+{
+    xmlChar *name;
+    xmlSchemaNotationPtr ret;
+    xmlNodePtr child = NULL;
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+    name = xmlGetProp(node, (const xmlChar *) "name");
+    if (name == NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "Notation has no name\n");
+        return (NULL);
+    }
+    ret = xmlSchemaAddNotation(ctxt, schema, name);
+    if (ret == NULL) {
+        xmlFree(name);
+        return (NULL);
+    }
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"notation %s has unexpected content\n",
+			name);
+    }
+
+    return (ret);
+}
+
+/**
+ * xmlSchemaParseAnyAttribute:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema AnyAttrribute declaration
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns an attribute def structure or NULL
+ */
+static xmlSchemaAttributePtr
+xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                        xmlNodePtr node)
+{
+    xmlChar *processContents;
+    xmlSchemaAttributePtr ret;
+    xmlNodePtr child = NULL;
+    char name[100];
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+
+    snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
+    ret = xmlSchemaAddAttribute(ctxt, schema, (xmlChar *)name);
+    if (ret == NULL) {
+        return (NULL);
+    }
+    ret->id = xmlGetProp(node, (const xmlChar *) "id");
+    processContents = xmlGetProp(node, (const xmlChar *) "processContents");
+    if ((processContents == NULL) ||
+	(xmlStrEqual(processContents, (const xmlChar *)"strict"))) {
+	ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
+    } else if (xmlStrEqual(processContents, (const xmlChar *)"skip")) {
+	ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
+    } else if (xmlStrEqual(processContents, (const xmlChar *)"lax")) {
+	ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
+    } else {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+	    "anyAttribute has unexpected content for processContents: %s\n",
+			processContents);
+	ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
+    }
+    if (processContents != NULL)
+	xmlFree(processContents);
+
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"anyAttribute %s has unexpected content\n",
+			name);
+    }
+
+    return (ret);
+}
+
+
+/**
+ * xmlSchemaParseAttribute:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Attrribute declaration
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns -1 in case of error, 0 if the declaration is inproper and
+ *         1 in case of success.
+ */
+static xmlSchemaAttributePtr
+xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                        xmlNodePtr node)
+{
+    xmlChar *name, *refNs = NULL, *ref = NULL;
+    xmlSchemaAttributePtr ret;
+    xmlNodePtr child = NULL;
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+    name = xmlGetProp(node, (const xmlChar *) "name");
+    if (name == NULL) {
+	char buf[100];
+
+	ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
+	if (ref == NULL) {
+	    xmlSchemaErrorContext(ctxt, schema, node, child);
+	    if ((ctxt != NULL) && (ctxt->error != NULL))
+		ctxt->error(ctxt->userData, "Attribute has no name nor ref\n");
+	    return (NULL);
+	}
+	snprintf(buf, 99, "anonattr%d", ctxt->counter++ + 1);
+	name = xmlStrdup((xmlChar *) buf);
+    }
+    ret = xmlSchemaAddAttribute(ctxt, schema, name);
+    if (ret == NULL) {
+        xmlFree(name);
+	if (ref != NULL)
+	    xmlFree(ref);
+        return (NULL);
+    }
+    xmlFree(name);
+    ret->ref = ref;
+    ret->refNs = refNs;
+    ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    if (IS_SCHEMA(child, "simpleType")) {
+	ret->base = xmlSchemaParseSimpleType(ctxt, schema, child);
+	child = child->next;
+    }
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"attribute %s has unexpected content\n",
+			name);
+    }
+
+    return (ret);
+}
+
+/**
+ * xmlSchemaParseAttributeGroup:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Attribute Group declaration
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the attribute group or NULL in case of error.
+ */
+static xmlSchemaAttributeGroupPtr
+xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                             xmlNodePtr node)
+{
+    xmlChar *name, *refNs = NULL, *ref = NULL;
+    xmlSchemaAttributeGroupPtr ret;
+    xmlSchemaAttributePtr last = NULL, attr;
+    xmlNodePtr child = NULL;
+    xmlChar *oldcontainer;
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+    oldcontainer = ctxt->container;
+    name = xmlGetProp(node, (const xmlChar *) "name");
+    if (name == NULL) {
+	char buf[100];
+
+	ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
+	if (ref == NULL) {
+	    xmlSchemaErrorContext(ctxt, schema, node, child);
+	    if ((ctxt != NULL) && (ctxt->error != NULL))
+		ctxt->error(ctxt->userData,
+			"AttributeGroup has no name nor ref\n");
+	    return (NULL);
+	}
+	snprintf(buf, 99, "anonattrgroup%d", ctxt->counter++ + 1);
+	name = xmlStrdup((xmlChar *) buf);
+    }
+    ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
+    if (ret == NULL) {
+        xmlFree(name);
+	if (ref != NULL)
+	    xmlFree(ref);
+        return (NULL);
+    }
+    ret->ref = ref;
+    ret->refNs = refNs;
+    child = node->children;
+    ctxt->container = name;
+    if (IS_SCHEMA(child, "annotation")) {
+	ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    while ((IS_SCHEMA(child, "attribute")) ||
+	   (IS_SCHEMA(child, "attributeGroup"))) {
+	attr = NULL;
+	if (IS_SCHEMA(child, "attribute")) {
+	    attr = xmlSchemaParseAttribute(ctxt, schema, child);
+	} else if (IS_SCHEMA(child, "attributeGroup")) {
+	    attr = (xmlSchemaAttributePtr)
+		xmlSchemaParseAttributeGroup(ctxt, schema, child);
+	}
+	if (attr != NULL) {
+	    if (last == NULL) {
+		ret->attributes = attr;
+		last = attr;
+	    } else {
+		last->next = attr;
+		last = attr;
+	    }
+	}
+	child = child->next;
+    }
+    if (IS_SCHEMA(child, "anyAttribute")) {
+	TODO
+	child = child->next;
+    }
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"attribute group %s has unexpected content\n",
+			name);
+    }
+
+    ctxt->container = oldcontainer;
+    return (ret);
+}
+
+/**
+ * xmlSchemaParseElement:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Element declaration
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns -1 in case of error, 0 if the declaration is inproper and
+ *         1 in case of success.
+ */
+static xmlSchemaElementPtr
+xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                      xmlNodePtr node, int toplevel)
+{
+    xmlChar *name, *refNs = NULL, *ref = NULL, *namespace, *fixed;
+    xmlSchemaElementPtr ret;
+    xmlNodePtr child = NULL;
+    xmlChar *oldcontainer;
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+    oldcontainer = ctxt->container;
+    name = xmlGetProp(node, (const xmlChar *) "name");
+    if (name == NULL) {
+	char buf[100];
+
+	ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
+	if (ref == NULL) {
+	    xmlSchemaErrorContext(ctxt, schema, node, child);
+	    if ((ctxt != NULL) && (ctxt->error != NULL))
+		ctxt->error(ctxt->userData, "Element has no name nor ref\n");
+	    return (NULL);
+	}
+	snprintf(buf, 99, "anonelem%d", ctxt->counter++ + 1);
+	name = xmlStrdup((xmlChar *) buf);
+    }
+    namespace = xmlGetProp(node, (const xmlChar *) "targetNamespace");
+    if (namespace == NULL)
+        ret =
+            xmlSchemaAddElement(ctxt, schema, name,
+                                schema->targetNamespace);
+    else
+        ret = xmlSchemaAddElement(ctxt, schema, name, namespace);
+    if (namespace != NULL)
+        xmlFree(namespace);
+    if (ret == NULL) {
+	xmlFree(name);
+	if (ref != NULL)
+	    xmlFree(ref);
+        return (NULL);
+    }
+    ret->type = XML_SCHEMA_TYPE_ELEMENT;
+    ret->ref = ref;
+    ret->refNs = refNs;
+    if (ref != NULL)
+        ret->flags |= XML_SCHEMAS_ELEM_REF;
+    if (toplevel)
+        ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
+    if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
+        ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
+    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
+        ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
+    ctxt->container = name;
+
+    ret->id = xmlGetProp(node, BAD_CAST "id");
+    ret->namedType = xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
+    ret->substGroup = xmlGetQNameProp(ctxt, node, "substitutionGroup",
+	                              &(ret->substGroupNs));
+    fixed = xmlGetProp(node, BAD_CAST "fixed");
+    ret->minOccurs = xmlGetMinOccurs(ctxt, node);
+    ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
+    
+    ret->value = xmlGetProp(node, BAD_CAST "default");
+    if ((ret->value != NULL) && (fixed != NULL)) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	ctxt->error(ctxt->userData,
+		    "Element %s has both default and fixed\n",
+		    ret->name);
+	xmlFree(fixed);
+    } else if (fixed != NULL) {
+        ret->flags |= XML_SCHEMAS_ELEM_FIXED;
+	ret->value = fixed;
+    }
+
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    if (IS_SCHEMA(child, "complexType")) {
+	ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
+        child = child->next;
+    } else if (IS_SCHEMA(child, "simpleType")) {
+	ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
+        child = child->next;
+    }
+    while ((IS_SCHEMA(child, "unique")) ||
+	   (IS_SCHEMA(child, "key")) ||
+	   (IS_SCHEMA(child, "keyref"))) {
+	TODO
+	child = child->next;
+    }
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"element %s has unexpected content\n",
+			name);
+    }
+
+    ctxt->container = oldcontainer;
+    xmlFree(name);
+    return (ret);
+}
+
+/**
+ * xmlSchemaParseUnion:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Union definition
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns -1 in case of error, 0 if the declaration is inproper and
+ *         1 in case of success.
+ */
+static xmlSchemaTypePtr
+xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                         xmlNodePtr node)
+{
+    xmlSchemaTypePtr type, subtype, last = NULL;
+    xmlNodePtr child = NULL;
+    xmlChar name[30];
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+
+
+    snprintf((char *)name, 30, "union %d", ctxt->counter++ + 1);
+    type = xmlSchemaAddType(ctxt, schema, name);
+    if (type == NULL)
+        return (NULL);
+    type->node = node;
+    type->type = XML_SCHEMA_TYPE_LIST;
+    type->id = xmlGetProp(node, BAD_CAST "id");
+    type->ref = xmlGetProp(node, BAD_CAST "memberTypes");
+
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    while (IS_SCHEMA(child, "simpleType")) {
+	subtype = (xmlSchemaTypePtr) 
+	      xmlSchemaParseSimpleType(ctxt, schema, child);
+	if (subtype != NULL) {
+	    if (last == NULL) {
+		type->subtypes = subtype;
+		last = subtype;
+	    } else {
+		last->next = subtype;
+		last = subtype;
+	    }
+	    last->next = NULL;
+	}
+	child = child->next;
+    }
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"Union %s has unexpected content\n",
+			type->name);
+    }
+    return (type);
+}
+
+/**
+ * xmlSchemaParseList:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema List definition
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns -1 in case of error, 0 if the declaration is inproper and
+ *         1 in case of success.
+ */
+static xmlSchemaTypePtr
+xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                         xmlNodePtr node)
+{
+    xmlSchemaTypePtr type, subtype;
+    xmlNodePtr child = NULL;
+    xmlChar name[30];
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+
+    snprintf((char *)name, 30, "list %d", ctxt->counter++ + 1);
+    type = xmlSchemaAddType(ctxt, schema, name);
+    if (type == NULL)
+        return (NULL);
+    type->node = node;
+    type->type = XML_SCHEMA_TYPE_LIST;
+    type->id = xmlGetProp(node, BAD_CAST "id");
+    type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
+
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    subtype = NULL;
+    if (IS_SCHEMA(child, "simpleType")) {
+	subtype = (xmlSchemaTypePtr) 
+	      xmlSchemaParseSimpleType(ctxt, schema, child);
+	child = child->next;
+	type->subtypes = subtype;
+    }
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"List %s has unexpected content\n",
+			type->name);
+    }
+    return (type);
+}
+/**
+ * xmlSchemaParseSimpleType:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Simple Type definition
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns -1 in case of error, 0 if the declaration is inproper and
+ *         1 in case of success.
+ */
+static xmlSchemaTypePtr
+xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                         xmlNodePtr node)
+{
+    xmlSchemaTypePtr type, subtype;
+    xmlNodePtr child = NULL;
+    xmlChar *name;
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+
+
+    name = xmlGetProp(node, (const xmlChar *) "name");
+    if (name == NULL) {
+	char buf[100];
+
+	snprintf(buf, 99, "simpletype%d", ctxt->counter++ + 1);
+	name = xmlStrdup((xmlChar *) buf);
+    }
+    if (name == NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "simpleType has no name\n");
+        return (NULL);
+    }
+    type = xmlSchemaAddType(ctxt, schema, name);
+    xmlFree(name);
+    if (type == NULL)
+        return (NULL);
+    type->node = node;
+    type->type = XML_SCHEMA_TYPE_SIMPLE;
+    type->id = xmlGetProp(node, BAD_CAST "id");
+
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    subtype = NULL;
+    if (IS_SCHEMA(child, "restriction")) {
+	subtype = (xmlSchemaTypePtr) 
+	      xmlSchemaParseRestriction(ctxt, schema, child, 1);
+	child = child->next;
+    } else if (IS_SCHEMA(child, "list")) {
+	subtype = (xmlSchemaTypePtr) 
+	      xmlSchemaParseList(ctxt, schema, child);
+	child = child->next;
+    } else if (IS_SCHEMA(child, "union")) {
+	subtype = (xmlSchemaTypePtr) 
+	      xmlSchemaParseUnion(ctxt, schema, child);
+	child = child->next;
+    }
+    type->subtypes = subtype;
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"SimpleType %s has unexpected content\n",
+			type->name);
+    }
+
+    return (type);
+}
+
+
+/**
+ * xmlSchemaParseGroup:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Group definition
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns -1 in case of error, 0 if the declaration is inproper and
+ *         1 in case of success.
+ */
+static xmlSchemaTypePtr
+xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                          xmlNodePtr node)
+{
+    xmlSchemaTypePtr type, subtype;
+    xmlNodePtr child = NULL;
+    xmlChar *name, *ref = NULL, *refNs = NULL;
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+
+
+    name = xmlGetProp(node, (const xmlChar *) "name");
+    if (name == NULL) {
+	char buf[100];
+
+	ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
+	if (ref == NULL) {
+	    xmlSchemaErrorContext(ctxt, schema, node, child);
+	    if ((ctxt != NULL) && (ctxt->error != NULL))
+		ctxt->error(ctxt->userData, "Group has no name nor ref\n");
+	    return (NULL);
+	}
+	snprintf(buf, 99, "anongroup%d", ctxt->counter++ + 1);
+	name = xmlStrdup((xmlChar *) buf);
+    }
+    type = xmlSchemaAddType(ctxt, schema, name);
+    if (type == NULL)
+        return (NULL);
+    type->node = node;
+    type->type = XML_SCHEMA_TYPE_GROUP;
+    type->id = xmlGetProp(node, BAD_CAST "id");
+    type->ref = ref;
+    type->refNs = refNs;
+    type->minOccurs = xmlGetMinOccurs(ctxt, node);
+    type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
+
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    subtype = NULL;
+    if (IS_SCHEMA(child, "all")) {
+	subtype = (xmlSchemaTypePtr) 
+	      xmlSchemaParseAll(ctxt, schema, child);
+	child = child->next;
+    } else if (IS_SCHEMA(child, "choice")) {
+	subtype = xmlSchemaParseChoice(ctxt, schema, child);
+	child = child->next;
+    } else if (IS_SCHEMA(child, "sequence")) {
+	subtype = (xmlSchemaTypePtr)
+	      xmlSchemaParseSequence(ctxt, schema, child);
+	child = child->next;
+    }
+    if (subtype != NULL)
+	type->subtypes = subtype;
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"Group %s has unexpected content\n",
+			type->name);
+    }
+
+    return (type);
+}
+
+/**
+ * xmlSchemaParseAll:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema All definition
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns -1 in case of error, 0 if the declaration is inproper and
+ *         1 in case of success.
+ */
+static xmlSchemaTypePtr
+xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                          xmlNodePtr node)
+{
+    xmlSchemaTypePtr type, subtype, last = NULL;
+    xmlNodePtr child = NULL;
+    xmlChar name[30];
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+
+
+    snprintf((char *)name, 30, "all%d", ctxt->counter++ + 1);
+    type = xmlSchemaAddType(ctxt, schema, name);
+    if (type == NULL)
+        return (NULL);
+    type->node = node;
+    type->type = XML_SCHEMA_TYPE_SEQUENCE;
+    type->id = xmlGetProp(node, BAD_CAST "id");
+    type->minOccurs = xmlGetMinOccurs(ctxt, node);
+    type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
+
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    while (IS_SCHEMA(child, "element")) {
+	subtype = (xmlSchemaTypePtr) 
+	      xmlSchemaParseElement(ctxt, schema, child, 0);
+	if (subtype != NULL) {
+	    if (last == NULL) {
+		type->subtypes = subtype;
+		last = subtype;
+	    } else {
+		last->next = subtype;
+		last = subtype;
+	    }
+	    last->next = NULL;
+	}
+	child = child->next;
+    }
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"All %s has unexpected content\n",
+			type->name);
+    }
+
+    return (type);
+}
+
+/**
+ * xmlSchemaParseChoice:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Choice definition
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns -1 in case of error, 0 if the declaration is inproper and
+ *         1 in case of success.
+ */
+static xmlSchemaTypePtr
+xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                          xmlNodePtr node)
+{
+    xmlSchemaTypePtr type, subtype, last = NULL;
+    xmlNodePtr child = NULL;
+    xmlChar name[30];
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+
+
+    snprintf((char *)name, 30, "choice %d", ctxt->counter++ + 1);
+    type = xmlSchemaAddType(ctxt, schema, name);
+    if (type == NULL)
+        return (NULL);
+    type->node = node;
+    type->type = XML_SCHEMA_TYPE_CHOICE;
+    type->id = xmlGetProp(node, BAD_CAST "id");
+    type->minOccurs = xmlGetMinOccurs(ctxt, node);
+    type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
+
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    while ((IS_SCHEMA(child, "element")) ||
+	   (IS_SCHEMA(child, "group")) ||
+	   (IS_SCHEMA(child, "any")) ||
+	   (IS_SCHEMA(child, "choice")) ||
+	   (IS_SCHEMA(child, "sequence"))) {
+	subtype = NULL;
+	if (IS_SCHEMA(child, "element")) {
+	    subtype = (xmlSchemaTypePtr) 
+		  xmlSchemaParseElement(ctxt, schema, child, 0);
+	} else if (IS_SCHEMA(child, "group")) {
+	    subtype = xmlSchemaParseGroup(ctxt, schema, child);
+	} else if (IS_SCHEMA(child, "any")) {
+	    subtype = xmlSchemaParseAny(ctxt, schema, child);
+	} else if (IS_SCHEMA(child, "sequence")) {
+	    subtype = xmlSchemaParseSequence(ctxt, schema, child);
+	} else if (IS_SCHEMA(child, "choice")) {
+	    subtype = xmlSchemaParseChoice(ctxt, schema, child);
+	}
+	if (subtype != NULL) {
+	    if (last == NULL) {
+		type->subtypes = subtype;
+		last = subtype;
+	    } else {
+		last->next = subtype;
+		last = subtype;
+	    }
+	    last->next = NULL;
+	}
+	child = child->next;
+    }
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"Choice %s has unexpected content\n",
+			type->name);
+    }
+
+    return (type);
+}
+
+/**
+ * xmlSchemaParseSequence:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Sequence definition
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns -1 in case of error, 0 if the declaration is inproper and
+ *         1 in case of success.
+ */
+static xmlSchemaTypePtr
+xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                          xmlNodePtr node)
+{
+    xmlSchemaTypePtr type, subtype, last = NULL;
+    xmlNodePtr child = NULL;
+    xmlChar name[30];
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+
+
+    snprintf((char *)name, 30, "sequence %d", ctxt->counter++ + 1);
+    type = xmlSchemaAddType(ctxt, schema, name);
+    if (type == NULL)
+        return (NULL);
+    type->node = node;
+    type->type = XML_SCHEMA_TYPE_SEQUENCE;
+    type->id = xmlGetProp(node, BAD_CAST "id");
+    type->minOccurs = xmlGetMinOccurs(ctxt, node);
+    type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
+
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    while ((IS_SCHEMA(child, "element")) ||
+	   (IS_SCHEMA(child, "group")) ||
+	   (IS_SCHEMA(child, "any")) ||
+	   (IS_SCHEMA(child, "choice")) ||
+	   (IS_SCHEMA(child, "sequence"))) {
+	subtype = NULL;
+	if (IS_SCHEMA(child, "element")) {
+	    subtype = (xmlSchemaTypePtr) 
+		  xmlSchemaParseElement(ctxt, schema, child, 0);
+	} else if (IS_SCHEMA(child, "group")) {
+	    subtype = xmlSchemaParseGroup(ctxt, schema, child);
+	} else if (IS_SCHEMA(child, "any")) {
+	    subtype = xmlSchemaParseAny(ctxt, schema, child);
+	} else if (IS_SCHEMA(child, "choice")) {
+	    subtype = xmlSchemaParseChoice(ctxt, schema, child);
+	} else if (IS_SCHEMA(child, "sequence")) {
+	    subtype = xmlSchemaParseSequence(ctxt, schema, child);
+	}
+	if (subtype != NULL) {
+	    if (last == NULL) {
+		type->subtypes = subtype;
+		last = subtype;
+	    } else {
+		last->next = subtype;
+		last = subtype;
+	    }
+	    last->next = NULL;
+	}
+	child = child->next;
+    }
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"Sequence %s has unexpected content\n",
+			type->name);
+    }
+
+    return (type);
+}
+
+/**
+ * xmlSchemaParseRestriction:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ * @simple:  is that part of a simple type.
+ *
+ * parse a XML schema Restriction definition
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the type definition or NULL in case of error
+ */
+static xmlSchemaTypePtr
+xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                          xmlNodePtr node, int simple)
+{
+    xmlSchemaTypePtr type, subtype;
+    xmlSchemaFacetPtr facet, lastfacet = NULL;
+    xmlNodePtr child = NULL;
+    xmlChar name[30];
+    xmlChar *oldcontainer;
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+
+    oldcontainer = ctxt->container;
+
+    snprintf((char *)name, 30, "restriction %d", ctxt->counter++ + 1);
+    type = xmlSchemaAddType(ctxt, schema, name);
+    if (type == NULL)
+        return (NULL);
+    type->node = node;
+    type->type = XML_SCHEMA_TYPE_RESTRICTION;
+    type->id = xmlGetProp(node, BAD_CAST "id");
+    type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
+    if ((!simple) && (type->base == NULL)) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"Restriction %s has no base\n",
+			type->name);
+    }
+    ctxt->container = name;
+
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    subtype = NULL;
+
+    if (IS_SCHEMA(child, "all")) {
+	subtype = (xmlSchemaTypePtr) 
+	      xmlSchemaParseAll(ctxt, schema, child);
+	child = child->next;
+	type->subtypes = subtype;
+    } else if (IS_SCHEMA(child, "choice")) {
+	subtype = xmlSchemaParseChoice(ctxt, schema, child);
+	child = child->next;
+	type->subtypes = subtype;
+    } else if (IS_SCHEMA(child, "sequence")) {
+	subtype = (xmlSchemaTypePtr) 
+	      xmlSchemaParseSequence(ctxt, schema, child);
+	child = child->next;
+	type->subtypes = subtype;
+    } else if (IS_SCHEMA(child, "group")) {
+	subtype = (xmlSchemaTypePtr) 
+	      xmlSchemaParseGroup(ctxt, schema, child);
+	child = child->next;
+	type->subtypes = subtype;
+    } else {
+	if (IS_SCHEMA(child, "simpleType")) {
+	    subtype = (xmlSchemaTypePtr) 
+		  xmlSchemaParseSimpleType(ctxt, schema, child);
+	    child = child->next;
+	    type->baseType = subtype;
+	}
+	/*
+	 * Facets
+	 */
+        while ((IS_SCHEMA(child, "minInclusive")) ||
+	       (IS_SCHEMA(child, "minExclusive")) ||
+	       (IS_SCHEMA(child, "maxInclusive")) ||
+	       (IS_SCHEMA(child, "maxExclusive")) ||
+	       (IS_SCHEMA(child, "totalDigits")) ||
+	       (IS_SCHEMA(child, "fractionDigits")) ||
+	       (IS_SCHEMA(child, "pattern")) ||
+	       (IS_SCHEMA(child, "enumeration")) ||
+	       (IS_SCHEMA(child, "whiteSpace")) ||
+	       (IS_SCHEMA(child, "length")) ||
+	       (IS_SCHEMA(child, "maxLength")) ||
+	       (IS_SCHEMA(child, "minLength"))) {
+	    facet = xmlSchemaParseFacet(ctxt, schema, child);
+	    if (facet != NULL) {
+		if (lastfacet == NULL) {
+		    type->facets = facet;
+		    lastfacet = facet;
+		} else {
+		    lastfacet->next = facet;
+		    lastfacet = facet;
+		}
+		lastfacet->next = NULL;
+	    }
+	    child = child->next;
+	}
+    }
+    child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"Restriction %s has unexpected content\n",
+			type->name);
+    }
+    ctxt->container = oldcontainer;
+    return (type);
+}
+
+/**
+ * xmlSchemaParseExtension:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Extension definition
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the type definition or NULL in case of error
+ */
+static xmlSchemaTypePtr
+xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                          xmlNodePtr node)
+{
+    xmlSchemaTypePtr type, subtype;
+    xmlNodePtr child = NULL;
+    xmlChar name[30];
+    xmlChar *oldcontainer;
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+
+    oldcontainer = ctxt->container;
+
+    snprintf((char *)name, 30, "extension %d", ctxt->counter++ + 1);
+    type = xmlSchemaAddType(ctxt, schema, name);
+    if (type == NULL)
+        return (NULL);
+    type->node = node;
+    type->type = XML_SCHEMA_TYPE_EXTENSION;
+    type->id = xmlGetProp(node, BAD_CAST "id");
+    ctxt->container = name;
+
+    type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
+    if (type->base == NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"Extension %s has no base\n",
+			type->name);
+    }
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    subtype = NULL;
+
+    if (IS_SCHEMA(child, "all")) {
+	subtype = xmlSchemaParseAll(ctxt, schema, child);
+	child = child->next;
+    } else if (IS_SCHEMA(child, "choice")) {
+	subtype = xmlSchemaParseChoice(ctxt, schema, child);
+	child = child->next;
+    } else if (IS_SCHEMA(child, "sequence")) {
+	subtype = xmlSchemaParseSequence(ctxt, schema, child);
+	child = child->next;
+    } else if (IS_SCHEMA(child, "group")) {
+	subtype = xmlSchemaParseGroup(ctxt, schema, child);
+	child = child->next;
+    }
+    if (subtype != NULL)
+	type->subtypes = subtype;
+    child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"Extension %s has unexpected content\n",
+			type->name);
+    }
+    ctxt->container = oldcontainer;
+    return (type);
+}
+
+/**
+ * xmlSchemaParseSimpleContent:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema SimpleContent definition
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the type definition or NULL in case of error
+ */
+static xmlSchemaTypePtr
+xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                          xmlNodePtr node)
+{
+    xmlSchemaTypePtr type, subtype;
+    xmlNodePtr child = NULL;
+    xmlChar name[30];
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+
+
+    snprintf((char *)name, 30, "complexContent %d", ctxt->counter++ + 1);
+    type = xmlSchemaAddType(ctxt, schema, name);
+    if (type == NULL)
+        return (NULL);
+    type->node = node;
+    type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
+    type->id = xmlGetProp(node, BAD_CAST "id");
+
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    subtype = NULL;
+    if (IS_SCHEMA(child, "restriction")) {
+	subtype = (xmlSchemaTypePtr) 
+	      xmlSchemaParseRestriction(ctxt, schema, child, 0);
+	child = child->next;
+    } else if (IS_SCHEMA(child, "extension")) {
+	subtype = (xmlSchemaTypePtr) 
+	      xmlSchemaParseExtension(ctxt, schema, child);
+	child = child->next;
+    }
+    type->subtypes = subtype;
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"SimpleContent %s has unexpected content\n",
+			type->name);
+    }
+    return (type);
+}
+
+/**
+ * xmlSchemaParseComplexContent:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema ComplexContent definition
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the type definition or NULL in case of error
+ */
+static xmlSchemaTypePtr
+xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                          xmlNodePtr node)
+{
+    xmlSchemaTypePtr type, subtype;
+    xmlNodePtr child = NULL;
+    xmlChar name[30];
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+
+
+    snprintf((char *)name, 30, "complexContent %d", ctxt->counter++ + 1);
+    type = xmlSchemaAddType(ctxt, schema, name);
+    if (type == NULL)
+        return (NULL);
+    type->node = node;
+    type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
+    type->id = xmlGetProp(node, BAD_CAST "id");
+
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    subtype = NULL;
+    if (IS_SCHEMA(child, "restriction")) {
+	subtype = (xmlSchemaTypePtr) 
+	      xmlSchemaParseRestriction(ctxt, schema, child, 0);
+	child = child->next;
+    } else if (IS_SCHEMA(child, "extension")) {
+	subtype = (xmlSchemaTypePtr) 
+	      xmlSchemaParseExtension(ctxt, schema, child);
+	child = child->next;
+    }
+    type->subtypes = subtype;
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"ComplexContent %s has unexpected content\n",
+			type->name);
+    }
+    return (type);
+}
+
+/**
+ * xmlSchemaParseComplexType:
+ * @ctxt:  a schema validation context
+ * @schema:  the schema being built
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema Complex Type definition
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the type definition or NULL in case of error
+ */
+static xmlSchemaTypePtr
+xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+                          xmlNodePtr node)
+{
+    xmlSchemaTypePtr type, subtype;
+    xmlNodePtr child = NULL;
+    xmlChar *name;
+    xmlChar *oldcontainer;
+
+    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+        return (NULL);
+
+    oldcontainer = ctxt->container;
+    name = xmlGetProp(node, (const xmlChar *) "name");
+    if (name == NULL) {
+	char buf[100];
+
+	snprintf(buf, 99, "anontype%d", ctxt->counter++ + 1);
+	name = xmlStrdup((xmlChar *) buf);
+    }
+    if (name == NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+        if ((ctxt != NULL) && (ctxt->error != NULL))
+            ctxt->error(ctxt->userData, "complexType has no name\n");
+        return (NULL);
+    }
+    type = xmlSchemaAddType(ctxt, schema, name);
+    if (type == NULL) {
+	xmlFree(name);
+        return (NULL);
+    }
+    type->node = node;
+    type->type = XML_SCHEMA_TYPE_COMPLEX;
+    type->id = xmlGetProp(node, BAD_CAST "id");
+    ctxt->container = name;
+
+    child = node->children;
+    if (IS_SCHEMA(child, "annotation")) {
+	type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
+	child = child->next;
+    }
+    if (IS_SCHEMA(child, "simpleContent")) {
+	subtype = xmlSchemaParseSimpleContent(ctxt, schema, child);
+	child = child->next;
+    } else if (IS_SCHEMA(child, "complexContent")) {
+	type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
+	child = child->next;
+    } else {
+	subtype = NULL;
+
+	if (IS_SCHEMA(child, "all")) {
+	    subtype = xmlSchemaParseAll(ctxt, schema, child);
+	    child = child->next;
+	} else if (IS_SCHEMA(child, "choice")) {
+	    subtype = xmlSchemaParseChoice(ctxt, schema, child);
+	    child = child->next;
+	} else if (IS_SCHEMA(child, "sequence")) {
+	    subtype = xmlSchemaParseSequence(ctxt, schema, child);
+	    child = child->next;
+	} else if (IS_SCHEMA(child, "group")) {
+	    subtype = xmlSchemaParseGroup(ctxt, schema, child);
+	    child = child->next;
+	}
+	if (subtype != NULL)
+	    type->subtypes = subtype;
+	child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
+    }
+    if (child != NULL) {
+	xmlSchemaErrorContext(ctxt, schema, node, child);
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+			"ComplexType %s has unexpected content\n",
+			type->name);
+    }
+    ctxt->container = oldcontainer;
+    xmlFree(name);
+    return (type);
+}
+
+
+/**
+ * xmlSchemaParseSchema:
+ * @ctxt:  a schema validation context
+ * @node:  a subtree containing XML Schema informations
+ *
+ * parse a XML schema definition from a node set
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the internal XML Schema structure built from the resource or
+ *         NULL in case of error
+ */
+static xmlSchemaPtr
+xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
+{
+    xmlSchemaPtr schema = NULL;
+    xmlSchemaAnnotPtr annot;
+    xmlNodePtr child = NULL;
+    xmlChar *val;
+
+    if ((ctxt == NULL) || (node == NULL))
+        return (NULL);
+
+    if (IS_SCHEMA(node, "schema")) {
+        schema = xmlSchemaNewSchema(ctxt);
+	if (schema == NULL)
+	    return(NULL);
+	schema->targetNamespace = xmlGetProp(node, BAD_CAST "targetNamespace");
+	schema->id = xmlGetProp(node, BAD_CAST "id");
+	schema->version = xmlGetProp(node, BAD_CAST "version");
+	val = xmlGetProp(node, BAD_CAST "elementFormDefault");
+	if (val != NULL) {
+	    if (xmlStrEqual(val, BAD_CAST "qualified"))
+		schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
+	    else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
+		xmlSchemaErrorContext(ctxt, schema, node, child);
+		if ((ctxt != NULL) && (ctxt->error != NULL)) {
+		    ctxt->error(ctxt->userData,
+				"Invalid value %s for elementFormDefault\n",
+				val);
+		}
+	    }
+	    xmlFree(val);
+	}
+	val = xmlGetProp(node, BAD_CAST "attributeFormDefault");
+	if (val != NULL) {
+	    if (xmlStrEqual(val, BAD_CAST "qualified"))
+		schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
+	    else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
+		xmlSchemaErrorContext(ctxt, schema, node, child);
+		if ((ctxt != NULL) && (ctxt->error != NULL)) {
+		    ctxt->error(ctxt->userData,
+				"Invalid value %s for elementFormDefault\n",
+				val);
+		}
+	    }
+	    xmlFree(val);
+	}
+
+        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")) {
+		TODO
+	    } 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 {
+		xmlSchemaErrorContext(ctxt, schema, node, child);
+		if ((ctxt != NULL) && (ctxt->error != NULL))
+		    ctxt->error(ctxt->userData,
+				"Schemas: unexpected element %s here \n",
+				child->name);
+		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;
+            }
+        }
+    }
+#ifdef DEBUG
+    if (schema == NULL)
+        xmlGenericError(xmlGenericErrorContext,
+                        "xmlSchemaParse() failed\n");
+#endif
+
+    return (schema);
+}
+
+/************************************************************************
+ * 									*
+ * 			Validating using Schemas			*
+ * 									*
+ ************************************************************************/
+
+/************************************************************************
+ * 									*
+ * 			Reading/Writing Schemas				*
+ * 									*
+ ************************************************************************/
+
+/**
+ * xmlSchemaNewParserCtxt:
+ * @URL:  the location of the schema
+ *
+ * Create an XML Schemas parse context for that file/resource expected
+ * to contain an XML Schemas file.
+ *
+ * Returns the parser context or NULL in case of error
+ */
+xmlSchemaParserCtxtPtr
+xmlSchemaNewParserCtxt(const char *URL) {
+    xmlSchemaParserCtxtPtr ret;
+
+    if (URL == NULL)
+	return(NULL);
+
+    ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
+    if (ret == NULL) {
+	xmlGenericError(xmlGenericErrorContext,
+		"Failed to allocate new schama parser context for %s\n", URL);
+        return (NULL);
+    }
+    memset(ret, 0, sizeof(xmlSchemaParserCtxt));
+    ret->URL = xmlStrdup((const xmlChar *)URL);
+    return (ret);
+}
+
+/**
+ * xmlSchemaFreeParserCtxt:
+ * @ctxt:  the schema parser context
+ *
+ * Free the resources associated to the schema parser context
+ */
+void
+xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt) {
+    if (ctxt == NULL)
+	return;
+    if (ctxt->URL != NULL)
+	xmlFree(ctxt->URL);
+    xmlFree(ctxt);
+}
+
+/************************************************************************
+ *									*
+ *			Building the content models			*
+ *									*
+ ************************************************************************/
+/**
+ * xmlSchemaBuildAContentModel:
+ * @type:  the schema type definition
+ * @ctxt:  the schema parser context
+ * @name:  the element name whose content is being built
+ *
+ * Generate the automata sequence needed for that type
+ */
+static void
+xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
+		           xmlSchemaParserCtxtPtr ctxt,
+		           const xmlChar *name) {
+    if (type == NULL) {
+	xmlGenericError(xmlGenericErrorContext,
+		"Found unexpected type = NULL in %s content model\n",
+			name);
+	return;
+    }
+    switch (type->type) {
+	case XML_SCHEMA_TYPE_ANY:
+	    /* TODO : handle the namespace too */
+	    /* TODO : make that a specific transition type */
+	    TODO
+	    ctxt->state = xmlAutomataNewTransition(ctxt->am, ctxt->state,
+		                NULL, BAD_CAST "*", NULL);
+	    break;
+	case XML_SCHEMA_TYPE_ELEMENT: {
+	    xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
+	    /* TODO : handle the namespace too */
+	    xmlAutomataStatePtr oldstate = ctxt->state;
+	    if (elem->maxOccurs >= UNBOUNDED) {
+		if (elem->refDecl != NULL) {
+		    xmlSchemaBuildAContentModel(
+			    (xmlSchemaTypePtr) elem->refDecl,
+			    ctxt, elem->refDecl->name);
+		} else {
+		    ctxt->state = xmlAutomataNewTransition(ctxt->am,
+			    ctxt->state, NULL, elem->name, type);
+		}
+		xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
+		if (elem->minOccurs == 0) {
+		    /* basically an elem* */
+		    xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
+		}
+	    } else if (elem->maxOccurs > 1) {
+		if (elem->refDecl != NULL) {
+		    TODO
+		    xmlSchemaBuildAContentModel(
+			    (xmlSchemaTypePtr) elem->refDecl,
+			    ctxt, elem->refDecl->name);
+		} else {
+		    ctxt->state = xmlAutomataNewCountTrans(ctxt->am,
+			    ctxt->state, NULL, elem->name,
+			    elem->minOccurs, elem->maxOccurs, type);
+		}
+	    } else {
+		if (elem->refDecl != NULL) {
+		    xmlSchemaBuildAContentModel(
+			    (xmlSchemaTypePtr) elem->refDecl,
+			    ctxt, elem->refDecl->name);
+		} else {
+		    ctxt->state = xmlAutomataNewTransition(ctxt->am,
+			    ctxt->state, NULL, elem->name, type);
+		}
+		if (elem->minOccurs == 0) {
+		    /* basically an elem? */
+		    xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
+		}
+	    }
+	    break;
+	}
+	case XML_SCHEMA_TYPE_SEQUENCE: {
+	    xmlSchemaTypePtr subtypes;
+
+	    /*
+	     * Simply iterate over the subtypes
+	     */
+	    subtypes = type->subtypes;
+	    while (subtypes != NULL) {
+		xmlSchemaBuildAContentModel(subtypes, ctxt, name);
+		subtypes = subtypes->next;
+	    }
+	    break;
+	}
+	case XML_SCHEMA_TYPE_CHOICE: {
+	    xmlSchemaTypePtr subtypes;
+	    xmlAutomataStatePtr start, end;
+
+	    start = ctxt->state;
+	    end = xmlAutomataNewState(ctxt->am);
+
+	    /*
+	     * iterate over the subtypes and remerge the end with an
+	     * epsilon transition
+	     */
+	    subtypes = type->subtypes;
+	    while (subtypes != NULL) {
+		ctxt->state = start;
+		xmlSchemaBuildAContentModel(subtypes, ctxt, name);
+		xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
+		subtypes = subtypes->next;
+	    }
+	    ctxt->state = end;
+	    break;
+	}
+	case XML_SCHEMA_TYPE_ALL: {
+	    TODO
+	    break;
+	}
+	case XML_SCHEMA_TYPE_RESTRICTION:
+	case XML_SCHEMA_TYPE_EXTENSION:
+	case XML_SCHEMA_TYPE_GROUP:
+	case XML_SCHEMA_TYPE_COMPLEX:
+	case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
+	    if (type->subtypes != NULL)
+		xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
+	    break;
+	default:
+	    xmlGenericError(xmlGenericErrorContext,
+		    "Found unexpected type %d in %s content model\n",
+		            type->type, name);
+	    return;
+    }
+}
+/**
+ * xmlSchemaBuildContentModel:
+ * @typeDecl:  the schema type definition
+ * @ctxt:  the schema parser context
+ *
+ * Fixes the content model of the element.
+ */
+static void
+xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
+		           xmlSchemaParserCtxtPtr ctxt,
+		           const xmlChar *name) {
+    xmlAutomataStatePtr start;
+
+#ifdef DEBUG_CONTENT
+    xmlGenericError(xmlGenericErrorContext,
+	    "Building content model for %s\n", name);
+#endif
+
+    if (elem->contModel != NULL)
+	return;
+    if (elem->subtypes == NULL)
+	return;
+    if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
+	return;
+    ctxt->am = xmlNewAutomata();
+    if (ctxt->am == NULL) {
+	xmlGenericError(xmlGenericErrorContext,
+		"Cannot create automata for elem %s\n", name);
+	return;
+    }
+    start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
+    xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
+    xmlAutomataSetFinalState(ctxt->am, ctxt->state);
+    elem->contModel = xmlAutomataCompile(ctxt->am);
+#ifdef DEBUG_CONTENT
+    printf("Content model of %s:\n", name);
+    xmlRegexpPrint(stdout, elem->contModel);
+#endif
+    ctxt->state = NULL;
+    xmlFreeAutomata(ctxt->am);
+    ctxt->am = NULL;
+}
+
+/**
+ * xmlSchemaRefFixupCallback:
+ * @elem:  the schema element context
+ * @ctxt:  the schema parser context
+ *
+ * Free the resources associated to the schema parser context
+ */
+static void
+xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
+		     xmlSchemaParserCtxtPtr ctxt,
+		     const xmlChar *name,
+		     ATTRIBUTE_UNUSED const xmlChar *context,
+		     ATTRIBUTE_UNUSED const xmlChar *namespace)
+{
+    if ((ctxt == NULL) || (elem == NULL))
+	return;
+    if (elem->ref != NULL) {
+	xmlSchemaElementPtr elemDecl;
+
+	if (elem->subtypes != NULL) {
+	    xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
+	    if ((ctxt != NULL) && (ctxt->error != NULL))
+		ctxt->error(ctxt->userData,
+			    "Schemas: element %s have both ref and subtype\n",
+			    name);
+	    return;
+	}
+	elemDecl = xmlHashLookup2(ctxt->schema->elemDecl,
+				  elem->ref, elem->refNs);
+
+        if (elemDecl == NULL) {
+	    if ((ctxt != NULL) && (ctxt->error != NULL))
+		ctxt->error(ctxt->userData,
+			    "Schemas: element %s ref to %s not found\n",
+			    name, elem->ref);
+	    return;
+	}
+	elem->refDecl = elemDecl;
+    } else if (elem->namedType != NULL) {
+	xmlSchemaTypePtr typeDecl;
+
+	if (elem->subtypes != NULL) {
+	    xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
+	    if ((ctxt != NULL) && (ctxt->error != NULL))
+		ctxt->error(ctxt->userData,
+			    "Schemas: element %s have both type and subtype\n",
+			    name);
+	    return;
+	}
+	typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
+		                    elem->namedTypeNs);
+
+        if (typeDecl == NULL) {
+	    if ((ctxt != NULL) && (ctxt->error != NULL))
+		ctxt->error(ctxt->userData,
+			    "Schemas: element %s type %s not found\n",
+			    name, elem->namedType);
+	    return;
+	}
+	elem->subtypes = typeDecl;
+    }
+}
+
+/**
+ * xmlSchemaTypeFixup:
+ * @typeDecl:  the schema type definition
+ * @ctxt:  the schema parser context
+ *
+ * Fixes the content model of the type.
+ */
+static void
+xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
+		   xmlSchemaParserCtxtPtr ctxt,
+		   const xmlChar *name)
+{
+    if (name == NULL)
+	name = typeDecl->name;
+    if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
+	switch (typeDecl->type) {
+	    case XML_SCHEMA_TYPE_SIMPLE_CONTENT: {
+		xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
+		typeDecl->contentType = typeDecl->subtypes->contentType;
+		break;
+	    }
+	    case XML_SCHEMA_TYPE_RESTRICTION: {
+		if (typeDecl->subtypes != NULL)
+		    xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
+
+		if (typeDecl->base != NULL) {
+		    xmlSchemaTypePtr baseType;
+
+		    baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
+						typeDecl->baseNs);
+		    if (baseType == NULL) {
+			if ((ctxt != NULL) && (ctxt->error != NULL))
+			    ctxt->error(ctxt->userData,
+				"Schemas: type %s base type %s not found\n",
+					name, typeDecl->base);
+		    }
+		    typeDecl->baseType = baseType;
+		}
+		if (typeDecl->subtypes == NULL)
+		    /* 1.1.1 */
+		    typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
+		else if ((typeDecl->subtypes->subtypes == NULL) &&
+		    ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
+		     (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
+		    /* 1.1.2 */
+		    typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
+		else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
+		    (typeDecl->subtypes->subtypes == NULL))
+		    /* 1.1.3 */
+		    typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
+		else {
+		    /* 1.2 and 2.X are applied at the other layer */
+		    typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
+		}
+		break;
+	    }
+	    case XML_SCHEMA_TYPE_EXTENSION: {
+		xmlSchemaContentType explicitContentType;
+		xmlSchemaTypePtr base;
+
+		if (typeDecl->base != NULL) {
+		    xmlSchemaTypePtr baseType;
+
+		    baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
+						typeDecl->baseNs);
+		    if (baseType == NULL) {
+			if ((ctxt != NULL) && (ctxt->error != NULL))
+			    ctxt->error(ctxt->userData,
+				"Schemas: type %s base type %s not found\n",
+					name, typeDecl->base);
+		    }
+		    typeDecl->baseType = baseType;
+		}
+		if (typeDecl->subtypes != NULL)
+		    xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
+
+		if (typeDecl->subtypes == NULL)
+		    /* 1.1.1 */
+		    explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
+		else if ((typeDecl->subtypes->subtypes == NULL) &&
+		    ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
+		     (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
+		    /* 1.1.2 */
+		    explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
+		else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
+		    (typeDecl->subtypes->subtypes == NULL))
+		    /* 1.1.3 */
+		    explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
+
+		base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
+					typeDecl->baseNs);
+		if (base == NULL) {
+		    xmlSchemaErrorContext(ctxt, NULL, typeDecl->node, NULL);
+		    if ((ctxt != NULL) && (ctxt->error != NULL))
+			ctxt->error(ctxt->userData,
+			"Schemas: base type %s of type %s not found\n",
+				    typeDecl->base, name);
+		    return;
+		}
+		xmlSchemaTypeFixup(base, ctxt, NULL);
+		if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
+		    /* 2.1 */
+		    typeDecl->contentType = base->contentType;
+		} else if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
+		    /* 2.2 imbitable ! */
+		    typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
+		} else {
+		    /* 2.3 imbitable pareil ! */
+		    typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
+		}
+		break;
+	    }
+	    case XML_SCHEMA_TYPE_COMPLEX: {
+		if (typeDecl->subtypes == NULL) {
+		    typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
+		} else {
+		    if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
+			typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
+		    else {
+			xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
+			typeDecl->contentType = typeDecl->subtypes->contentType;
+		    }
+		}
+		break;
+	    }
+	    case XML_SCHEMA_TYPE_COMPLEX_CONTENT: {
+		if (typeDecl->subtypes == NULL) {
+		    typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
+		} else {
+		    if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
+			typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
+		    else {
+			xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
+			typeDecl->contentType = typeDecl->subtypes->contentType;
+		    }
+		}
+		break;
+	    }
+	    case XML_SCHEMA_TYPE_SEQUENCE:
+	    case XML_SCHEMA_TYPE_GROUP:
+	    case XML_SCHEMA_TYPE_ALL:
+	    case XML_SCHEMA_TYPE_CHOICE:
+		typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
+		break;
+	    case XML_SCHEMA_TYPE_BASIC:
+	    case XML_SCHEMA_TYPE_ANY:
+	    case XML_SCHEMA_TYPE_FACET:
+	    case XML_SCHEMA_TYPE_SIMPLE:
+	    case XML_SCHEMA_TYPE_UR:
+	    case XML_SCHEMA_TYPE_ELEMENT:
+	    case XML_SCHEMA_TYPE_ATTRIBUTE:
+	    case XML_SCHEMA_TYPE_NOTATION:
+	    case XML_SCHEMA_TYPE_LIST:
+	    case XML_SCHEMA_TYPE_UNION:
+	    case XML_SCHEMA_FACET_MININCLUSIVE:
+	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
+	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
+	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
+	    case XML_SCHEMA_FACET_TOTALDIGITS:
+	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
+	    case XML_SCHEMA_FACET_PATTERN:
+	    case XML_SCHEMA_FACET_ENUMERATION:
+	    case XML_SCHEMA_FACET_WHITESPACE:
+	    case XML_SCHEMA_FACET_LENGTH:
+	    case XML_SCHEMA_FACET_MAXLENGTH:
+	    case XML_SCHEMA_FACET_MINLENGTH:
+		typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
+		break;
+	}
+    } 
+}
+
+/**
+ * xmlSchemaCheckDefaults:
+ * @typeDecl:  the schema type definition
+ * @ctxt:  the schema parser context
+ *
+ * Checks the default values types, especially for facets 
+ */
+static void
+xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
+		   xmlSchemaParserCtxtPtr ctxt,
+		   const xmlChar *name)
+{
+    static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
+    if (name == NULL)
+	name = typeDecl->name;
+    if (nonNegativeIntegerType == NULL) {
+	nonNegativeIntegerType = xmlSchemaGetPredefinedType(
+		BAD_CAST "nonNegativeInteger", xmlSchemaNs);
+    }
+    if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
+	if (typeDecl->facets != NULL) {
+	    xmlSchemaFacetPtr facet = typeDecl->facets;
+	    while (facet != NULL) {
+		switch (facet->type) {
+		    case XML_SCHEMA_FACET_MININCLUSIVE:
+		    case XML_SCHEMA_FACET_MINEXCLUSIVE:
+		    case XML_SCHEMA_FACET_MAXINCLUSIVE:
+		    case XML_SCHEMA_FACET_MAXEXCLUSIVE: {
+			/*
+			 * Okay we need to validate the value
+			 * at that point.
+			 */
+			xmlSchemaValidCtxtPtr vctxt;
+
+			vctxt = xmlSchemaNewValidCtxt(NULL);
+			if (vctxt == NULL)
+			    break;
+			xmlSchemaValidateSimpleValue(vctxt, typeDecl,
+						     facet->value);
+			facet->val = vctxt->value;
+			vctxt->value = NULL;
+			if (facet->val == NULL) {
+			    /* error code */
+			    xmlSchemaErrorContext(ctxt, NULL,
+				    facet->node, NULL);
+			    ctxt->error(ctxt->userData,
+			    "Schemas: type %s facet value %s invalid\n",
+					name, facet->value);
+			}
+			xmlSchemaFreeValidCtxt(vctxt);
+			break;
+		    }
+		    case XML_SCHEMA_FACET_ENUMERATION: {
+			/*
+			 * Okay we need to validate the value
+			 * at that point.
+			 */
+			xmlSchemaValidCtxtPtr vctxt;
+			int ret;
+
+			vctxt = xmlSchemaNewValidCtxt(NULL);
+			if (vctxt == NULL)
+			    break;
+			ret = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
+						     facet->value);
+			if (ret != 0) {
+			    xmlSchemaErrorContext(ctxt, NULL,
+				    facet->node, NULL);
+			    ctxt->error(ctxt->userData,
+			    "Schemas: type %s enumeration value %s invalid\n",
+					name, facet->value);
+			}
+			xmlSchemaFreeValidCtxt(vctxt);
+			break;
+		    }
+		    case XML_SCHEMA_FACET_PATTERN:
+			facet->regexp = xmlRegexpCompile(facet->value);
+			if (facet->regexp == NULL) {
+			    /* error code */
+			    ctxt->error(ctxt->userData,
+			"Schemas: type %s facet regexp %s invalid\n",
+					name, facet->value);
+			}
+			break;
+		    case XML_SCHEMA_FACET_TOTALDIGITS:
+		    case XML_SCHEMA_FACET_FRACTIONDIGITS:
+		    case XML_SCHEMA_FACET_LENGTH:
+		    case XML_SCHEMA_FACET_MAXLENGTH:
+		    case XML_SCHEMA_FACET_MINLENGTH: {
+			int ret;
+
+			ret = xmlSchemaValidatePredefinedType(
+				     nonNegativeIntegerType, facet->value,
+				     &facet->val);
+			if (ret != 0) {
+			    /* error code */
+			    xmlSchemaErrorContext(ctxt, NULL,
+				    facet->node, NULL);
+			    ctxt->error(ctxt->userData,
+			    "Schemas: type %s facet value %s invalid\n",
+					name, facet->value);
+			}
+			break;
+		    }
+		    case XML_SCHEMA_FACET_WHITESPACE: {
+			if (xmlStrEqual(facet->value, BAD_CAST"preserve")) {
+			    facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
+			} else if (xmlStrEqual(facet->value,
+				    BAD_CAST"replace")) {
+			    facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
+			} else if (xmlStrEqual(facet->value,
+				    BAD_CAST"collapse")) {
+			    facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
+			} else {
+			    xmlSchemaErrorContext(ctxt, NULL,
+				    facet->node, NULL);
+			    ctxt->error(ctxt->userData,
+			    "Schemas: type %s whiteSpace value %s invalid\n",
+					name, facet->value);
+			}
+		    }
+		    default:
+			break;
+		}
+		facet = facet->next;
+	    }
+	}
+    }
+}
+
+/**
+ * xmlSchemaAttrFixup:
+ * @attrDecl:  the schema attribute definition
+ * @ctxt:  the schema parser context
+ * @name:  the attribute name
+ *
+ * Fixes finish doing the computations on the attributes definitions
+ */
+static void
+xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
+		   xmlSchemaParserCtxtPtr ctxt,
+		   const xmlChar *name)
+{
+    if (name == NULL)
+	name = attrDecl->name;
+    if (attrDecl->subtypes != NULL)
+	return;
+    if (attrDecl->typeName != NULL) {
+	xmlSchemaTypePtr type;
+
+	type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
+				    attrDecl->typeNs);
+	if (type == NULL) {
+	    if ((ctxt != NULL) && (ctxt->error != NULL))
+		ctxt->error(ctxt->userData,
+		    "Schemas: attribute %s type %s not found\n",
+			    name, attrDecl->typeName);
+	}
+	attrDecl->subtypes = type;
+    } else if (attrDecl->ref != NULL) {
+	xmlSchemaAttributePtr ref;
+
+	ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
+		             attrDecl->refNs);
+	if (ref == NULL) {
+	    if ((ctxt != NULL) && (ctxt->error != NULL))
+		ctxt->error(ctxt->userData,
+		    "Schemas: attribute %s reference %s not found\n",
+			    name, attrDecl->ref);
+	    return;
+	}
+	xmlSchemaAttrFixup(ref, ctxt, NULL);
+	attrDecl->subtypes = ref->subtypes;
+    } else {
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+		"Schemas: attribute %s has no type nor reference\n",
+			name);
+    }
+}
+
+/**
+ * xmlSchemaParse:
+ * @ctxt:  a schema validation context
+ * @URL:  the location of the schema
+ *
+ * Load, XML parse a schema definition resource and build an internal
+ * XML Shema struture which can be used to validate instances.
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the internal XML Schema structure built from the resource or
+ *         NULL in case of error
+ */
+xmlSchemaPtr
+xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
+{
+    xmlSchemaPtr ret = NULL;
+    xmlDocPtr doc;
+    xmlNodePtr root, cur, delete;
+
+    xmlSchemaInitTypes();
+
+    if ((ctxt == NULL) || (ctxt->URL == NULL))
+        return (NULL);
+
+    ctxt->counter = 0;
+    ctxt->container = NULL;
+
+    /*
+     * First step is to parse the input document into an DOM/Infoset
+     */
+    doc = xmlParseFile((const char *) ctxt->URL);
+    if (doc == NULL) {
+        if (ctxt->error != NULL)
+            ctxt->error(ctxt->userData,
+                        "xmlSchemaParse: could not load %s\n", ctxt->URL);
+        return (NULL);
+    }
+
+    /*
+     * Then extract the root and Schema parse it
+     */
+    root = xmlDocGetRootElement(doc);
+    if (root == NULL) {
+        if (ctxt->error != NULL)
+            ctxt->error(ctxt->userData, "xmlSchemaParse: %s is empty\n",
+                        ctxt->URL);
+        return (NULL);
+    }
+
+    /*
+     * 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;
+    }
+
+    /*
+     * Then do the parsing for good
+     */
+    ret = xmlSchemaParseSchema(ctxt, root);
+    ret->doc = doc;
+
+    /*
+     * Then fix all the references.
+     */
+    ctxt->schema = ret;
+    xmlHashScanFull(ret->elemDecl,
+	            (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
+
+    /*
+     * Then fixup all types properties
+     */
+    xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
+
+    /*
+     * Then build the content model for all elements
+     */
+    xmlHashScan(ret->elemDecl,
+	            (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
+
+    /*
+     * Then check the defaults part of the type like facets values
+     */
+    xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt);
+
+    /*
+     * Then fixup all attributes declarations
+     */
+    xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
+
+    return (ret);
+}
+ 
+/**
+ * xmlSchemaParse:
+ * @ctxt:  a schema validation context
+ * @URL:  the location of the schema
+ *
+ * Load, XML parse a schema definition resource and build an internal
+ * XML Shema struture which can be used to validate instances.
+ * *WARNING* this interface is highly subject to change
+ *
+ * Returns the internal XML Schema structure built from the resource or
+ *         NULL in case of error
+ */
+void
+xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
+	xmlSchemaValidityErrorFunc err,
+	xmlSchemaValidityWarningFunc warn, void *ctx) {
+    if (ctxt == NULL)
+	return;
+    ctxt->error = err;
+    ctxt->warning = warn;
+    ctxt->userData = ctx;
+}
+
+/************************************************************************
+ * 									*
+ * 			Simple type validation				*
+ * 									*
+ ************************************************************************/
+
+/**
+ * xmlSchemaValidateSimpleValue:
+ * @ctxt:  a schema validation context
+ * @type:  the type declaration
+ * @value:  the value to validate
+ *
+ * Validate a value against a simple type
+ *
+ * Returns 0 if the value is valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt, 
+			     xmlSchemaTypePtr type,
+	                     xmlChar *value) {
+    int ret = 0;
+    /*
+     * First normalize the value accordingly to Schema Datatype
+     * 4.3.6 whiteSpace definition of the whiteSpace facet of type
+     */
+    /*
+     * Then check the normalized value against the lexical space of the
+     * type.
+     */
+    if (type->type == XML_SCHEMA_TYPE_BASIC) {
+	if (ctxt->value != NULL) {
+	    xmlSchemaFreeValue(ctxt->value);
+	    ctxt->value = NULL;
+	}
+	ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
+    } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
+	xmlSchemaTypePtr base;
+	xmlSchemaFacetPtr facet;
+	int tmp;
+
+	base = type->baseType;
+	if (base != NULL) {
+	    ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
+	} else if (type->subtypes != NULL) {
+	    
+	}
+	/*
+	 * Do not validate facets when working on building the Schemas
+	 */
+	if (ctxt->schema != NULL) {
+	    if (ret == 0) {
+		facet = type->facets;
+		while (facet != NULL) {
+		    tmp = xmlSchemaValidateFacet(base, facet, value,
+						 ctxt->value);
+		    if (tmp != 0)
+			ret = tmp;
+		    facet = facet->next;
+		}
+	    }
+	}
+    } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
+	xmlSchemaTypePtr base;
+
+	base = type->subtypes;
+	if (base != NULL) {
+	    ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
+	} else {
+	    TODO
+	}
+    } else if (type->type == XML_SCHEMA_TYPE_LIST) {
+	xmlSchemaTypePtr base;
+	xmlChar *cur, *end, tmp;
+	int ret2;
+
+	base = type->subtypes;
+	if (base == NULL) {
+	    ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
+	    if (ctxt->error != NULL) {
+		xmlSchemaErrorContext(NULL, ctxt->schema, type->node, NULL);
+		ctxt->error(ctxt->userData,
+		"Internal: List type %s has no base type\n",
+			    type->name);
+	    }
+	    return(-1);
+	}
+	cur = value;
+	do {
+	    while (IS_BLANK(*cur)) cur++;
+	    end = cur;
+	    while ((*end != 0) && (!(IS_BLANK(*end)))) end++;
+	    if (end == cur)
+		break;
+	    tmp = *end;
+	    *end = 0;
+	    ret2 = xmlSchemaValidateSimpleValue(ctxt, base, cur);
+	    if (ret2 != 0)
+		ret = 1;
+	    *end = tmp;
+	    cur = end;
+	} while (*cur != 0);
+    } else {
+	TODO
+    }
+    return(ret);
+}
+
+/************************************************************************
+ * 									*
+ * 			DOM Validation code				*
+ * 									*
+ ************************************************************************/
+
+static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
+	                            xmlNodePtr node);
+static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
+	xmlNodePtr elem, xmlSchemaAttributePtr attributes);
+static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
+	xmlNodePtr elem, xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type);
+
+/**
+ * xmlSchemaRegisterAttributes:
+ * @ctxt:  a schema validation context
+ * @attrs:  a list of attributes
+ *
+ * Register the list of attributes as the set to be validated on that element
+ *
+ * Returns -1 in case of error, 0 otherwise
+ */
+static int
+xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt,
+	                    xmlAttrPtr attrs) {
+    while (attrs != NULL) {
+	if (ctxt->attrNr >= ctxt->attrMax) {
+	    xmlSchemaAttrStatePtr tmp;
+
+	    ctxt->attrMax *= 2;
+	    tmp = (xmlSchemaAttrStatePtr)
+		          xmlRealloc(ctxt->attr, ctxt->attrMax *
+				     sizeof(xmlSchemaAttrState));
+	    if (tmp == NULL) {
+		ctxt->attrMax /= 2;
+		return(-1);
+	    }
+	    ctxt->attr = tmp;
+	}
+	ctxt->attr[ctxt->attrNr].attr = attrs;
+	ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
+	ctxt->attrNr++;
+	attrs = attrs->next;
+    }
+    return(0);
+}
+
+/**
+ * xmlSchemaCheckAttributes:
+ * @ctxt:  a schema validation context
+ * @node:  the node carrying it.
+ *
+ * Check that the registered set of attributes on the current node
+ * has been properly validated.
+ *
+ * Returns 0 if validity constraints are met, 1 otherwise.
+ */
+static int
+xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
+    int ret = 0;
+    int i;
+
+    for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
+	if (ctxt->attr[i].attr == NULL)
+	    break;
+	if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
+	    ret = 1;
+	    ctxt->err = XML_SCHEMAS_ERR_ATTRUNKNOWN;
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData,
+		"Attribute %s on %s is unknown\n",
+			    ctxt->attr[i].attr->name,
+			    node->name);
+	}
+    }
+    return(ret);
+}
+
+/**
+ * xmlSchemaValidateSimpleContent:
+ * @ctxt:  a schema validation context
+ * @elem:  an element
+ * @type:  the type declaration
+ *
+ * Validate the content of an element expected to be a simple type
+ *
+ * Returns 0 if the element is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
+	                       ATTRIBUTE_UNUSED xmlNodePtr node) {
+    xmlNodePtr child;
+    xmlSchemaTypePtr type, base;
+    xmlChar *value;
+    int ret = 0, tmp;
+
+    child = ctxt->node;
+    type = ctxt->type;
+
+    /*
+     * Validation Rule: Element Locally Valid (Type): 3.1.3
+     */
+    value = xmlNodeGetContent(child);
+    /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
+    switch (type->type) {
+	case XML_SCHEMA_TYPE_RESTRICTION: {
+	    xmlSchemaFacetPtr facet;
+
+	    base = type->baseType;
+	    if (base != NULL) {
+		ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
+	    } else {
+		TODO
+	    }
+	    if (ret == 0) {
+		facet = type->facets;
+		while (facet != NULL) {
+		    tmp = xmlSchemaValidateFacet(base, facet, value,
+			                         ctxt->value);
+		    if (tmp != 0)
+			ret = tmp;
+		    facet = facet->next;
+		}
+	    }
+	    break;
+	}
+	default:
+	    TODO
+    }
+    if (value != NULL)
+	xmlFree(value);
+
+    return(ret);
+}
+
+/**
+ * xmlSchemaValidateCheckNodeList
+ * @nodelist: the list of nodes
+ *
+ * Check the node list is only made of text nodes and entities pointing
+ * to text nodes
+ *
+ * Returns 1 if true, 0 if false and -1 in case of error
+ */
+static int
+xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist) {
+    while (nodelist != NULL) {
+	if (nodelist->type == XML_ENTITY_REF_NODE) {
+	    TODO /* implement recursion in the entity content */
+	}
+	if ((nodelist->type != XML_TEXT_NODE) &&
+	    (nodelist->type != XML_COMMENT_NODE) &&
+	    (nodelist->type != XML_PI_NODE) &&
+	    (nodelist->type != XML_PI_NODE)) {
+	    return(0);
+	}
+	nodelist = nodelist->next;
+    }
+    return(1);
+}
+
+/**
+ * xmlSchemaSkipIgnored:
+ * @ctxt:  a schema validation context
+ * @type:  the current type context
+ * @node:  the top node.
+ *
+ * Skip ignorable nodes in that context
+ *
+ * Returns the new sibling
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static xmlNodePtr
+xmlSchemaSkipIgnored(ATTRIBUTE_UNUSED xmlSchemaValidCtxtPtr ctxt,
+	             xmlSchemaTypePtr type,
+	             xmlNodePtr node) {
+    int mixed = 0;
+    /*
+     * TODO complete and handle entities
+     */
+    mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
+	     (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
+    while ((node != NULL) &&
+	   ((node->type == XML_COMMENT_NODE) ||
+	    ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
+	    (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
+	     (node->type == XML_TEXT_NODE) &&
+	     (IS_BLANK_NODE(node)))))) {
+	node = node->next;
+    }
+    return(node);
+}
+
+/**
+ * xmlSchemaValidateCallback:
+ * @ctxt:  a schema validation context
+ * @name:  the name of the element detected (might be NULL)
+ * @type:  the type
+ *
+ * A transition has been made in the automata associated to an element
+ * content model
+ */
+static void
+xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
+	                  ATTRIBUTE_UNUSED const xmlChar *name,
+			  xmlSchemaTypePtr type,
+			  xmlNodePtr node) {
+    xmlSchemaTypePtr oldtype = ctxt->type;
+    xmlNodePtr oldnode = ctxt->node;
+#ifdef DEBUG_CONTENT
+    printf("xmlSchemaValidateCallback: %s, %s, %s\n",
+	   name, type->name, node->name);
+#endif
+    ctxt->type = type;
+    ctxt->node = node;
+    xmlSchemaValidateContent(ctxt, node);
+    ctxt->type = oldtype;
+    ctxt->node = oldnode;
+}
+
+
+#if 0
+/**
+ * xmlSchemaValidateSimpleRestrictionType:
+ * @ctxt:  a schema validation context
+ * @node:  the top node.
+ *
+ * Validate the content of a restriction type.
+ *
+ * Returns 0 if the element is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
+                                       xmlNodePtr node)
+{
+    xmlNodePtr child;
+    xmlSchemaTypePtr type;
+    int ret;
+
+    child = ctxt->node;
+    type = ctxt->type;
+
+    if ((ctxt == NULL) || (type == NULL)) {
+        ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
+        if (ctxt->error != NULL)
+            ctxt->error(ctxt->userData,
+	    "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
+                        node->name);
+        return (-1);
+    }
+    /*
+     * Only text and text based entities references shall be found there
+     */
+    ret = xmlSchemaValidateCheckNodeList(child);
+    if (ret < 0) {
+        ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
+        if (ctxt->error != NULL)
+            ctxt->error(ctxt->userData,
+		"Internal error: xmlSchemaValidateSimpleType %s content\n",
+                        node->name);
+        return (-1);
+    } else if (ret == 0) {
+        ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
+        if (ctxt->error != NULL)
+            ctxt->error(ctxt->userData,
+                        "Element %s content is not a simple type\n",
+                        node->name);
+        return (-1);
+    }
+    ctxt->type = type->subtypes;
+    xmlSchemaValidateContent(ctxt, node);
+    ctxt->type = type;
+    return (ret);
+}
+#endif
+
+/**
+ * xmlSchemaValidateSimpleType:
+ * @ctxt:  a schema validation context
+ * @node:  the top node.
+ *
+ * Validate the content of an simple type.
+ *
+ * Returns 0 if the element is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
+    xmlNodePtr child;
+    xmlSchemaTypePtr type;
+    xmlAttrPtr attr;
+    int ret;
+
+    child = ctxt->node;
+    type = ctxt->type;
+
+    if ((ctxt == NULL) || (type == NULL)) {
+	ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
+	if (ctxt->error != NULL)
+	    ctxt->error(ctxt->userData,
+		    "Internal error: xmlSchemaValidateSimpleType %s\n",
+			node->name);
+	return(-1);
+    }
+    /*
+     * Only text and text based entities references shall be found there
+     */
+    ret = xmlSchemaValidateCheckNodeList(child);
+    if (ret < 0) {
+	ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
+	if (ctxt->error != NULL)
+	    ctxt->error(ctxt->userData,
+		    "Internal error: xmlSchemaValidateSimpleType %s content\n",
+			node->name);
+	return(-1);
+    } else if (ret == 0) {
+	ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
+	if (ctxt->error != NULL)
+	    ctxt->error(ctxt->userData,
+		    "Element %s content is not a simple type\n",
+			node->name);
+	return(-1);
+    }
+    /*
+     * Validation Rule: Element Locally Valid (Type): 3.1.1
+     */
+    attr = node->properties;
+    while (attr != NULL) {
+	if ((attr->ns == NULL) ||
+	    (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
+	    ((!xmlStrEqual(attr->name, BAD_CAST"type")) &&
+	     (!xmlStrEqual(attr->name, BAD_CAST"nil")) &&
+	     (!xmlStrEqual(attr->name, BAD_CAST"schemasLocation")) &&
+	     (!xmlStrEqual(attr->name, BAD_CAST"noNamespaceSchemaLocation")))) {
+	    ctxt->err = XML_SCHEMAS_ERR_INVALIDATTR;
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData,
+			"Element %s: attribute %s should not be present\n",
+			    child->name, attr->name);
+	    return(ctxt->err);
+	}
+    }
+
+    ctxt->type = type->subtypes;
+    ret = xmlSchemaValidateSimpleContent(ctxt, node);
+    ctxt->type = type;
+    return(ret);
+}
+
+/**
+ * xmlSchemaValidateElementType:
+ * @ctxt:  a schema validation context
+ * @node:  the top node.
+ *
+ * Validate the content of an element type.
+ * Validation Rule: Element Locally Valid (Complex Type)
+ *
+ * Returns 0 if the element is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
+    xmlNodePtr child;
+    xmlSchemaTypePtr type;
+    xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
+    xmlSchemaElementPtr decl;
+    int ret, attrBase;
+
+    oldregexp = ctxt->regexp;
+
+    child = ctxt->node;
+    type = ctxt->type;
+
+    if ((ctxt == NULL) || (type == NULL)) {
+	ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
+	if (ctxt->error != NULL)
+	    ctxt->error(ctxt->userData,
+		    "Internal error: xmlSchemaValidateElementType\n",
+			node->name);
+	return(-1);
+    }
+    if (child == NULL) {
+	if (type->minOccurs > 0) {
+	    ctxt->err = XML_SCHEMAS_ERR_MISSING;
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData,
+			"Element %s: missing child %s\n",
+			    node->name, type->name);
+	}
+	return(ctxt->err);
+    }
+
+    /*
+     * Verify the element matches
+     */
+    if (!xmlStrEqual(child->name, type->name)) {
+	ctxt->err = XML_SCHEMAS_ERR_WRONGELEM;
+	if (ctxt->error != NULL)
+	    ctxt->error(ctxt->userData,
+		    "Element %s: missing child %s found %s\n",
+			node->name, type->name, child->name);
+        return(ctxt->err);
+    }
+    /*
+     * Verify the attributes
+     */
+    attrBase = ctxt->attrBase;
+    ctxt->attrBase = ctxt->attrNr;
+    xmlSchemaRegisterAttributes(ctxt, child->properties);
+    xmlSchemaValidateAttributes(ctxt, child, type->attributes);
+    /*
+     * Verify the element content recursively
+     */
+    decl = (xmlSchemaElementPtr) type;
+    oldregexp = ctxt->regexp;
+    if (decl->contModel != NULL) {
+	ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
+			     (xmlRegExecCallbacks) xmlSchemaValidateCallback,
+			     ctxt);
+#ifdef DEBUG_AUTOMATA
+	xmlGenericError(xmlGenericErrorContext,
+		"====> %s\n", node->name);
+#endif
+    }
+    xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr)type,
+	                  type->subtypes);
+
+    if (decl->contModel != NULL) {
+	ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
+#ifdef DEBUG_AUTOMATA
+	xmlGenericError(xmlGenericErrorContext,
+		"====> %s : %d\n", node->name, ret);
+#endif
+	if (ret == 0) {
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData, "Element %s content check failed\n",
+			    node->name);
+	} else if (ret < 0) {
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData, "Element %s content check failure\n",
+			    node->name);
+#ifdef DEBUG_CONTENT
+	} else {
+	    xmlGenericError(xmlGenericErrorContext,
+			    "Element %s content check succeeded\n", node->name);
+
+#endif
+	}
+	xmlRegFreeExecCtxt(ctxt->regexp);
+    }
+    /*
+     * Verify that all attributes were Schemas-validated
+     */
+    xmlSchemaCheckAttributes(ctxt, node);
+    ctxt->attrNr = ctxt->attrBase;
+    ctxt->attrBase = attrBase;
+
+    ctxt->regexp = oldregexp;
+
+    ctxt->node = child;
+    ctxt->type = type;
+    return(ctxt->err);
+}
+
+/**
+ * xmlSchemaValidateBasicType:
+ * @ctxt:  a schema validation context
+ * @node:  the top node.
+ *
+ * Validate the content of an element expected to be a basic type type
+ *
+ * Returns 0 if the element is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
+    int ret;
+    xmlNodePtr child, cur;
+    xmlSchemaTypePtr type;
+    xmlChar *value;     /* lexical representation */
+
+    child = ctxt->node;
+    type = ctxt->type;
+
+    if ((ctxt == NULL) || (type == NULL)) {
+	ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
+	if (ctxt->error != NULL)
+	    ctxt->error(ctxt->userData,
+		    "Internal error: xmlSchemaValidateBasicType\n",
+			node->name);
+	return(-1);
+    }
+    /*
+     * First check the content model of the node.
+     */
+    cur = child;
+    while (cur != NULL) {
+	switch (cur->type) {
+	    case XML_TEXT_NODE:
+	    case XML_CDATA_SECTION_NODE:
+	    case XML_PI_NODE:
+	    case XML_COMMENT_NODE:
+	    case XML_XINCLUDE_START:
+	    case XML_XINCLUDE_END:
+	        break;
+	    case XML_ENTITY_REF_NODE:
+	    case XML_ENTITY_NODE:
+	        TODO
+		break;
+	    case XML_ELEMENT_NODE:
+		ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
+		if (ctxt->error != NULL)
+		    ctxt->error(ctxt->userData,
+			    "Element %s: child %s should not be present\n",
+				node->name, cur->name);
+		return(ctxt->err);
+            case XML_ATTRIBUTE_NODE:
+            case XML_DOCUMENT_NODE:
+            case XML_DOCUMENT_TYPE_NODE:
+            case XML_DOCUMENT_FRAG_NODE:
+            case XML_NOTATION_NODE:
+            case XML_HTML_DOCUMENT_NODE:
+            case XML_DTD_NODE:
+            case XML_ELEMENT_DECL:
+            case XML_ATTRIBUTE_DECL:
+            case XML_ENTITY_DECL:
+            case XML_NAMESPACE_DECL:
+#ifdef LIBXML_DOCB_ENABLED
+            case XML_DOCB_DOCUMENT_NODE:
+#endif
+		ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
+		if (ctxt->error != NULL)
+		    ctxt->error(ctxt->userData,
+			    "Element %s: node type %d unexpected here\n",
+				node->name, cur->type);
+		return(ctxt->err);
+	}
+	cur = cur->next;
+    }
+    if (child == NULL)
+	value = NULL;
+    else
+	value = xmlNodeGetContent(child->parent);
+
+    if (ctxt->value != NULL) {
+	xmlSchemaFreeValue(ctxt->value);
+	ctxt->value = NULL;
+    }
+    ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
+    if (value != NULL)
+	xmlFree(value);
+    if (ret != 0) {
+	ctxt->error(ctxt->userData,
+		"Element %s: failed to validate basic type %s\n",
+		    node->name, type->name);
+    }
+    return(ret);
+}
+
+/**
+ * xmlSchemaValidateComplexType:
+ * @ctxt:  a schema validation context
+ * @node:  the top node.
+ *
+ * Validate the content of an element expected to be a complex type type
+ * xmlschema-1.html#cvc-complex-type
+ * Validation Rule: Element Locally Valid (Complex Type)
+ *
+ * Returns 0 if the element is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
+    xmlNodePtr child;
+    xmlSchemaTypePtr type, subtype, model;
+    int ret;
+
+    child = ctxt->node;
+    type = ctxt->type;
+
+    /* 3.4.4 1 was verified on the caller */
+
+    switch (type->contentType) {
+	case XML_SCHEMA_CONTENT_EMPTY:
+	    if (child != NULL) {
+		if (ctxt->error != NULL)
+		    ctxt->error(ctxt->userData,
+			    "Element %s is supposed to be empty\n",
+			        node->name);
+	    }
+	    break;
+	case XML_SCHEMA_CONTENT_ELEMENTS:
+	case XML_SCHEMA_CONTENT_MIXED:
+	case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
+	    /*
+	     * Skip ignorable nodes in that context
+	     */
+	    child = xmlSchemaSkipIgnored(ctxt, type, child);
+	    subtype = type->subtypes;
+	    ctxt->type = model;
+	    while (child != NULL) {
+		if (child->type == XML_ELEMENT_NODE) {
+		    ret = xmlRegExecPushString(ctxt->regexp,
+					       child->name, child);
+#ifdef DEBUG_AUTOMATA
+		    if (ret < 0)
+			xmlGenericError(xmlGenericErrorContext,
+				"  --> %s Error\n", child->name);
+		    else
+			xmlGenericError(xmlGenericErrorContext,
+				"  --> %s\n", child->name);
+#endif
+		}
+		child = child->next;
+		/*
+		 * Skip ignorable nodes in that context
+		 */
+		child = xmlSchemaSkipIgnored(ctxt, type, child);
+	    }
+	    break;
+	default:
+	    TODO
+	    xmlGenericError(xmlGenericErrorContext,
+		    "unimplemented content type %d\n",
+		            type->contentType);
+    }
+    return(ctxt->err);
+}
+
+/**
+ * xmlSchemaValidateContent:
+ * @ctxt:  a schema validation context
+ * @elem:  an element
+ * @type:  the type declaration
+ *
+ * Validate the content of an element against the type.
+ *
+ * Returns 0 if the element is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
+    xmlNodePtr child;
+    xmlSchemaTypePtr type;
+
+    child = ctxt->node;
+    type = ctxt->type;
+
+    switch (type->type) {
+	case XML_SCHEMA_TYPE_ANY:
+	    /* Any type will do it, fine */
+	    TODO /* handle recursivity */
+	    break;
+	case XML_SCHEMA_TYPE_COMPLEX:
+	    xmlSchemaValidateComplexType(ctxt, node);
+	    break;
+	case XML_SCHEMA_TYPE_ELEMENT: {
+	    xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
+	    /*
+	     * Handle element reference here
+	     */
+	    if (decl->ref != NULL) {
+		if (decl->refDecl == NULL) {
+		    ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
+		    if (ctxt->error != NULL)
+			ctxt->error(ctxt->userData,
+		    "Internal error: element reference %s not resolved\n",
+				    decl->ref);
+		    return(-1);
+		}
+		ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
+		decl = decl->refDecl;
+	    }
+	    xmlSchemaValidateElementType(ctxt, node);
+	    ctxt->type = type;
+	    break;
+	}
+	case XML_SCHEMA_TYPE_BASIC:
+	    xmlSchemaValidateBasicType(ctxt, node);
+	    break;
+	case XML_SCHEMA_TYPE_FACET:
+	    TODO
+	    break;
+	case XML_SCHEMA_TYPE_SIMPLE:
+	    xmlSchemaValidateSimpleType(ctxt, node);
+	    break;
+	case XML_SCHEMA_TYPE_SEQUENCE:
+	    TODO
+	    break;
+	case XML_SCHEMA_TYPE_CHOICE:
+	    TODO
+	    break;
+	case XML_SCHEMA_TYPE_ALL:
+	    TODO
+	    break;
+	case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
+	    TODO
+	    break;
+	case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
+	    TODO
+	    break;
+	case XML_SCHEMA_TYPE_UR:
+	    TODO
+	    break;
+	case XML_SCHEMA_TYPE_RESTRICTION:
+	    /*xmlSchemaValidateRestrictionType(ctxt, node); */
+	    TODO
+	    break;
+	case XML_SCHEMA_TYPE_EXTENSION:
+	    TODO
+	    break;
+	case XML_SCHEMA_TYPE_ATTRIBUTE:
+	    TODO
+	    break;
+	case XML_SCHEMA_TYPE_GROUP:
+	    TODO
+	    break;
+	case XML_SCHEMA_TYPE_NOTATION:
+	    TODO
+	    break;
+	case XML_SCHEMA_TYPE_LIST:
+	    TODO
+	    break;
+	case XML_SCHEMA_TYPE_UNION:
+	    TODO
+	    break;
+	case XML_SCHEMA_FACET_MININCLUSIVE:
+	    TODO
+	    break;
+	case XML_SCHEMA_FACET_MINEXCLUSIVE:
+	    TODO
+	    break;
+	case XML_SCHEMA_FACET_MAXINCLUSIVE:
+	    TODO
+	    break;
+	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
+	    TODO
+	    break;
+	case XML_SCHEMA_FACET_TOTALDIGITS:
+	    TODO
+	    break;
+	case XML_SCHEMA_FACET_FRACTIONDIGITS:
+	    TODO
+	    break;
+	case XML_SCHEMA_FACET_PATTERN:
+	    TODO
+	    break;
+	case XML_SCHEMA_FACET_ENUMERATION:
+	    TODO
+	    break;
+	case XML_SCHEMA_FACET_WHITESPACE:
+	    TODO
+	    break;
+	case XML_SCHEMA_FACET_LENGTH:
+	    TODO
+	    break;
+	case XML_SCHEMA_FACET_MAXLENGTH:
+	    TODO
+	    break;
+	case XML_SCHEMA_FACET_MINLENGTH:
+	    TODO
+	    break;
+    }
+    xmlSchemaValidateAttributes(ctxt, node, type->attributes);
+
+    if (ctxt->node == NULL)
+	return(ctxt->err);
+    ctxt->node = ctxt->node->next;
+    ctxt->type = type->next;
+    return(ctxt->err);
+}
+
+/**
+ * xmlSchemaValidateType:
+ * @ctxt:  a schema validation context
+ * @elem:  an element
+ * @type:  the list of type declarations
+ *
+ * Validate the content of an element against the types.
+ *
+ * Returns 0 if the element is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
+	                  xmlSchemaElementPtr elemDecl,
+			  xmlSchemaTypePtr type) {
+    xmlChar *nil;
+
+    if ((elem->content == NULL) || (type == NULL) || (elemDecl == NULL))
+	return(0);
+    /*
+     * 3.3.4 : 2
+     */
+    if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
+	ctxt->err = XML_SCHEMAS_ERR_ISABSTRACT;
+        if (ctxt->error != NULL)
+            ctxt->error(ctxt->userData, "Element %s is abstract\n", elem->name);
+	return(ctxt->err);
+    }
+    /*
+     * 3.3.4: 3
+     */
+    nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
+    if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
+	/* 3.3.4: 3.2 */
+	if (xmlStrEqual(nil, BAD_CAST "true")) {
+	    if (elem->children != NULL) {
+		ctxt->err = XML_SCHEMAS_ERR_NOTEMPTY;
+		if (ctxt->error != NULL)
+		    ctxt->error(ctxt->userData, "Element %s is not empty\n",
+			        elem->name);
+		return(ctxt->err);
+	    }
+	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
+		(elemDecl->value != NULL)) {
+		ctxt->err = XML_SCHEMAS_ERR_HAVEDEFAULT;
+		if (ctxt->error != NULL)
+		    ctxt->error(ctxt->userData,
+			    "Empty element %s cannot get a fixed value\n",
+			        elem->name);
+		return(ctxt->err);
+	    }
+	}
+    } else {
+	/* 3.3.4: 3.1 */
+	if (nil != NULL) {
+	    ctxt->err = XML_SCHEMAS_ERR_NOTNILLABLE;
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData,
+			"Element %s with xs:nil but not nillable\n",
+			    elem->name);
+	    xmlFree(nil);
+	    return(ctxt->err);
+	}
+    }
+
+    /* TODO 3.3.4: 4 if the element carries xs:type*/
+
+    ctxt->type = elemDecl->subtypes;
+    ctxt->node = elem->children;
+    xmlSchemaValidateContent(ctxt, elem);
+    xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
+    
+    return(ctxt->err);
+}
+
+
+/**
+ * xmlSchemaValidateAttributes:
+ * @ctxt:  a schema validation context
+ * @elem:  an element
+ * @attributes:  the list of attribute declarations
+ *
+ * Validate the attributes of an element.
+ *
+ * Returns 0 if the element is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
+	                    xmlSchemaAttributePtr attributes) {
+    int i, ret;
+    xmlAttrPtr attr;
+    xmlChar *value;
+
+    if (attributes == NULL)
+	return(0);
+    while (attributes != NULL) {
+	for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
+	    attr = ctxt->attr[i].attr;
+	    if (attr == NULL)
+		continue;
+	    if (!xmlStrEqual(attr->name, attributes->name))
+		continue;
+	    /*
+	     * TODO: handle the mess about namespaces here.
+	     */
+	    if ((attr->ns != NULL) /* || (attributes->ns != NULL) */) {
+		TODO
+	    }
+	    if (attributes->subtypes == NULL) {
+		ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
+		if (ctxt->error != NULL)
+		    ctxt->error(ctxt->userData,
+		"Internal error: attribute %s type not resolved\n",
+				attr->name);
+		continue;
+	    }
+	    value = xmlNodeListGetString(elem->doc, attr->children, 1);
+	    ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
+		                               value);
+	    if (ret != 0) {
+		ctxt->err = XML_SCHEMAS_ERR_ATTRINVALID;
+		if (ctxt->error != NULL)
+		    ctxt->error(ctxt->userData,
+		"attribute %s on %s does not match type\n",
+				attr->name, elem->name);
+	    } else {
+		ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
+	    }
+	    if (value != NULL) {
+		xmlFree(value);
+	    }
+	}
+	attributes = attributes->next;
+    }
+    return(ctxt->err);
+}
+
+/**
+ * xmlSchemaValidateElement:
+ * @ctxt:  a schema validation context
+ * @elem:  an element
+ *
+ * Validate an element in a tree
+ *
+ * Returns 0 if the element is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem) {
+    xmlSchemaElementPtr elemDecl;
+    int ret, attrBase;
+
+    if (elem->ns != NULL)
+	elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
+		elem->name, elem->ns->href, NULL);
+    else
+	elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
+		elem->name, NULL, NULL);
+    /*
+     * 3.3.4 : 1
+     */
+    if (elemDecl == NULL) {
+	ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
+        if (ctxt->error != NULL)
+            ctxt->error(ctxt->userData, "Element %s not declared\n",
+                        elem->name);
+	return(ctxt->err);
+    }
+    if (elemDecl->subtypes == NULL) {
+	ctxt->err = XML_SCHEMAS_ERR_NOTYPE;
+        if (ctxt->error != NULL)
+            ctxt->error(ctxt->userData, "Element %s has no type\n",
+                        elem->name);
+	return(ctxt->err);
+    }
+    /*
+     * Verify the attributes
+     */
+    attrBase = ctxt->attrBase;
+    ctxt->attrBase = ctxt->attrNr;
+    xmlSchemaRegisterAttributes(ctxt, elem->properties);
+    xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
+    /*
+     * Verify the element content recursively
+     */
+    if (elemDecl->contModel != NULL) {
+	ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
+			     (xmlRegExecCallbacks) xmlSchemaValidateCallback,
+			     ctxt);
+#ifdef DEBUG_AUTOMATA
+	xmlGenericError(xmlGenericErrorContext,
+		"====> %s\n", elem->name);
+#endif
+    }
+    xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
+    ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
+#ifdef DEBUG_AUTOMATA
+    xmlGenericError(xmlGenericErrorContext,
+	    "====> %s : %d\n", elem->name, ret);
+#endif
+    if (ret == 0) {
+        if (ctxt->error != NULL)
+            ctxt->error(ctxt->userData, "Element %s content check failed\n",
+                        elem->name);
+    } else if (ret < 0) {
+        if (ctxt->error != NULL)
+            ctxt->error(ctxt->userData, "Element %s content check failed\n",
+                        elem->name);
+#ifdef DEBUG_CONTENT
+    } else {
+	xmlGenericError(xmlGenericErrorContext,
+                        "Element %s content check succeeded\n", elem->name);
+
+#endif
+    }
+    if (elemDecl->contModel != NULL) {
+	xmlRegFreeExecCtxt(ctxt->regexp);
+    }
+    /*
+     * Verify that all attributes were Schemas-validated
+     */
+    xmlSchemaCheckAttributes(ctxt, elem);
+    ctxt->attrNr = ctxt->attrBase;
+    ctxt->attrBase = attrBase;
+    
+    return(ctxt->err);
+}
+
+/**
+ * xmlSchemaValidateDocument:
+ * @ctxt:  a schema validation context
+ * @doc:  a parsed document tree
+ *
+ * Validate a document tree in memory.
+ *
+ * Returns 0 if the document is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
+    xmlNodePtr root;
+    xmlSchemaElementPtr elemDecl;
+
+    root = xmlDocGetRootElement(doc);
+    if (root == NULL) {
+	ctxt->err = XML_SCHEMAS_ERR_NOROOT;
+        if (ctxt->error != NULL)
+            ctxt->error(ctxt->userData, "document has no root\n");
+        return(ctxt->err);
+    }
+    if (root->ns != NULL)
+	elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
+		root->name, root->ns->href, NULL);
+    else
+	elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
+		root->name, NULL, NULL);
+    if (elemDecl == NULL) {
+	ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
+        if (ctxt->error != NULL)
+            ctxt->error(ctxt->userData, "Element %s not declared\n",
+                        root->name);
+    }
+    if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
+	ctxt->err = XML_SCHEMAS_ERR_NOTTOPLEVEL;
+        if (ctxt->error != NULL)
+            ctxt->error(ctxt->userData, "Root element %s not toplevel\n",
+                        root->name);
+    }
+    /*
+     * Okay, start the recursive validation
+     */
+    xmlSchemaValidateElement(ctxt, root);
+
+    return(ctxt->err);
+}
+
+/************************************************************************
+ * 									*
+ * 			SAX Validation code				*
+ * 									*
+ ************************************************************************/
+
+/************************************************************************
+ * 									*
+ * 			Validation interfaces				*
+ * 									*
+ ************************************************************************/
+
+/**
+ * xmlSchemaNewValidCtxt:
+ * @schema:  a precompiled XML Schemas
+ *
+ * Create an XML Schemas validation context based on the given schema
+ *
+ * Returns the validation context or NULL in case of error
+ */
+xmlSchemaValidCtxtPtr
+xmlSchemaNewValidCtxt(xmlSchemaPtr schema) {
+    xmlSchemaValidCtxtPtr ret;
+
+    ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
+    if (ret == NULL) {
+	xmlGenericError(xmlGenericErrorContext,
+		"Failed to allocate new schama validation context\n");
+        return (NULL);
+    }
+    memset(ret, 0, sizeof(xmlSchemaValidCtxt));
+    ret->schema = schema;
+    ret->attrNr = 0;
+    ret->attrMax = 10;
+    ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
+						  sizeof(xmlSchemaAttrState));
+    if (ret->attr == NULL) {
+	free(ret);
+	return(NULL);
+    }
+    memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
+    return (ret);
+}
+
+/**
+ * xmlSchemaFreeValidCtxt:
+ * @ctxt:  the schema validation context
+ *
+ * Free the resources associated to the schema validation context
+ */
+void
+xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt) {
+    if (ctxt == NULL)
+	return;
+    if (ctxt->attr != NULL)
+	xmlFree(ctxt->attr);
+    xmlFree(ctxt);
+}
+
+/**
+ * xmlSchemaSetValidErrors:
+ * @ctxt:  a schema validation context
+ * @err:  the error function
+ * @warn: the warning function
+ * @ctxt: the functions context
+ *
+ * Set the error and warning callback informations
+ */
+void
+xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
+	xmlSchemaValidityErrorFunc err,
+	xmlSchemaValidityWarningFunc warn, void *ctx) {
+    if (ctxt == NULL)
+	return;
+    ctxt->error = err;
+    ctxt->warning = warn;
+    ctxt->userData = ctx;
+}
+
+/**
+ * xmlSchemaValidateDoc:
+ * @ctxt:  a schema validation context
+ * @doc:  a parsed document tree
+ *
+ * Validate a document tree in memory.
+ *
+ * Returns 0 if the document is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+int
+xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
+    int ret;
+
+    if ((ctxt == NULL) || (doc == NULL))
+	return(-1);
+
+    ctxt->doc = doc;
+    ret = xmlSchemaValidateDocument(ctxt, doc);
+    return(ret);
+}
+
+/**
+ * xmlSchemaValidateStream:
+ * @ctxt:  a schema validation context
+ * @input:  the input to use for reading the data
+ * @enc:  an optional encoding information
+ * @sax:  a SAX handler for the resulting events
+ * @user_data:  the context to provide to the SAX handler.
+ *
+ * Validate a document tree in memory.
+ *
+ * Returns 0 if the document is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+int	
+xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
+	xmlParserInputBufferPtr input, xmlCharEncoding enc,
+	xmlSAXHandlerPtr sax, void *user_data) {
+    if ((ctxt == NULL) || (input == NULL))
+	return(-1);
+    ctxt->input = input;
+    ctxt->enc = enc;
+    ctxt->sax = sax;
+    ctxt->user_data = user_data;
+    TODO
+    return(0);
+}
+
+#endif /* LIBXML_SCHEMAS_ENABLED */