Edit

kc3-lang/libxml2/xmlschemas.c

Branch :

  • Show log

    Commit

  • Author : Daniel Veillard
    Date : 2003-07-15 13:34:05
    Hash : 34ba3879
    Message : removed some warnings by casting xmlChar to unsigned int and a couple of * DOCBparser.c HTMLparser.c entities.c parser.c relaxng.c xmlschemas.c xpath.c: removed some warnings by casting xmlChar to unsigned int and a couple of others. * xmlschemastypes.c: fixes a segfault on empty hexBinary strings Daniel

  • xmlschemas.c
  • /*
     * 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/uri.h>
    
    #include <libxml/xmlschemas.h>
    #include <libxml/schemasInternals.h>
    #include <libxml/xmlschemastypes.h>
    #include <libxml/xmlautomata.h>
    #include <libxml/xmlregexp.h>
    
    /* #define DEBUG 1 */
    /* #define DEBUG_CONTENT 1 */
    /* #define DEBUG_TYPE 1 */
    /* #define DEBUG_CONTENT_REGEXP 1 */
    /* #define DEBUG_AUTOMATA 1 */
    
    #define UNBOUNDED (1 << 30)
    #define TODO 								\
        xmlGenericError(xmlGenericErrorContext,				\
    	    "Unimplemented block at %s:%d\n",				\
                __FILE__, __LINE__);
    
    #define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar *)"the default namespace"
    
    /*
     * 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 */
        xmlSchemaValidError err;
        int	                nberrors;
    
        xmlSchemaPtr       schema;        /* The schema in use */
        xmlChar 	      *container;     /* the current element, group, ... */
        int counter;
    
        xmlChar	      *URL;
        xmlDocPtr          doc;
    
        const char     *buffer;
        int               size;
    
        /*
         * 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;
        int                     nberrors;
    
        xmlNodePtr              node;
        xmlNodePtr              cur;
        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) {
            ctxt->nberrors++;
            if ((ctxt != NULL) && (ctxt->error != NULL))
                ctxt->error(ctxt->userData, "Out of memory\n");
            return (NULL);
        }
        memset(ret, 0, sizeof(xmlSchema));
    
        return (ret);
    }
    
    /**
     * xmlSchemaNewFacet:
     *
     * Allocate a new Facet structure.
     *
     * Returns the newly allocated structure or NULL in case or error
     */
    xmlSchemaFacetPtr
    xmlSchemaNewFacet(void)
    {
        xmlSchemaFacetPtr ret;
    
        ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
        if (ret == NULL) {
            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) {
            ctxt->nberrors++;
            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);
    }
    
    /**
     * xmlSchemaFreeAnnot:
     * @annot:  a schema type structure
     *
     * Deallocate a annotation structure
     */
    static void
    xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
    {
        if (annot == NULL)
            return;
        xmlFree(annot);
    }
    
    /**
     * 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);
        if (attr->ref != NULL)
            xmlFree((xmlChar *) attr->ref);
        if (attr->refNs != NULL)
            xmlFree((xmlChar *) attr->refNs);
        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->annot != NULL)
            xmlSchemaFreeAnnot(elem->annot);
        if (elem->contModel != NULL)
    	xmlRegFreeRegexp(elem->contModel);
        xmlFree(elem);
    }
    
    /**
     * xmlSchemaFreeFacet:
     * @facet:  a schema facet structure
     *
     * Deallocate a Schema Facet structure.
     */
    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);
        if (facet->annot != NULL)
    	xmlSchemaFreeAnnot(facet->annot);
        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)
            xmlSchemaFreeAnnot(type->annot);
        if (type->facets != NULL) {
    	xmlSchemaFacetPtr facet, next;
    
    	facet = type->facets;
    	while (facet != NULL) {
    	    next = facet->next;
    	    xmlSchemaFreeFacet(facet);
    	    facet = next;
    	}
        }
        xmlFree(type);
    }
    
    /**
     * xmlSchemaFree:
     * @schema:  a schema structure
     *
     * Deallocate a Schema structure.
     */
    void
    xmlSchemaFree(xmlSchemaPtr schema)
    {
        if (schema == NULL)
            return;
    
        if (schema->id != NULL)
            xmlFree((xmlChar *) schema->id);
        if (schema->targetNamespace != NULL)
            xmlFree((xmlChar *) schema->targetNamespace);
        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->groupDecl != NULL)
            xmlHashFree(schema->groupDecl,
                        (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 xmlChar *prefix = 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 = (long) node->content;
    	    } else if ((node->prev != NULL) &&
    		       (node->prev->type == XML_ELEMENT_NODE)) {
    		line = (long) node->prev->content;
    	    } else if ((node->parent != NULL) &&
    		       (node->parent->type == XML_ELEMENT_NODE)) {
    		line = (long) node->parent->content;
    	    }
    	    if ((node->doc != NULL) && (node->doc->URL != NULL))
    		file = node->doc->URL;
    	    if (node->name != NULL)
    		name = node->name;
    	    if ((node->type == XML_ELEMENT_NODE) && (node->ns != NULL) &&
    	        (node->ns->prefix != NULL))
    		prefix = node->ns->prefix;
    	}
        } 
        
        if (ctxt != NULL)
    	type = "compilation error";
        else if (schema != NULL)
    	type = "runtime error";
    
        if ((file != NULL) && (line != 0) && (name != NULL) && (prefix != NULL))
    	ctxt->error(ctxt->userData, "%s: file %s line %d element %s:%s\n",
    		type, file, line, prefix, name);
        else 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) && (prefix != NULL))
    	ctxt->error(ctxt->userData, "%s: file %s element %s:%s\n",
    		type, file, prefix, 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) && (prefix != NULL))
    	ctxt->error(ctxt->userData, "%s: element %s:%s\n", type, prefix, name);
        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,
    		     const xmlChar *name ATTRIBUTE_UNUSED,
    		     const xmlChar *context ATTRIBUTE_UNUSED,
    		     const xmlChar *namespace ATTRIBUTE_UNUSED)
    {
        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;
    	case XML_SCHEMA_CONTENT_ANY:
    	    fprintf(output, "any ");
    	    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", (const char *) 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 the group definition or NULL if not found.
     */
    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) {
            ctxt->nberrors++;
            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) {
            ctxt->nberrors++;
            if ((ctxt != NULL) && (ctxt->error != NULL))
                ctxt->error(ctxt->userData, "Notation %s already defined\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) {
            ctxt->nberrors++;
            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) {
            ctxt->nberrors++;
            if ((ctxt != NULL) && (ctxt->error != NULL))
                ctxt->error(ctxt->userData, "Attribute %s already defined\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) {
            ctxt->nberrors++;
            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) {
            ctxt->nberrors++;
            if ((ctxt != NULL) && (ctxt->error != NULL))
                ctxt->error(ctxt->userData, "Attribute group %s already defined\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) {
            ctxt->nberrors++;
            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) {
    	    ctxt->nberrors++;
    	    if ((ctxt != NULL) && (ctxt->error != NULL))
    		ctxt->error(ctxt->userData, "Element %s already defined\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) {
            ctxt->nberrors++;
            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) {
            ctxt->nberrors++;
            if ((ctxt != NULL) && (ctxt->error != NULL))
                ctxt->error(ctxt->userData, "Type %s already defined\n", name);
            xmlFree((char *) ret->name);
            xmlFree(ret);
            return (NULL);
        }
        ret->minOccurs = 1;
        ret->maxOccurs = 1;
    
        return (ret);
    }
    
    /**
     * xmlSchemaAddGroup:
     * @ctxt:  a schema validation context
     * @schema:  the schema being built
     * @name:  the group name
     *
     * Add an XML schema Group definition
     *
     * Returns the new struture or NULL in case of error
     */
    static xmlSchemaTypePtr
    xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
                     const xmlChar * name)
    {
        xmlSchemaTypePtr ret = NULL;
        int val;
    
        if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
            return (NULL);
    
        if (schema->groupDecl == NULL)
            schema->groupDecl = xmlHashCreate(10);
        if (schema->groupDecl == NULL)
            return (NULL);
    
        ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
        if (ret == NULL) {
            ctxt->nberrors++;
            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->groupDecl, name, schema->targetNamespace,
                               ret);
        if (val != 0) {
            ctxt->nberrors++;
            if ((ctxt != NULL) && (ctxt->error != NULL))
                ctxt->error(ctxt->userData, "Group %s already defined\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) {
    	ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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 {
            ctxt->nberrors++;
    	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();
        if (facet == NULL)
    	return (NULL);
        facet->node = node;
        value = xmlGetProp(node, (const xmlChar *) "value");
        if (value == NULL) {
            ctxt->nberrors++;
    	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 {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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 {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
    	    ctxt->nberrors++;
    	    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));
        ret->node = node;
        child = node->children;
        if (IS_SCHEMA(child, "annotation")) {
    	ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
    	child = child->next;
        }
        if (IS_SCHEMA(child, "simpleType")) {
    	ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
    	child = child->next;
        }
        if (child != NULL) {
            ctxt->nberrors++;
    	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) {
    	    ctxt->nberrors++;
    	    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);
    	if (name == NULL) {
    	    ctxt->nberrors++;
    	    if ((ctxt != NULL) && (ctxt->error != NULL))
    		ctxt->error(ctxt->userData,
    			"out of memory\n");
    	    return (NULL);
    	}
        }
        ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
        if (ret == NULL) {
            xmlFree(name);
    	if (ref != NULL)
    	    xmlFree(ref);
            return (NULL);
        }
        ret->ref = ref;
        ret->refNs = refNs;
        ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
        ret->node = node;
        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) {
            ctxt->nberrors++;
    	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;
        xmlFree(name);
        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) {
    	    ctxt->nberrors++;
    	    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);
        ret->node = node;
        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)) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
    	    ctxt->nberrors++;
    	    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 = xmlSchemaAddGroup(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) {
            ctxt->nberrors++;
    	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_ALL;
        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) {
            ctxt->nberrors++;
    	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);
    }
    
    /**
     * xmlSchemaParseImport:
     * @ctxt:  a schema validation context
     * @schema:  the schema being built
     * @node:  a subtree containing XML Schema informations
     *
     * parse a XML schema Import 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 int
    xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
                              xmlNodePtr node)
    {
        xmlNodePtr child = NULL;
        xmlChar *namespace;
        xmlChar *schemaLocation;
        xmlChar *previous;
        xmlURIPtr check;
    
        if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
            return (-1);
    
        namespace = xmlGetProp(node, BAD_CAST "namespace");
        if (namespace != NULL) {
    	check = xmlParseURI((const char *) namespace);
    	if (check == NULL) {
    	    ctxt->nberrors++;
    	    xmlSchemaErrorContext(ctxt, schema, node, child);
    	    if ((ctxt != NULL) && (ctxt->error != NULL))
    		ctxt->error(ctxt->userData,
    			    "Import namespace attribute is not an URI: %s\n",
    			    namespace);
    	    xmlFree(namespace);
    	    return(-1);
    	} else {
    	    xmlFreeURI(check);
    	}
        }
        schemaLocation = xmlGetProp(node, BAD_CAST "schemaLocation");
        if (schemaLocation != NULL) {
    	check = xmlParseURI((const char *) schemaLocation);
    	if (check == NULL) {
    	    ctxt->nberrors++;
    	    xmlSchemaErrorContext(ctxt, schema, node, child);
    	    if ((ctxt != NULL) && (ctxt->error != NULL))
    		ctxt->error(ctxt->userData,
    		    "Import schemaLocation attribute is not an URI: %s\n",
    			    schemaLocation);
    	    if (namespace != NULL)
    		xmlFree(namespace);
    	    xmlFree(schemaLocation);
    	    return(-1);
    	} else {
    	    xmlFreeURI(check);
    	}
        }
        if (schema->schemasImports == NULL) {
    	schema->schemasImports = xmlHashCreate(10);
    	if (schema->schemasImports == NULL) {
    	    ctxt->nberrors++;
    	    xmlSchemaErrorContext(ctxt, schema, node, child);
    	    if ((ctxt != NULL) && (ctxt->error != NULL))
    		ctxt->error(ctxt->userData,
    		    "Internal: failed to build import table\n");
    	    if (namespace != NULL)
    		xmlFree(namespace);
    	    if (schemaLocation != NULL)
    		xmlFree(schemaLocation);
    	    return(-1);
    	}
        }
        if (namespace == NULL) {
    	previous = xmlHashLookup(schema->schemasImports,
    		XML_SCHEMAS_DEFAULT_NAMESPACE);
    	if (schemaLocation != NULL) {
    	    if (previous != NULL) {
    		if (!xmlStrEqual(schemaLocation, previous)) {
    		    ctxt->nberrors++;
    		    xmlSchemaErrorContext(ctxt, schema, node, child);
    		    if ((ctxt != NULL) && (ctxt->error != NULL))
    			ctxt->error(ctxt->userData,
    	"Redefining import for default namespace with a different URI: %s\n",
    	                            schemaLocation);
    		}
    	    } else {
    		xmlHashAddEntry(schema->schemasImports, 
    			XML_SCHEMAS_DEFAULT_NAMESPACE, schemaLocation);
    	    }
    	}
        } else {
    	previous = xmlHashLookup(schema->schemasImports, namespace);
    	if (schemaLocation != NULL) {
    	    if (previous != NULL) {
    		if (!xmlStrEqual(schemaLocation, previous)) {
    		    ctxt->nberrors++;
    		    xmlSchemaErrorContext(ctxt, schema, node, child);
    		    if ((ctxt != NULL) && (ctxt->error != NULL))
    			ctxt->error(ctxt->userData,
    	"Redefining import for namespace %s with a different URI: %s\n",
    	                            namespace, schemaLocation);
    		}
    	    } else {
    		xmlHashAddEntry(schema->schemasImports, 
    			namespace, schemaLocation);
    	    }
    	}
        }
    
        child = node->children;
        while (IS_SCHEMA(child, "annotation")) {
    	/*
    	 * the annotations here are simply discarded ...
    	 */
    	child = child->next;
        }
        if (child != NULL) {
            ctxt->nberrors++;
    	xmlSchemaErrorContext(ctxt, schema, node, child);
    	if ((ctxt != NULL) && (ctxt->error != NULL))
    	    ctxt->error(ctxt->userData,
    			"Import has unexpected content\n");
    	return(-1);
        }
        return(1);
    }
    
    /**
     * 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) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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)) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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) {
            ctxt->nberrors++;
    	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")) {
    	type->subtypes = 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) {
            ctxt->nberrors++;
    	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;
        int nberrors;
    
        if ((ctxt == NULL) || (node == NULL))
            return (NULL);
    
        nberrors = ctxt->nberrors;
        ctxt->nberrors = 0;
        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")) {
    	        ctxt->nberrors++;
    		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")) {
    	        ctxt->nberrors++;
    		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")) {
    		xmlSchemaParseImport(ctxt, schema, child);
    	    } else if (IS_SCHEMA(child, "redefine")) {
    		TODO
    	    }
    	    child = child->next;
    	}
    	while (child != NULL) {
    	    if (IS_SCHEMA(child, "complexType")) {
                    xmlSchemaParseComplexType(ctxt, schema, child);
    		child = child->next;
    	    } else if (IS_SCHEMA(child, "simpleType")) {
                    xmlSchemaParseSimpleType(ctxt, schema, child);
    		child = child->next;
    	    } else if (IS_SCHEMA(child, "element")) {
                    xmlSchemaParseElement(ctxt, schema, child, 1);
    		child = child->next;
    	    } else if (IS_SCHEMA(child, "attribute")) {
                    xmlSchemaParseAttribute(ctxt, schema, child);
    		child = child->next;
    	    } else if (IS_SCHEMA(child, "attributeGroup")) {
                    xmlSchemaParseAttributeGroup(ctxt, schema, child);
    		child = child->next;
    	    } else if (IS_SCHEMA(child, "group")) {
    		xmlSchemaParseGroup(ctxt, schema, child);
    		child = child->next;
    	    } else if (IS_SCHEMA(child, "notation")) {
    		xmlSchemaParseNotation(ctxt, schema, child);
    		child = child->next;
    	    } else {
    	        ctxt->nberrors++;
    		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;
                }
            }
        }
        if (ctxt->nberrors != 0) {
            if (schema != NULL) {
    	    xmlSchemaFree(schema);
    	    schema = NULL;
    	}
        }
        ctxt->nberrors = nberrors;
    #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);
    }
    
    /**
     * xmlSchemaNewMemParserCtxt:
     * @buffer:  a pointer to a char array containing the schemas
     * @size:  the size of the array
     *
     * Create an XML Schemas parse context for that memory buffer expected
     * to contain an XML Schemas file.
     *
     * Returns the parser context or NULL in case of error
     */
    xmlSchemaParserCtxtPtr
    xmlSchemaNewMemParserCtxt(const char *buffer, int size) {
        xmlSchemaParserCtxtPtr ret;
    
        if ((buffer == NULL) || (size <= 0))
    	return(NULL);
    
        ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
        if (ret == NULL) {
    	xmlGenericError(xmlGenericErrorContext,
    		"Failed to allocate new schama parser context\n");
            return (NULL);
        }
        memset(ret, 0, sizeof(xmlSchemaParserCtxt));
        ret->buffer = buffer;
        ret->size = size;
        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);
        if (ctxt->doc != NULL)
    	xmlFreeDoc(ctxt->doc);
        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->minOccurs > 1) {
    		    xmlAutomataStatePtr tmp;
    		    int counter;
    
    		    ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
    			                                oldstate, NULL);
    		    oldstate = ctxt->state;
    
    		    counter = xmlAutomataNewCounter(ctxt->am,
    				    elem->minOccurs - 1, 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);
    		    }
    		    tmp = ctxt->state;
    		    xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
    			                       counter);
    		    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
    			                       NULL, counter);
    
    		} 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);
    		    }
    		    xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
    		    if (elem->minOccurs == 0) {
    			/* basically an elem* */
    			xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
    		    }
    		}
    	    } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
    		xmlAutomataStatePtr tmp;
    		int counter;
    
    		ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
    						    oldstate, NULL);
    		oldstate = ctxt->state;
    
    		counter = xmlAutomataNewCounter(ctxt->am,
    				elem->minOccurs - 1, elem->maxOccurs - 1);
    
    		if (elem->refDecl != NULL) {
    		    xmlSchemaBuildAContentModel(
    			    (xmlSchemaTypePtr) elem->refDecl,
    			    ctxt, elem->refDecl->name);
    		} else {
    		    ctxt->state = xmlAutomataNewTransition(ctxt->am,
    			    ctxt->state, NULL, elem->name, type);
    		}
    		tmp = ctxt->state;
    		xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
    					   counter);
    		ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
    					   NULL, counter);
    		if (elem->minOccurs == 0) {
    		    /* basically an elem? */
    		    xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
    		}
    
    	    } 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;
    
    	    /*
    	     * If max and min occurances are default (1) then
    	     * simply iterate over the subtypes
    	     */
    	    if ((type->minOccurs == 1 ) && (type->maxOccurs == 1)) {
    	        subtypes = type->subtypes;
    	        while (subtypes != NULL) {
    		    xmlSchemaBuildAContentModel(subtypes, ctxt, name);
    		    subtypes = subtypes->next;
    	        }
    	    } else {
    	        xmlAutomataStatePtr oldstate = ctxt->state;
    	        if (type->maxOccurs >= UNBOUNDED) {
    		    if (type->minOccurs > 1) {
    		        xmlAutomataStatePtr tmp;
    		        int counter;
    
    		        ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
    			                                oldstate, NULL);
    		        oldstate = ctxt->state;
    
    		        counter = xmlAutomataNewCounter(ctxt->am,
    			        	    type->minOccurs - 1, UNBOUNDED);
    
    	                subtypes = type->subtypes;
    	                while (subtypes != NULL) {
    		            xmlSchemaBuildAContentModel(subtypes, ctxt, name);
    		            subtypes = subtypes->next;
    	                }
    		        tmp = ctxt->state;
    		        xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
    		                            counter);
    		        ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
    		                            NULL, counter);
    
    		    } else {
    	                subtypes = type->subtypes;
    	                while (subtypes != NULL) {
    		            xmlSchemaBuildAContentModel(subtypes, ctxt, name);
    		            subtypes = subtypes->next;
    	                }
    		        xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
    		        if (type->minOccurs == 0) {
    			    xmlAutomataNewEpsilon(ctxt->am, oldstate,
    				                  ctxt->state);
    		        }
    		    }
    	        } else if ((type->maxOccurs > 1) || (type->minOccurs > 1)) {
    		    xmlAutomataStatePtr tmp;
    		    int counter;
    
    		    ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
    						    oldstate, NULL);
    		    oldstate = ctxt->state;
    
    		    counter = xmlAutomataNewCounter(ctxt->am,
    		                  type->minOccurs - 1, type->maxOccurs - 1);
    
    	            subtypes = type->subtypes;
    	            while (subtypes != NULL) {
    		        xmlSchemaBuildAContentModel(subtypes, ctxt, name);
    		        subtypes = subtypes->next;
    	            }
    		    tmp = ctxt->state;
    		    xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
    		          counter);
    		    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
    		                                             NULL, counter);
    		    if (type->minOccurs == 0) {
    		        xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
    		    }
    
    	        } else {
    	            subtypes = type->subtypes;
    	            while (subtypes != NULL) {
    		        xmlSchemaBuildAContentModel(subtypes, ctxt, name);
    		        subtypes = subtypes->next;
    	            }
    		    if (type->minOccurs == 0) {
    		        xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
    		    }
    	        }
    	    }
    	    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
    	     */
    	    if (type->maxOccurs == 1) {
    		subtypes = type->subtypes;
    		while (subtypes != NULL) {
    		    ctxt->state = start;
    		    xmlSchemaBuildAContentModel(subtypes, ctxt, name);
    		    xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
    		    subtypes = subtypes->next;
    		}
    	    } else {
    		int counter;
    		xmlAutomataStatePtr hop;
    		int maxOccurs = type->maxOccurs == UNBOUNDED ?
    		                      UNBOUNDED : type->maxOccurs - 1;
    		int minOccurs = type->minOccurs < 1 ? 0 : type->minOccurs - 1;
    
    		/*
    		 * use a counter to keep track of the number of transtions
    		 * which went through the choice.
    		 */
    		counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
    		hop = xmlAutomataNewState(ctxt->am);
    
    		subtypes = type->subtypes;
    		while (subtypes != NULL) {
    		    ctxt->state = start;
    		    xmlSchemaBuildAContentModel(subtypes, ctxt, name);
    		    xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
    		    subtypes = subtypes->next;
    		}
    		xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
    		xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
    	    }
    	    if (type->minOccurs == 0) {
    		xmlAutomataNewEpsilon(ctxt->am, start, end);
    	    }
    	    ctxt->state = end;
    	    break;
    	}
    	case XML_SCHEMA_TYPE_ALL: {
    	    xmlAutomataStatePtr start;
    	    xmlSchemaTypePtr subtypes;
    	    xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
    	    int lax;
    
    	    subtypes = type->subtypes;
    	    if (subtypes == NULL)
    		break;
    	    start = ctxt->state;
    	    while (subtypes != NULL) {
    		ctxt->state = start;
    		elem = (xmlSchemaElementPtr) subtypes;
    
    		/* TODO : handle the namespace too */
    		if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
    		    xmlAutomataNewOnceTrans(ctxt->am, ctxt->state, ctxt->state,
    				    elem->name, 1, 1, subtypes);
    		} else {
    		    xmlAutomataNewCountTrans(ctxt->am, ctxt->state, ctxt->state,
    				    elem->name, elem->minOccurs,
    				    elem->maxOccurs, subtypes);
    		}
    		subtypes = subtypes->next;
    	    }
    	    lax = type->minOccurs == 0;
    	    ctxt->state = xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
    		                                 lax);
    	    break;
    	}
    	case XML_SCHEMA_TYPE_RESTRICTION:
    	    if (type->subtypes != NULL)
    		xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
    	    break;
    	case XML_SCHEMA_TYPE_EXTENSION:
    	    if (type->baseType != NULL) {
    		xmlSchemaTypePtr subtypes;
    
    		xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
    		subtypes = type->subtypes;
    		while (subtypes != NULL) {
    		    xmlSchemaBuildAContentModel(subtypes, ctxt, name);
    		    subtypes = subtypes->next;
    		}
    	    } else if (type->subtypes != NULL)
    		xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
    	    break;
    	case XML_SCHEMA_TYPE_GROUP:
    	    if (type->subtypes == NULL) {
    	    }
    	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:
     * @elem:  the element
     * @ctxt:  the schema parser context
     * @name:  the element name
     *
     * Builds the content model of the element.
     */
    static void
    xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
    		           xmlSchemaParserCtxtPtr ctxt,
    		           const xmlChar *name) {
        xmlAutomataStatePtr start;
    
        if (elem->contModel != NULL)
    	return;
        if (elem->subtypes == NULL) {
    	elem->contentType = XML_SCHEMA_CONTENT_ANY;
    	return;
        }
        if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
    	return;
        if (elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC)
    	return;
    
    #ifdef DEBUG_CONTENT
        xmlGenericError(xmlGenericErrorContext,
    	    "Building content model for %s\n", name);
    #endif
    
        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);
        if (elem->contModel == NULL) {
    	xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
    	if ((ctxt != NULL) && (ctxt->error != NULL))
    	    ctxt->error(ctxt->userData,
    			"failed to compile %s content model\n",
    			name);
    	ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
    	ctxt->nberrors++;
        } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
    	xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
    	if ((ctxt != NULL) && (ctxt->error != NULL))
    	    ctxt->error(ctxt->userData,
    			"Content model of %s is not determinist:\n", name);
    	ctxt->err = XML_SCHEMAS_ERR_NOTDETERMINIST;
    	ctxt->nberrors++;
        } else {
    #ifdef DEBUG_CONTENT_REGEXP
    	xmlGenericError(xmlGenericErrorContext,
    			"Content model of %s:\n", name);
    	xmlRegexpPrint(stderr, 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,
    		     const xmlChar *context ATTRIBUTE_UNUSED,
    		     const xmlChar *namespace ATTRIBUTE_UNUSED)
    {
        if ((ctxt == NULL) || (elem == NULL))
    	return;
        if (elem->ref != NULL) {
    	xmlSchemaElementPtr elemDecl;
    
    	if (elem->subtypes != NULL) {
    	    ctxt->nberrors++;
    	    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) {
    	    ctxt->nberrors++;
    	    xmlSchemaErrorContext(ctxt, NULL, elem->node, 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) {
    	    ctxt->nberrors++;
    	    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) {
    	    ctxt->nberrors++;
    	    xmlSchemaErrorContext(ctxt, NULL, elem->node, 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 (typeDecl == NULL)
            return;
        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);
    		if (typeDecl->subtypes != 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) {
    		        ctxt->nberrors++;
    			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) {
    		        ctxt->nberrors++;
    			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);
    
    		explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
    		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) {
    		    ctxt->nberrors++;
    		    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);
    			if (typeDecl->subtypes != 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);
    			if (typeDecl->subtypes != 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_ATTRIBUTEGROUP:
    	    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;
    	}
        } 
    #ifdef DEBUG_TYPE
        if (typeDecl->node != NULL) {
    	xmlGenericError(xmlGenericErrorContext,
    		"Type of %s : %s:%d :", name, typeDecl->node->doc->URL,
    			xmlGetLineNo(typeDecl->node));
        } else {
    	xmlGenericError(xmlGenericErrorContext,
    		"Type of %s :", name);
        }
        switch (typeDecl->contentType) {
    	case XML_SCHEMA_CONTENT_SIMPLE:
    	    xmlGenericError(xmlGenericErrorContext,
    		    "simple\n"); break;
    	case XML_SCHEMA_CONTENT_ELEMENTS:
    	    xmlGenericError(xmlGenericErrorContext,
    		    "elements\n"); break;
            case XML_SCHEMA_CONTENT_UNKNOWN:
    	    xmlGenericError(xmlGenericErrorContext,
    		    "unknown !!!\n"); break;
            case XML_SCHEMA_CONTENT_EMPTY:
    	    xmlGenericError(xmlGenericErrorContext,
    		    "empty\n"); break;
            case XML_SCHEMA_CONTENT_MIXED:
    	    xmlGenericError(xmlGenericErrorContext,
    		    "mixed\n"); break;
            case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
    	    xmlGenericError(xmlGenericErrorContext,
    		    "mixed or elems\n"); break;
            case XML_SCHEMA_CONTENT_BASIC:
    	    xmlGenericError(xmlGenericErrorContext,
    		    "basic\n"); break;
    	default:
    	    xmlGenericError(xmlGenericErrorContext,
    		    "not registered !!!\n"); break;
        }
    #endif
    }
    
    /**
     * xmlSchemaCheckFacet:
     * @facet:  the facet
     * @typeDecl:  the schema type definition
     * @ctxt:  the schema parser context or NULL
     * @name: name of the type
     *
     * Checks the default values types, especially for facets 
     *
     * Returns 0 if okay or -1 in cae of error
     */
    int
    xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
    	            xmlSchemaTypePtr typeDecl,
    		    xmlSchemaParserCtxtPtr ctxt,
    		    const xmlChar *name)
    {
        static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
        int ret = 0;
    
        if (nonNegativeIntegerType == NULL) {
    	nonNegativeIntegerType = xmlSchemaGetPredefinedType(
    		BAD_CAST "nonNegativeInteger", xmlSchemaNs);
        }
        switch (facet->type) {
    	case XML_SCHEMA_FACET_MININCLUSIVE:
    	case XML_SCHEMA_FACET_MINEXCLUSIVE:
    	case XML_SCHEMA_FACET_MAXINCLUSIVE:
    	case XML_SCHEMA_FACET_MAXEXCLUSIVE: {
    	    /*
    	     * Okay we need to validate the value
    	     * at that point.
    	     */
    	    xmlSchemaValidCtxtPtr vctxt;
    
    	    vctxt = xmlSchemaNewValidCtxt(NULL);
    	    if (vctxt == NULL)
    		break;
    	    xmlSchemaValidateSimpleValue(vctxt, typeDecl,
    					 facet->value);
    	    facet->val = vctxt->value;
    	    vctxt->value = NULL;
    	    if (facet->val == NULL) {
    		/* error code */
    		if (ctxt != NULL) {
    		    ctxt->nberrors++;
    		    xmlSchemaErrorContext(ctxt, NULL,
    			    facet->node, NULL);
    		    ctxt->error(ctxt->userData,
    		    "Schemas: type %s facet value %s invalid\n",
    				name, facet->value);
    		}
    		ret = -1;
    	    }
    	    xmlSchemaFreeValidCtxt(vctxt);
    	    break;
    	}
    	case XML_SCHEMA_FACET_ENUMERATION: {
    	    /*
    	     * Okay we need to validate the value
    	     * at that point.
    	     */
    	    xmlSchemaValidCtxtPtr vctxt;
    	    int tmp;
    
    	    vctxt = xmlSchemaNewValidCtxt(NULL);
    	    if (vctxt == NULL)
    		break;
    	    tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
    					 facet->value);
    	    if (tmp != 0) {
    		if (ctxt != NULL) {
    		    ctxt->nberrors++;
    		    xmlSchemaErrorContext(ctxt, NULL,
    			    facet->node, NULL);
    		    ctxt->error(ctxt->userData,
    		    "Schemas: type %s enumeration value %s invalid\n",
    				name, facet->value);
    		}
    		ret = -1;
    	    }
    	    xmlSchemaFreeValidCtxt(vctxt);
    	    break;
    	}
    	case XML_SCHEMA_FACET_PATTERN:
    	    facet->regexp = xmlRegexpCompile(facet->value);
    	    if (facet->regexp == NULL) {
    		/* error code */
    		if (ctxt != NULL) {
    		    ctxt->nberrors++;
    		    ctxt->error(ctxt->userData,
    		"Schemas: type %s facet regexp %s invalid\n",
    				name, facet->value);
    		}
    		ret = -1;
    	    }
    	    break;
    	case XML_SCHEMA_FACET_TOTALDIGITS:
    	case XML_SCHEMA_FACET_FRACTIONDIGITS:
    	case XML_SCHEMA_FACET_LENGTH:
    	case XML_SCHEMA_FACET_MAXLENGTH:
    	case XML_SCHEMA_FACET_MINLENGTH: {
    	    int tmp;
    
    	    tmp = xmlSchemaValidatePredefinedType(
    			 nonNegativeIntegerType, facet->value,
    			 &facet->val);
    	    if (tmp != 0) {
    		/* error code */
    		if (ctxt != NULL) {
    		    ctxt->nberrors++;
    		    xmlSchemaErrorContext(ctxt, NULL,
    			    facet->node, NULL);
    		    ctxt->error(ctxt->userData,
    		    "Schemas: type %s facet value %s invalid\n",
    				name, facet->value);
    		}
    		ret = -1;
    	    }
    	    break;
    	}
    	case XML_SCHEMA_FACET_WHITESPACE: {
    	    if (xmlStrEqual(facet->value, BAD_CAST"preserve")) {
    		facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
    	    } else if (xmlStrEqual(facet->value,
    			BAD_CAST"replace")) {
    		facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
    	    } else if (xmlStrEqual(facet->value,
    			BAD_CAST"collapse")) {
    		facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
    	    } else {
    		if (ctxt != NULL) {
    		    ctxt->nberrors++;
    		    xmlSchemaErrorContext(ctxt, NULL,
    			    facet->node, NULL);
    		    ctxt->error(ctxt->userData,
    		    "Schemas: type %s whiteSpace value %s invalid\n",
    				name, facet->value);
    		}
    		ret = -1;
    	    }
    	}
    	default:
    	    break;
        }
        return(ret);
    }
    
    /**
     * xmlSchemaCheckDefaults:
     * @typeDecl:  the schema type definition
     * @ctxt:  the schema parser context
     *
     * Checks the default values types, especially for facets 
     */
    static void
    xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
    		   xmlSchemaParserCtxtPtr ctxt,
    		   const xmlChar *name)
    {
        if (name == NULL)
    	name = typeDecl->name;
        if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
    	if (typeDecl->facets != NULL) {
    	    xmlSchemaFacetPtr facet = typeDecl->facets;
    	    while (facet != NULL) {
    		xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
    		facet = facet->next;
    	    }
    	}
        }
    }
    
    /**
     * xmlSchemaAttrGrpFixup:
     * @attrgrpDecl:  the schema attribute definition
     * @ctxt:  the schema parser context
     * @name:  the attribute name
     *
     * Fixes finish doing the computations on the attributes definitions
     */
    static void
    xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
    		   xmlSchemaParserCtxtPtr ctxt,
    		   const xmlChar *name)
    {
        if (name == NULL)
    	name = attrgrpDecl->name;
        if (attrgrpDecl->attributes != NULL)
    	return;
        if (attrgrpDecl->ref != NULL) {
    	xmlSchemaAttributeGroupPtr ref;
    
    	ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
    		             attrgrpDecl->refNs);
    	if (ref == NULL) {
    	    ctxt->nberrors++;
    	    xmlSchemaErrorContext(ctxt, NULL, attrgrpDecl->node, NULL);
    	    if ((ctxt != NULL) && (ctxt->error != NULL))
    		ctxt->error(ctxt->userData,
    		    "Schemas: attribute group %s reference %s not found\n",
    			    name, attrgrpDecl->ref);
    	    return;
    	}
    	xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
    	attrgrpDecl->attributes = ref->attributes;
        } else {
            ctxt->nberrors++;
    	xmlSchemaErrorContext(ctxt, NULL, attrgrpDecl->node, NULL);
    	if ((ctxt != NULL) && (ctxt->error != NULL))
    	    ctxt->error(ctxt->userData,
    		"Schemas: attribute %s has no attributes nor reference\n",
    			name);
        }
    }
    
    /**
     * 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) {
    	    ctxt->nberrors++;
    	    xmlSchemaErrorContext(ctxt, NULL, attrDecl->node, 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) {
    	    ctxt->nberrors++;
    	    xmlSchemaErrorContext(ctxt, NULL, attrDecl->node, 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 {
    	ctxt->nberrors++;
    	xmlSchemaErrorContext(ctxt, NULL, attrDecl->node, NULL);
    	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
     *
     * 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;
        int nberrors;
    
        xmlSchemaInitTypes();
    
        if (ctxt == NULL)
            return (NULL);
    
        nberrors = ctxt->nberrors;
        ctxt->nberrors = 0;
        ctxt->counter = 0;
        ctxt->container = NULL;
    
        /*
         * First step is to parse the input document into an DOM/Infoset
         */
        if (ctxt->URL != NULL) {
    	doc = xmlParseFile((const char *) ctxt->URL);
    	if (doc == NULL) {
    	    ctxt->nberrors++;
    	    if (ctxt->error != NULL)
    		ctxt->error(ctxt->userData,
    			    "xmlSchemaParse: could not load %s\n", ctxt->URL);
    	    return (NULL);
    	}
        } else if (ctxt->buffer != NULL) {
    	doc = xmlParseMemory(ctxt->buffer, ctxt->size);
    	if (doc == NULL) {
    	    ctxt->nberrors++;
    	    if (ctxt->error != NULL)
    		ctxt->error(ctxt->userData,
    			    "xmlSchemaParse: could not parse schemas\n");
    	    return (NULL);
    	}
    	doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
    	ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
        } else {
            ctxt->nberrors++;
    	if (ctxt->error != NULL)
    	    ctxt->error(ctxt->userData,
    			"xmlSchemaParse: nothing to parse\n");
    	return (NULL);
        }
    
        /*
         * Then extract the root and Schema parse it
         */
        root = xmlDocGetRootElement(doc);
        if (root == NULL) {
            ctxt->nberrors++;
            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);
        if (ret == NULL)
    	return(NULL);
        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);
    
        /*
         * Then fixup all attributes group declarations
         */
        xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup, ctxt);
    
        if (ctxt->nberrors != 0) {
            xmlSchemaFree(ret);
    	ret = NULL;
        }
        return (ret);
    }
     
    /**
     * xmlSchemaSetParserErrors:
     * @ctxt:  a schema validation context
     * @err:  the error callback
     * @warn:  the warning callback
     * @ctx:  contextual data for the callbacks
     *
     * Set the callback functions used to handle errors for a validation context
     */
    void
    xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
    	xmlSchemaValidityErrorFunc err,
    	xmlSchemaValidityWarningFunc warn, void *ctx) {
        if (ctxt == NULL)
    	return;
        ctxt->error = err;
        ctxt->warning = warn;
        ctxt->userData = ctx;
    }
    
    /**
     * xmlSchemaFacetTypeToString:
     * @type:  the facet type
     *
     * Convert the xmlSchemaTypeType to a char string.
     *
     * Returns the char string representation of the facet type if the
     *     type is a facet and an "Internal Error" string otherwise.
     */
    static const char *
    xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
    {
        switch (type) {
            case XML_SCHEMA_FACET_PATTERN:
                return ("pattern");
    	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
                return ("maxExclusive");
    	case XML_SCHEMA_FACET_MAXINCLUSIVE:
                return ("maxInclusive");
    	case XML_SCHEMA_FACET_MINEXCLUSIVE:
                return ("minExclusive");
    	case XML_SCHEMA_FACET_MININCLUSIVE:
                return ("minInclusive");
    	case XML_SCHEMA_FACET_WHITESPACE:
                return ("whiteSpace");
    	case XML_SCHEMA_FACET_ENUMERATION:
                return ("enumeration");
    	case XML_SCHEMA_FACET_LENGTH:
                return ("length");
    	case XML_SCHEMA_FACET_MAXLENGTH:
                return ("maxLength");
    	case XML_SCHEMA_FACET_MINLENGTH:
                return ("minLength");
    	case XML_SCHEMA_FACET_TOTALDIGITS:
                return ("totalDigits");
    	case XML_SCHEMA_FACET_FRACTIONDIGITS:
                return ("fractionDigits");
            default:
                break;
        }
        return ("Internal Error");
    }
    
    /**
     * xmlSchemaValidateFacets:
     * @ctxt:  a schema validation context
     * @base:  the base type
     * @facets:  the list of facets to check
     * @value:  the lexical repr of the value to validate
     * @val:  the precomputed value
     *
     * Check a value against all facet conditions
     *
     * 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
    xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt, 
    			     xmlSchemaTypePtr base,
    	                    xmlSchemaFacetPtr facets,
    	                             xmlChar *value) {
        int ret = 0;
        int tmp = 0;
        xmlSchemaTypeType type;
        xmlSchemaFacetPtr facet = facets;
    
        while (facet != NULL) {
            type = facet->type;
            if (type == XML_SCHEMA_FACET_ENUMERATION) {
    	    tmp = 1;
    
    	    while (facet != NULL) {
    		tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
    		if (tmp == 0) {
                        return 0;
    		}
    		facet = facet->next;
    	    }
            } else
    	    tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
    
            if (tmp != 0) {
                ret = tmp;
    	    ctxt->nberrors++;
                if (ctxt->error != NULL)
    	        ctxt->error(ctxt->userData,
    	             "Failed to validate type with facet %s\n",
                         xmlSchemaFacetTypeToString(type));
    	    ctxt->err = XML_SCHEMAS_ERR_FACET;
            }
            if (facet != NULL)
                facet = facet->next;
        }
        return (ret);
    }
    
    /************************************************************************
     * 									*
     * 			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 = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
    	                                 ctxt->cur);
            if (ret != 0) {
    	    ctxt->nberrors++;
                if (ctxt->error != NULL)
    	        ctxt->error(ctxt->userData,
    		        "Failed to validate basic type %s\n", type->name);
    	    ctxt->err = XML_SCHEMAS_ERR_VALUE;
            }
        } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
    	xmlSchemaTypePtr base;
    	xmlSchemaFacetPtr facet;
    
    	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;
                    ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
    	    }
    	}
        } 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;
    	    ctxt->nberrors++;
    	    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 ((attrs->ns != NULL) &&
    	    (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
    	    attrs = attrs->next;
    	    continue;
    	}
    	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;
    	    ctxt->nberrors++;
    	    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,
    	                       xmlNodePtr node ATTRIBUTE_UNUSED) {
        xmlNodePtr child;
        xmlSchemaTypePtr type, base;
        xmlChar *value;
        int ret = 0;
    
        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;
                    ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
    	    }
    	    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(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
    	             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,
    	                  const xmlChar *name ATTRIBUTE_UNUSED,
    			  xmlSchemaTypePtr type,
    			  xmlNodePtr node) {
        xmlSchemaTypePtr oldtype = ctxt->type;
        xmlNodePtr oldnode = ctxt->node;
    #ifdef DEBUG_CONTENT
        xmlGenericError(xmlGenericErrorContext,
                        "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->nberrors++;
            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->nberrors++;
            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->nberrors++;
            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->nberrors++;
    	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->nberrors++;
    	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->nberrors++;
    	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;
    	    ctxt->nberrors++;
    	    if (ctxt->error != NULL)
    		ctxt->error(ctxt->userData,
    			"Element %s: attribute %s should not be present\n",
    			    node->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->nberrors++;
    	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->nberrors++;
    	    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->nberrors++;
    	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) {
    	    ctxt->nberrors++;
    	    ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
    	    if (ctxt->error != NULL)
    		ctxt->error(ctxt->userData, "Element %s content check failed\n",
    			    node->name);
    	} else if (ret < 0) {
    	    ctxt->nberrors++;
    	    ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
    	    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->nberrors++;
    	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->nberrors++;
    		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->nberrors++;
    		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->nberrors++;
            if (ctxt->error != NULL)
    	    ctxt->error(ctxt->userData,
    		    "Element %s: failed to validate basic type %s\n",
    		        node->name, type->name);
    	ctxt->err = XML_SCHEMAS_ERR_VALUE;
        }
        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;
        int ret;
    
        child = ctxt->node;
        type = ctxt->type;
        ctxt->cur = node;
    
        switch (type->contentType) {
    	case XML_SCHEMA_CONTENT_EMPTY:
    	    if (child != NULL) {
    		ctxt->nberrors++;
    		if (ctxt->error != NULL)
    		    ctxt->error(ctxt->userData,
    			    "Element %s is supposed to be empty\n",
    			        node->name);
    	    }
    	    if (type->attributes != NULL) {
    		xmlSchemaValidateAttributes(ctxt, node, type->attributes);
    	    }
    	    subtype = type->subtypes;
    	    while (subtype != NULL) {
    		ctxt->type = subtype;
    		xmlSchemaValidateComplexType(ctxt, node);
    		subtype = subtype->next;
    	    }
    	    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);
    	    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;
    	case XML_SCHEMA_CONTENT_BASIC: {
    	    if (type->subtypes != NULL) {
    		ctxt->type = type->subtypes;
    		xmlSchemaValidateComplexType(ctxt, node);
    	    }
    	    if (type->baseType != NULL) {
    		ctxt->type = type->baseType;
    		xmlSchemaValidateBasicType(ctxt, node);
    	    }
    	    if (type->attributes != NULL) {
    		xmlSchemaValidateAttributes(ctxt, node, type->attributes);
    	    }
    	    ctxt->type = type;
    	    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;
        ctxt->cur = node;
    
        xmlSchemaValidateAttributes(ctxt, node, type->attributes);
        ctxt->cur = node;
    
        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->nberrors++;
    		    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;
    	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
    	    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 == NULL) || (type == NULL) || (elemDecl == NULL))
    	return(0);
    
        /*
         * 3.3.4 : 2
         */
        if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
            ctxt->nberrors++;
    	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->nberrors++;
    		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->nberrors++;
    		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;
    	    ctxt->nberrors++;
    	    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;
        xmlSchemaAttributeGroupPtr group = NULL;
    
        if (attributes == NULL)
    	return(0);
        while (attributes != NULL) {
    	/*
    	 * Handle attribute groups
    	 */
    	if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
    	    group = (xmlSchemaAttributeGroupPtr) attributes;
    	    xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
    	    attributes = group->next;
    	    continue;
    	}
    	for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
    	    attr = ctxt->attr[i].attr;
    	    if (attr == NULL)
    		continue;
    	    if (attributes->ref != NULL) {
    		if (!xmlStrEqual(attr->name, attributes->ref))
    		    continue;
    		if (attr->ns != NULL) {
    		    if ((attributes->refNs == NULL) ||
    		        (!xmlStrEqual(attr->ns->href, attributes->refNs)))
    			continue;
    		} else if (attributes->refNs != NULL) {
    		    continue;
    		}
    	    } else {
    		if (!xmlStrEqual(attr->name, attributes->name))
    		    continue;
    		/*
    		 * TODO: handle the mess about namespaces here.
    		 */
    		if ((attr->ns != NULL) /* || (attributes->ns != NULL) */) {
    		    TODO
    		}
    	    }
    	    ctxt->cur = (xmlNodePtr) attributes;
    	    if (attributes->subtypes == NULL) {
    	        ctxt->nberrors++;
    		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->nberrors++;
    		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->nberrors++;
    	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->nberrors++;
    	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);
        if (elemDecl->contModel != NULL) {
    	ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
    #ifdef DEBUG_AUTOMATA
    	xmlGenericError(xmlGenericErrorContext,
    		"====> %s : %d\n", elem->name, ret);
    #endif
    	if (ret == 0) {
    	    ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
    	    ctxt->nberrors++;
    	    if (ctxt->error != NULL)
    		ctxt->error(ctxt->userData, "Element %s content check failed\n",
    			    elem->name);
    	} else if (ret < 0) {
    	    ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
    	    ctxt->nberrors++;
    	    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
    	}
    	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;
    	ctxt->nberrors++;
            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;
    	ctxt->nberrors++;
            if (ctxt->error != NULL)
                ctxt->error(ctxt->userData, "Element %s not declared\n",
                            root->name);
        } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
    	ctxt->err = XML_SCHEMAS_ERR_NOTTOPLEVEL;
    	ctxt->nberrors++;
            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);
        if (ctxt->value != NULL)
    	xmlSchemaFreeValue(ctxt->value);
        xmlFree(ctxt);
    }
    
    /**
     * xmlSchemaSetValidErrors:
     * @ctxt:  a schema validation context
     * @err:  the error function
     * @warn: the warning function
     * @ctx: 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 */