Edit

kc3-lang/libxml2/xmlschemas.c

Branch :

  • Show log

    Commit

  • Author : Kasimier T. Buchcik
    Date : 2005-02-18 11:37:58
    Hash : ff858ca8
    Message : Started support for IDC resolution to default attributes. If building the * xmlschemas.c: Started support for IDC resolution to default attributes. If building the content model for <all>: ensured to put element declarations and not the particles into the content model automaton (this was bug #167754, reported by Frans Englich).

  • 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>
     */
    
    /* 
     * TODO:
     *   - when types are redefined in includes, check that all
     *     types in the redef list are equal
     *     -> need a type equality operation.
     *   - if we don't intend to use the schema for schemas, we 
     *     need to validate all schema attributes (ref, type, name)
     *     against their types.
     */
    #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>
    #include <libxml/dict.h>
    #ifdef LIBXML_PATTERN_ENABLED
    #include <libxml/pattern.h>
    #endif
    
    /* #define DEBUG 1 */
    
    /* #define DEBUG_CONTENT 1 */
    
    /* #define DEBUG_TYPE 1 */
    
    /* #define DEBUG_CONTENT_REGEXP 1 */
    
    /* #define DEBUG_AUTOMATA 1 */
    
    /* #define DEBUG_ATTR_VALIDATION 1 */
    
    /* #define DEBUG_UNION_VALIDATION 1 */
    
    #define ELEM_INFO_ENABLED 1 
    
    /* #define IDC_ENABLED 1 */
    
    /* #define IDC_VALUE_SUPPORT 1 */
    
    /* #define IDC_XPATH_SUPPORT 1 */
    
    /* #define DEBUG_IDC 1 */
    
    
    #define UNBOUNDED (1 << 30)
    #define TODO 								\
        xmlGenericError(xmlGenericErrorContext,				\
    	    "Unimplemented block at %s:%d\n",				\
                __FILE__, __LINE__);
    
    #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
    
    /*
     * 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";
    
    static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
        "Element decl.";
    static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
        "Element ref.";
    static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
        "Attribute decl.";
    static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
        "Attribute ref.";
    static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
        "simple type";
    static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
        "complex type";
    static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
        "Model group";
    static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
        "Model group ref.";
    
    #define IS_SCHEMA(node, type)						\
       ((node != NULL) && (node->ns != NULL) &&				\
        (xmlStrEqual(node->name, (const xmlChar *) type)) &&		\
        (xmlStrEqual(node->ns->href, xmlSchemaNs)))
    
    #define FREE_AND_NULL(str)						\
        if (str != NULL) {							\
    	xmlFree(str);							\
    	str = NULL;							\
        }
    
    #define IS_ANYTYPE(item)                           \
        ((item->type == XML_SCHEMA_TYPE_BASIC) &&      \
         (item->builtInType == XML_SCHEMAS_ANYTYPE))   
    
    #define IS_COMPLEX_TYPE(item)                      \
        ((item->type == XML_SCHEMA_TYPE_COMPLEX) ||    \
         (item->builtInType == XML_SCHEMAS_ANYTYPE))
    
    #define IS_SIMPLE_TYPE(item)                       \
        ((item->type == XML_SCHEMA_TYPE_SIMPLE) ||     \
         ((item->type == XML_SCHEMA_TYPE_BASIC) &&     \
          (item->builtInType != XML_SCHEMAS_ANYTYPE))) 
    
    /*
    #define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
    #define XML_SCHEMAS_VAL_WTSP_REPLACE  1
    #define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
    */
    
    #define XML_SCHEMAS_PARSE_ERROR		1
    
    #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
    
    
    /*
    * XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
    * locate schemata to be imported
    * using the namespace name; otherwise
    * the location URI will be used */
    
    /*
    * xmlSchemaParserOption:
    *
    * This is the set of XML Schema parser options.
    *
    typedef enum {
        XML_SCHEMA_PAR_LOCATE_BY_NSNAME	= 1<<0
    	* locate schemata to be imported
    	* using the namespace name; otherwise
    	* the location URI will be used *
    } xmlSchemaParserOption;
    */
    
    typedef struct _xmlSchemaAssemble xmlSchemaAssemble;
    typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
    struct _xmlSchemaAssemble {
        void **items;  /* used for dynamic addition of schemata */
        int nbItems; /* used for dynamic addition of schemata */
        int sizeItems; /* used for dynamic addition of schemata */
    };
    
    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;
        xmlStructuredErrorFunc serror;
    
        xmlSchemaPtr topschema;	/* The main schema */
        xmlHashTablePtr namespaces;	/* Hash table of namespaces to schemas */
    
        xmlSchemaPtr schema;        /* The schema in use */
        const xmlChar *container;   /* the current element, group, ... */
        int counter;
    
        const xmlChar *URL;
        xmlDocPtr doc;
        int preserve;		/* Whether the doc should be freed  */
    
        const char *buffer;
        int size;
    
        /*
         * Used to build complex element content models
         */
        xmlAutomataPtr am;
        xmlAutomataStatePtr start;
        xmlAutomataStatePtr end;
        xmlAutomataStatePtr state;
    
        xmlDictPtr dict;		/* dictionnary for interned string names */
        int        includes;	/* the inclusion level, 0 for root or imports */
        xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
        xmlSchemaTypePtr parentItem; /* The current parent schema item */
        xmlSchemaAssemblePtr assemble;
        int options;
        xmlSchemaValidCtxtPtr vctxt;
    };
    
    
    #define XML_SCHEMAS_ATTR_UNKNOWN 1
    #define XML_SCHEMAS_ATTR_CHECKED 2
    #define XML_SCHEMAS_ATTR_PROHIBITED 3
    #define XML_SCHEMAS_ATTR_MISSING 4
    #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
    #define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
    #define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
    #define XML_SCHEMAS_ATTR_DEFAULT 8
    #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
    #define XML_SCHEMAS_ATTR_WILD_NO_DECL 10
    
    typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
    typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
    struct _xmlSchemaAttrState {
        xmlSchemaAttrStatePtr next;
        xmlAttrPtr attr;
        int state;
        xmlSchemaAttributePtr decl;
        const xmlChar *value;
    };
    
    typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
    typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
    struct _xmlSchemaBasicItem {
        xmlSchemaTypeType type;
        xmlSchemaAnnotPtr annot;
    };
    
    typedef struct _xmlSchemaItemQNRef xmlSchemaItemQNRef;
    typedef xmlSchemaItemQNRef *xmlSchemaItemQNRefPtr;
    struct _xmlSchemaItemQNRef {
        xmlSchemaBasicItemPtr item;
        const xmlChar *name;
        const xmlChar *targetNamespace;
    };
    
    typedef struct _xmlSchemaIDC xmlSchemaIDC;
    typedef xmlSchemaIDC *xmlSchemaIDCPtr;
    
    /**
     * xmlSchemaIDCSelect:
     *
     * The identity-constraint "field" and "selector" item, holding the
     * XPath expression.
     */
    typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
    typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
    struct _xmlSchemaIDCSelect {    
        xmlSchemaIDCSelectPtr next;
        xmlSchemaIDCPtr idc;
        int index; /* an index position if significant for IDC key-sequences */
        const xmlChar *xpath; /* the XPath expression */
        void *xpathComp; /* the compiled XPath expression */
    };
    
    /**
     * xmlSchemaIDC:
     *
     * The identity-constraint definition component.
     */
    
    struct _xmlSchemaIDC {
        xmlSchemaTypeType type;
        xmlSchemaAnnotPtr annot;
        xmlSchemaIDCPtr next;
        xmlNodePtr node;
        const xmlChar *name;    
        const xmlChar *targetNamespace;
        xmlSchemaIDCSelectPtr selector;
        xmlSchemaIDCSelectPtr fields;
        int nbFields;
        xmlSchemaItemQNRefPtr ref;
    };
    
    /**
     * xmlSchemaIDCAug:
     *
     * The augmented IDC information used for validation.
     */
    typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
    typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
    struct _xmlSchemaIDCAug {
        xmlSchemaIDCAugPtr next; /* next in a list */
        xmlSchemaIDCPtr def; /* the IDC definition */
        int bubbleDepth; /* the lowest level to which IDC 
                            tables need to be bubbled upwards */
    };
    
    /**
     * xmlSchemaPSVIIDCKeySequence:
     *
     * The key sequence of a node table item.
     */
    typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
    typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
    struct _xmlSchemaPSVIIDCKey {
        xmlSchemaTypePtr type;
        xmlSchemaValPtr compValue;
    };
    
    /**
     * xmlSchemaPSVIIDCNode:
     *
     * The node table item of a node table.
     */
    typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
    typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
    struct _xmlSchemaPSVIIDCNode {
        xmlNodePtr node;
        xmlSchemaPSVIIDCKeyPtr *keys;
    };
    
    /**
     * xmlSchemaPSVIIDCBinding:
     *
     * The identity-constraint binding item of the [identity-constraint table].
     */
    typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
    typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
    struct _xmlSchemaPSVIIDCBinding {
        xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
        xmlSchemaIDCPtr definition; /* the IDC definition */
        xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
        int nbNodes; /* number of entries in the node table */
        int sizeNodes; /* size of the node table */
        int nbDupls; /* number of already identified duplicates in the node 
                        table */
        /* int nbKeys; number of keys in each key-sequence */
    };
    
    #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
    #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
    
    #define XPATH_STATE_OBJ_MATCHES -2
    #define XPATH_STATE_OBJ_BLOCKED -3
    
    typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
    typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
    
    /**
     * xmlSchemaIDCStateObj:
     *
     * The state object used to evaluate XPath expressions.
     */
    typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
    typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
    struct _xmlSchemaIDCStateObj {
        int type;    
        xmlSchemaIDCStateObjPtr next; /* next if in a list */
        int depth; /* depth of creation */
        int *history; /* list of (depth, state-id) tuples */
        int nbHistory;
        int sizeHistory;
        xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
                                           matcher */
        xmlSchemaIDCSelectPtr sel;
        void *xpathCtxt;
    };
    
    #define IDC_MATCHER 0
    
    /**
     * xmlSchemaIDCMatcher:
     *
     * Used to  IDC selectors (and fields) successively.
     */
    struct _xmlSchemaIDCMatcher {
        int type;
        int depth; /* the tree depth at creation time */
        xmlSchemaIDCMatcherPtr next; /* next in the list */
        xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
        xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
                                             elements */
        int sizeKeySeqs;
        int targetDepth;
    };
    
    /*
    * Element info flags.
    */
    #define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1<<0
    
    /**
     * xmlSchemaElemInfo:
     *
     * Holds information of an element node.
     */
    typedef struct _xmlSchemaElemInfo xmlSchemaElemInfo;
    typedef xmlSchemaElemInfo *xmlSchemaElemInfoPtr;
    struct _xmlSchemaElemInfo {
        int depth;
        int flags; /* combination of element info flags */
        xmlNodePtr node;
        const xmlChar *localName;
        const xmlChar *namespaceName;
        xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
        xmlSchemaTypePtr decl; /* the element/attribute declaration */
        xmlSchemaValPtr value; /* the pre-computed value if any */
        xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
                                                for the scope element*/
        xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
                                               element */
    };
    
    /**
     * 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 */
        xmlStructuredErrorFunc serror;
    
        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;
    
        xmlSchemaAttrStatePtr attrTop;
        xmlSchemaAttrStatePtr attr;
        /* xmlNodePtr scope; not used */
        int valueWS;
        int options;
        xmlNodePtr validationRoot;    
        xmlSchemaParserCtxtPtr pctxt;
        int xsiAssemble;
    #ifdef ELEM_INFO_ENABLED
        int depth;
        xmlSchemaElemInfoPtr *elemInfos; /* array of element informations */
        int sizeElemInfos;
        xmlSchemaElemInfoPtr nodeInfo; /* the current element information */
        xmlSchemaElemInfoPtr attrInfo; /* node infor for the current attribute */
    #endif
    #ifdef IDC_ENABLED
        xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
    
        xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
        xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
        
        xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
        int nbIdcNodes;
        int sizeIdcNodes;
    
        xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
        int nbIdcKeys;
        int sizeIdcKeys;
    #endif
    };
    
    /*
     * These are the entries in the schemas importSchemas hash table
     */
    typedef struct _xmlSchemaImport xmlSchemaImport;
    typedef xmlSchemaImport *xmlSchemaImportPtr;
    struct _xmlSchemaImport {
        const xmlChar *schemaLocation;
        xmlSchemaPtr schema; /* not used any more */
        xmlDocPtr doc;
        int isMain;
    };
    
    /*
     * These are the entries associated to includes in a schemas
     */
    typedef struct _xmlSchemaInclude xmlSchemaInclude;
    typedef xmlSchemaInclude *xmlSchemaIncludePtr;
    struct _xmlSchemaInclude {
        xmlSchemaIncludePtr next;
        const xmlChar *schemaLocation;
        xmlDocPtr doc;
    };
    
    typedef struct _xmlSchemaParticle xmlSchemaParticle;
    typedef xmlSchemaParticle *xmlSchemaParticlePtr;
    struct _xmlSchemaParticle {
        xmlSchemaTypeType type;
        xmlSchemaParticlePtr next; /* the next particle if in a list */
        int minOccurs;
        int maxOccurs;
        xmlSchemaTypePtr term;
    };
    
    
    typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
    typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
    struct _xmlSchemaModelGroup {
        xmlSchemaTypeType type;
        int compositor; /* one of all, choice or sequence */
        xmlSchemaParticlePtr particles; /* list of particles */
        xmlSchemaAnnotPtr annot;
    };
    
    typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
    typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
    struct _xmlSchemaModelGroupDef {
        xmlSchemaTypeType type;
        const xmlChar *name;
        const xmlChar *targetNamespace;
        xmlSchemaModelGroupPtr modelGroup;
        xmlSchemaAnnotPtr annot;
    };
    
    /************************************************************************
     * 									*
     * 			Some predeclarations				*
     * 									*
     ************************************************************************/
    
    static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
                                     xmlSchemaPtr schema,
                                     xmlNodePtr node);
    static void
    xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
                       xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
    static const xmlChar *
    xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
    static int
    xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt, 
    				 xmlSchemaTypePtr type,
    				 const xmlChar *value,
    				 int fireErrors,
    				 int applyFacets,
    				 int normalize,
    				 int checkNodes);
    static int
    xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
    				      xmlSchemaElementPtr elemDecl); 
    static int
    xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
    				   xmlSchemaTypePtr type);
    static int
    xmlSchemaHasElemOrCharContent(xmlNodePtr node);
    static int
    xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
                         xmlNodePtr node);
    static void
    xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
                           xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
    
    /************************************************************************
     *									*
     * 			Datatype error handlers				*
     *									*
     ************************************************************************/
    
    /**
     * xmlSchemaPErrMemory:
     * @node: a context node
     * @extra:  extra informations
     *
     * Handle an out of memory condition
     */
    static void
    xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
                        const char *extra, xmlNodePtr node)
    {
        if (ctxt != NULL)
            ctxt->nberrors++;
        __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
                         extra);
    }
    
    /**
     * xmlSchemaPErr:
     * @ctxt: the parsing context
     * @node: the context node
     * @error: the error code
     * @msg: the error message
     * @str1: extra data
     * @str2: extra data
     * 
     * Handle a parser error
     */
    static void
    xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
                  const char *msg, const xmlChar * str1, const xmlChar * str2)
    {
        xmlGenericErrorFunc channel = NULL;
        xmlStructuredErrorFunc schannel = NULL;
        void *data = NULL;
    
        if (ctxt != NULL) {
            ctxt->nberrors++;
            channel = ctxt->error;
            data = ctxt->userData;
    	schannel = ctxt->serror;
        }
        __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
                        error, XML_ERR_ERROR, NULL, 0,
                        (const char *) str1, (const char *) str2, NULL, 0, 0,
                        msg, str1, str2);
    }
    
    /**
     * xmlSchemaPErr2:
     * @ctxt: the parsing context
     * @node: the context node
     * @node: the current child
     * @error: the error code
     * @msg: the error message
     * @str1: extra data
     * @str2: extra data
     * 
     * Handle a parser error
     */
    static void
    xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
                   xmlNodePtr child, int error,
                   const char *msg, const xmlChar * str1, const xmlChar * str2)
    {
        if (child != NULL)
            xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
        else
            xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
    }
    
    
    /**
     * xmlSchemaPErrExt:
     * @ctxt: the parsing context
     * @node: the context node
     * @error: the error code 
     * @strData1: extra data
     * @strData2: extra data
     * @strData3: extra data
     * @msg: the message
     * @str1:  extra parameter for the message display
     * @str2:  extra parameter for the message display
     * @str3:  extra parameter for the message display
     * @str4:  extra parameter for the message display
     * @str5:  extra parameter for the message display
     * 
     * Handle a parser error
     */
    static void
    xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
    		const xmlChar * strData1, const xmlChar * strData2, 
    		const xmlChar * strData3, const char *msg, const xmlChar * str1, 
    		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
    		const xmlChar * str5)
    {
    
        xmlGenericErrorFunc channel = NULL;
        xmlStructuredErrorFunc schannel = NULL;
        void *data = NULL;
    
        if (ctxt != NULL) {
            ctxt->nberrors++;
            channel = ctxt->error;
            data = ctxt->userData;
    	schannel = ctxt->serror;
        }
        __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
                        error, XML_ERR_ERROR, NULL, 0,
                        (const char *) strData1, (const char *) strData2, 
    		    (const char *) strData3, 0, 0, msg, str1, str2, 
    		    str3, str4, str5);
    }
    
    
    /**
     * xmlSchemaVTypeErrMemory:
     * @node: a context node
     * @extra:  extra informations
     *
     * Handle an out of memory condition
     */
    static void
    xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
                        const char *extra, xmlNodePtr node)
    {
        if (ctxt != NULL) {
            ctxt->nberrors++;
            ctxt->err = XML_SCHEMAV_INTERNAL;
        }
        __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
                         extra);
    }
    
    /**
     * xmlSchemaVErr3:
     * @ctxt: the validation context
     * @node: the context node
     * @error: the error code
     * @msg: the error message
     * @str1: extra data
     * @str2: extra data
     * @str3: extra data
     * 
     * Handle a validation error
     */
    static void
    xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
                   const char *msg, const xmlChar *str1, const xmlChar *str2,
    	       const xmlChar *str3)
    {
        xmlStructuredErrorFunc schannel = NULL;
        xmlGenericErrorFunc channel = NULL;
        void *data = NULL;
    
        if (ctxt != NULL) {
            ctxt->nberrors++;
    	ctxt->err = error;
            channel = ctxt->error;
            schannel = ctxt->serror;
            data = ctxt->userData;
        }
        /* reajust to global error numbers */
        /* Removed, since the old schema error codes have been 
        * substituted for the global error codes.
        *
        * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT; 
        */
        __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
                        error, XML_ERR_ERROR, NULL, 0,
                        (const char *) str1, (const char *) str2,
    		    (const char *) str3, 0, 0,
                        msg, str1, str2, str3);
    }
    
    /**
     * xmlSchemaVErrExt:
     * @ctxt: the validation context
     * @node: the context node
     * @error: the error code 
     * @msg: the message
     * @str1:  extra parameter for the message display
     * @str2:  extra parameter for the message display
     * @str3:  extra parameter for the message display
     * @str4:  extra parameter for the message display
     * @str5:  extra parameter for the message display
     * 
     * Handle a validation error
     */
    static void
    xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
    		 const char *msg, const xmlChar * str1, 
    		 const xmlChar * str2, const xmlChar * str3, 
    		 const xmlChar * str4, const xmlChar * str5)
    {
        xmlStructuredErrorFunc schannel = NULL;
        xmlGenericErrorFunc channel = NULL;
        void *data = NULL;
    
        if (ctxt != NULL) {
            ctxt->nberrors++;
    	ctxt->err = error;
            channel = ctxt->error;
            schannel = ctxt->serror;
            data = ctxt->userData;
        }
        /* reajust to global error numbers */
         /* Removed, since the old schema error codes have been 
        * substituted for the global error codes.
        *
        * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
        */
        __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
                        error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0, 
    		    msg, str1, str2, str3, str4, str5);
    }
    /**
     * xmlSchemaVErr:
     * @ctxt: the validation context
     * @node: the context node
     * @error: the error code
     * @msg: the error message
     * @str1: extra data
     * @str2: extra data
     * 
     * Handle a validation error
     */
    static void
    xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
                  const char *msg, const xmlChar * str1, const xmlChar * str2)
    {
        xmlStructuredErrorFunc schannel = NULL;
        xmlGenericErrorFunc channel = NULL;
        void *data = NULL;
    
        if (ctxt != NULL) {
            ctxt->nberrors++;
    	ctxt->err = error;
            channel = ctxt->error;
            data = ctxt->userData;
            schannel = ctxt->serror;
        }
        /* reajust to global error numbers */
        /* Removed, since the old schema error codes have been 
        * substituted for the global error codes.
        *
        * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
        */
        __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
                        error, XML_ERR_ERROR, NULL, 0,
                        (const char *) str1, (const char *) str2, NULL, 0, 0,
                        msg, str1, str2);
    }
    
    /**
     * xmlSchemaGetAttrName:
     * @attr:  the attribute declaration/use
     *
     * Returns the name of the attribute; if the attribute
     * is a reference, the name of the referenced global type will be returned.
     */
    static const xmlChar *
    xmlSchemaGetAttrName(xmlSchemaAttributePtr attr) 
    {
        if (attr->ref != NULL) 
    	return(attr->ref);
        else
    	return(attr->name);	
    }
    
    /**
     * xmlSchemaGetAttrTargetNsURI:
     * @type:  the type (element or attribute)
     *
     * Returns the target namespace URI of the type; if the type is a reference,
     * the target namespace of the referenced type will be returned.
     */
    static const xmlChar *
    xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
    {  
        if (attr->ref != NULL)
    	return (attr->refNs);
        else
    	return(attr->targetNamespace);  
    }
    
    /**
     * xmlSchemaFormatNsUriLocal:
     * @buf: the string buffer
     * @uri:  the namespace URI
     * @local: the local name
     *
     * Returns a representation of the given URI used
     * for error reports.
     *
     * Returns an empty string, if @ns is NULL, a formatted
     * string otherwise.
     */  
    static const xmlChar*   
    xmlSchemaFormatNsUriLocal(xmlChar **buf,
    			   const xmlChar *uri, const xmlChar *local)
    {
        if (*buf != NULL)
    	xmlFree(*buf);
        if (uri == NULL) {
    	*buf = xmlStrdup(BAD_CAST "{'");
    	*buf = xmlStrcat(*buf, local);
        } else {
    	*buf = xmlStrdup(BAD_CAST "{'");
    	*buf = xmlStrcat(*buf, uri);
    	*buf = xmlStrcat(*buf, BAD_CAST "', '");
    	*buf = xmlStrcat(*buf, local);	
        }
        *buf = xmlStrcat(*buf, BAD_CAST "'}");
        return ((const xmlChar *) *buf);
    }
    
    /**
     * xmlSchemaFormatNsPrefixLocal:
     * @buf: the string buffer
     * @ns:  the namespace
     * @local: the local name
     *
     * Returns a representation of the given URI used
     * for error reports.
     *
     * Returns an empty string, if @ns is NULL, a formatted
     * string otherwise.
     */  
    static const xmlChar*   
    xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
    			      xmlNsPtr ns, const xmlChar *local)
    {
        if (*buf != NULL) {
    	xmlFree(*buf);
    	*buf = NULL;
        }
        if ((ns == NULL) || (ns->prefix == NULL))
    	return(local);
        else {
    	*buf = xmlStrdup(ns->prefix);
    	*buf = xmlStrcat(*buf, BAD_CAST ":");
    	*buf = xmlStrcat(*buf, local);
        }
        return ((const xmlChar *) *buf);
    }
    
    /**
     * xmlSchemaWildcardPCToString:
     * @pc: the type of processContents
     *
     * Returns a string representation of the type of 
     * processContents.
     */
    static const xmlChar *
    xmlSchemaWildcardPCToString(int pc)
    {
        switch (pc) {
    	case XML_SCHEMAS_ANY_SKIP:
    	    return (BAD_CAST "skip");
    	case XML_SCHEMAS_ANY_LAX:
    	    return (BAD_CAST "lax");
    	case XML_SCHEMAS_ANY_STRICT:
    	    return (BAD_CAST "strict");
    	default:
    	    return (BAD_CAST "invalid process contents");
        }
    }
    
    /**
     * xmlSchemaFormatItemForReport:
     * @buf: the string buffer
     * @itemDes: the designation of the item
     * @itemName: the name of the item
     * @item: the item as an object 
     * @itemNode: the node of the item
     * @local: the local name
     * @parsing: if the function is used during the parse
     *
     * Returns a representation of the given item used
     * for error reports. 
     *
     * The following order is used to build the resulting 
     * designation if the arguments are not NULL:
     * 1a. If itemDes not NULL -> itemDes
     * 1b. If (itemDes not NULL) and (itemName not NULL)
     *     -> itemDes + itemName
     * 2. If the preceding was NULL and (item not NULL) -> item
     * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
     * 
     * If the itemNode is an attribute node, the name of the attribute
     * will be appended to the result.
     *
     * Returns the formatted string and sets @buf to the resulting value.
     */  
    static xmlChar*   
    xmlSchemaFormatItemForReport(xmlChar **buf,		     
    		     const xmlChar *itemDes,
    		     xmlSchemaTypePtr item,
    		     xmlNodePtr itemNode,
    		     int parsing)
    {
        xmlChar *str = NULL;
        int named = 1;
    
        if (*buf != NULL) {
    	xmlFree(*buf);
    	*buf = NULL;
        }
                
        if (itemDes != NULL) {
    	*buf = xmlStrdup(itemDes);	
        } else if (item != NULL) {
    	switch (item->type) {
    	case XML_SCHEMA_TYPE_BASIC:
    	    if (item->builtInType == XML_SCHEMAS_ANYTYPE)
    		*buf = xmlStrdup(BAD_CAST "'anyType'");
    	    else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
    		*buf = xmlStrdup(BAD_CAST "'anySimpleType'");
    	    else {
    		/* *buf = xmlStrdup(BAD_CAST "bi "); */
    		/* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
    		*buf = xmlStrdup(BAD_CAST "'");
    		*buf = xmlStrcat(*buf, item->name);
    		*buf = xmlStrcat(*buf, BAD_CAST "'");
    	    }
    	    break;
    	case XML_SCHEMA_TYPE_SIMPLE:
    	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
    		*buf = xmlStrdup(xmlSchemaElemDesST);
    		*buf = xmlStrcat(*buf, BAD_CAST " '");
    		*buf = xmlStrcat(*buf, item->name);
    		*buf = xmlStrcat(*buf, BAD_CAST "'");
    	    } else {
    		*buf = xmlStrdup(xmlSchemaElemDesST);
    	    }
    	    break;
    	case XML_SCHEMA_TYPE_COMPLEX:
    	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
    		*buf = xmlStrdup(xmlSchemaElemDesCT);
    		*buf = xmlStrcat(*buf, BAD_CAST " '");
    		*buf = xmlStrcat(*buf, item->name);
    		*buf = xmlStrcat(*buf, BAD_CAST "'");
    	    } else {
    		*buf = xmlStrdup(xmlSchemaElemDesCT);
    	    }
    	    break;
    	case XML_SCHEMA_TYPE_ATTRIBUTE: {
    		xmlSchemaAttributePtr attr;
    	    
    		attr = (xmlSchemaAttributePtr) item;	    
    		if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
    		    (attr->ref == NULL)) {
    		    *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
    		    *buf = xmlStrcat(*buf, BAD_CAST " '");
    		    *buf = xmlStrcat(*buf, attr->name);
    		    *buf = xmlStrcat(*buf, BAD_CAST "'");
    		} else {
    		    *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
    		    *buf = xmlStrcat(*buf, BAD_CAST " '");
    		    *buf = xmlStrcat(*buf, attr->refPrefix);
    		    *buf = xmlStrcat(*buf, BAD_CAST ":");
    		    *buf = xmlStrcat(*buf, attr->ref);
    		    *buf = xmlStrcat(*buf, BAD_CAST "'");
    		}	
    	    }
    	    break;
    	case XML_SCHEMA_TYPE_ELEMENT: {
    		xmlSchemaElementPtr elem;
    
    		elem = (xmlSchemaElementPtr) item;	    
    		if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) || 
    		    (elem->ref == NULL)) {
    		    *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
    		    *buf = xmlStrcat(*buf, BAD_CAST " '");
    		    *buf = xmlStrcat(*buf, elem->name);
    		    *buf = xmlStrcat(*buf, BAD_CAST "'");
    		} else {
    		    *buf = xmlStrdup(xmlSchemaElemDesElemRef);
    		    *buf = xmlStrcat(*buf, BAD_CAST " '");
    		    *buf = xmlStrcat(*buf, elem->refPrefix);
    		    *buf = xmlStrcat(*buf, BAD_CAST ":");
    		    *buf = xmlStrcat(*buf, elem->ref);
    		    *buf = xmlStrcat(*buf, BAD_CAST "'");
    		}
    	    }
    	    break;
    	case XML_SCHEMA_TYPE_IDC_UNIQUE:
    	case XML_SCHEMA_TYPE_IDC_KEY:
    	case XML_SCHEMA_TYPE_IDC_KEYREF:		
    	    if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
    		*buf = xmlStrdup(BAD_CAST "unique '");
    	    else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
    		*buf = xmlStrdup(BAD_CAST "key '");
    	    else
    		*buf = xmlStrdup(BAD_CAST "keyRef '");
    	    *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
    	    *buf = xmlStrcat(*buf, BAD_CAST "'");
    	    break;
    	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
    	    *buf = xmlStrdup(xmlSchemaWildcardPCToString(
    		    ((xmlSchemaWildcardPtr) item)->processContents));
    	    *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
    	    break;
    	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:
    	    *buf = xmlStrdup(BAD_CAST "facet '");
    	    *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
    	    *buf = xmlStrcat(*buf, BAD_CAST "'");
    	    break;
    	case XML_SCHEMA_TYPE_NOTATION:
    	    *buf = xmlStrdup(BAD_CAST "notation");
    	    break;
    	case XML_SCHEMA_TYPE_GROUP:
    	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
    		*buf = xmlStrdup(xmlSchemaElemModelGrDef);
    		*buf = xmlStrcat(*buf, BAD_CAST " '");
    		*buf = xmlStrcat(*buf, item->name);
    		*buf = xmlStrcat(*buf, BAD_CAST "'");
    	    } else {
    		*buf = xmlStrdup(xmlSchemaElemModelGrRef);
    		*buf = xmlStrcat(*buf, BAD_CAST " '");
    		*buf = xmlStrcat(*buf, item->ref);
    		*buf = xmlStrcat(*buf, BAD_CAST "'");
    	    }
    	    break;
    	default:
    	    named = 0;
    	}
        } else 
    	named = 0;
    
        if ((named == 0) && (itemNode != NULL)) {
    	xmlNodePtr elem;
    
    	if (itemNode->type == XML_ATTRIBUTE_NODE)
    	    elem = itemNode->parent;
    	else 
    	    elem = itemNode;
    	*buf = xmlStrdup(BAD_CAST "Element '");
    	if (parsing)
    	    *buf = xmlStrcat(*buf, elem->name);
    	else
    	    *buf = xmlStrcat(*buf, 
    		xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
    	*buf = xmlStrcat(*buf, BAD_CAST "'");
        }
        if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
    	*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
    	*buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str, 
    	    itemNode->ns, itemNode->name));
    	*buf = xmlStrcat(*buf, BAD_CAST "'");
        }
        FREE_AND_NULL(str);
        
        return (*buf);
    }
    
    /**
     * xmlSchemaPFormatItemDes:
     * @buf: the string buffer
     * @item: the item as a schema object
     * @itemNode: the item as a node
     *
     * If the pointer to @buf is not NULL and @but holds no value,
     * the value is set to a item designation using 
     * xmlSchemaFormatItemForReport. This one avoids adding
     * an attribute designation postfix.
     *
     * Returns a string of all enumeration elements.
     */
    static void
    xmlSchemaPRequestItemDes(xmlChar **buf,
    		       xmlSchemaTypePtr item,
    		       xmlNodePtr itemNode)
    {
        if ((buf == 0) || (*buf != NULL)) 
    	return;
        if (itemNode->type == XML_ATTRIBUTE_NODE)
    	itemNode = itemNode->parent;
        xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);	
    }
    
    /**
     * xmlSchemaFormatFacetEnumSet:
     * @buf: the string buffer
     * @type: the type holding the enumeration facets
     *
     * Builds a string consisting of all enumeration elements.
     *
     * Returns a string of all enumeration elements.
     */
    static const xmlChar *
    xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
    {
        xmlSchemaFacetLinkPtr link;
    
        if (*buf != NULL)
    	xmlFree(*buf);    
        *buf = NULL;
        for (link = type->facetSet; link != NULL; link = link->next) {
    	if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
    	    if (*buf == NULL) {
    		*buf = xmlStrdup(BAD_CAST "'");
    		*buf = xmlStrcat(*buf, link->facet->value);
    		*buf = xmlStrcat(*buf, BAD_CAST "'");
    	    } else {
    		*buf = xmlStrcat(*buf, BAD_CAST ", '");
    		*buf = xmlStrcat(*buf, link->facet->value);
    		*buf = xmlStrcat(*buf, BAD_CAST "'");
    	    }
    	}
        }
        return ((const xmlChar *) *buf);
    }
    
    /**
     * xmlSchemaVFacetErr:
     * @ctxt:  the schema validation context
     * @error: the error code
     * @node: the node to be validated  
     * @value: the value of the node
     * @type: the type holding the facet
     * @facet: the facet
     * @message: the error message of NULL
     * @str1: extra data
     * @str2: extra data
     * @str3: extra data
     *
     * Reports a facet validation error.
     * TODO: Should this report the value of an element as well?
     */
    static void
    xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt, 
    		   xmlParserErrors error,
    		   xmlNodePtr node,		   
    		   const xmlChar *value,
    		   unsigned long length,
    		   xmlSchemaTypePtr type,
    		   xmlSchemaFacetPtr facet,		   
    		   const char *message,
    		   const xmlChar *str1,
    		   const xmlChar *str2,
    		   const xmlChar *str3)
    {
        xmlChar *str = NULL, *msg = NULL;
        xmlSchemaTypeType facetType;
    
        xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
        msg = xmlStrcat(msg, BAD_CAST " [");
        msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
        msg = xmlStrcat(msg, BAD_CAST ", facet '");
        if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
    	facetType = XML_SCHEMA_FACET_ENUMERATION;
    	/*
    	* If enumerations are validated, one must not expect the
    	* facet to be given.
    	*/	
        } else	
    	facetType = facet->type;
        msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
        msg = xmlStrcat(msg, BAD_CAST "']: ");
        if (message == NULL) {
    	/*
    	* Use a default message.
    	*/
    	if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
    	    (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
    	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
    
    	    char len[25], actLen[25];
    
    	    /* FIXME, TODO: What is the max expected string length of the
    	    * this value?
    	    */
    	    if (node->type == XML_ATTRIBUTE_NODE)
    		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
    	    else
    		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
    
    	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
    	    snprintf(actLen, 24, "%lu", length);
    
    	    if (facetType == XML_SCHEMA_FACET_LENGTH)
    		msg = xmlStrcat(msg, 
    		BAD_CAST "this differs from the allowed length of '%s'.\n");     
    	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
    		msg = xmlStrcat(msg, 
    		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
    	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
    		msg = xmlStrcat(msg, 
    		BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
    	    
    	    if (node->type == XML_ATTRIBUTE_NODE)
    		xmlSchemaVErrExt(ctxt, node, error,
    		    (const char *) msg,
    		    value, (const xmlChar *) actLen, (const xmlChar *) len,
    		    NULL, NULL);
    	    else 
    		xmlSchemaVErr(ctxt, node, error,  
    		    (const char *) msg,
    		    (const xmlChar *) actLen, (const xmlChar *) len);
    	
    	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
    	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
    		"of the set {%s}.\n");
    	    xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, 
    		xmlSchemaFormatFacetEnumSet(&str, type));
    	} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
    	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
    		"by the pattern '%s'.\n");
    	    xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, 
    		facet->value);	       
    	} else if (node->type == XML_ATTRIBUTE_NODE) {		
    	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
    	    xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
    	} else {	    
    	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
    	    xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
    	}
        } else {
    	msg = xmlStrcat(msg, (const xmlChar *) message);
    	msg = xmlStrcat(msg, BAD_CAST ".\n");
    	xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
        }        
        FREE_AND_NULL(str)
        xmlFree(msg);
    }
    
    /**
     * xmlSchemaVSimpleTypeErr:
     * @ctxt:  the schema validation context
     * @error: the error code
     * @type: the type used for validation
     * @node: the node containing the validated value
     * @value: the validated value
     *
     * Reports a simple type validation error.
     * TODO: Should this report the value of an element as well?
     */
    static void
    xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt, 
    			xmlParserErrors error,			
    			xmlNodePtr node,
    			const xmlChar *value,
    			xmlSchemaTypePtr type)
    {
        xmlChar *str = NULL, *msg = NULL;
        
        xmlSchemaFormatItemForReport(&msg, NULL,  NULL, node, 0);    
        msg = xmlStrcat(msg, BAD_CAST " [");
        msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
        if (node->type == XML_ATTRIBUTE_NODE) {
    	msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
    	xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
        } else {
    	msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
    	xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
        }
        FREE_AND_NULL(str)	
        xmlFree(msg);
    }
    
    /**
     * xmlSchemaVComplexTypeErr:
     * @ctxt:  the schema validation context
     * @error: the error code
     * @node: the node containing the validated value
     * @type: the complex type used for validation
     * @message: the error message
     *
     * Reports a complex type validation error.
     */
    static void
    xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt, 
    			xmlParserErrors error,
    			xmlNodePtr node,
    			xmlSchemaTypePtr type,			
    			const char *message)
    {
        xmlChar *str = NULL, *msg = NULL;
        
        xmlSchemaFormatItemForReport(&msg, NULL,  NULL, node, 0);
        /* Specify the complex type only if it is global. */
        if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
    	msg = xmlStrcat(msg, BAD_CAST " [");
    	msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
    	msg = xmlStrcat(msg, BAD_CAST "]");
        }
        msg = xmlStrcat(msg, BAD_CAST ": %s.\n");   
        xmlSchemaVErr(ctxt, node, error, (const char *) msg,
    	(const xmlChar *) message, NULL);
        FREE_AND_NULL(str)	
        xmlFree(msg);
    }
    
    /**
     * xmlSchemaVComplexTypeElemErr:
     * @ctxt:  the schema validation context
     * @error: the error code
     * @node: the node containing the validated value
     * @type: the complex type used for validation
     * @message: the error message
     *
     * Reports a complex type validation error.
     */
    static void
    xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt, 
    			xmlParserErrors error,
    			xmlNodePtr node,
    			xmlSchemaTypePtr type,			
    			const char *message,
    			int nbval,
    			int nbneg,
    			xmlChar **values)
    {
        xmlChar *str = NULL, *msg = NULL;
        xmlChar *localName, *nsName;
        const xmlChar *cur, *end;
        int i;
        
        xmlSchemaFormatItemForReport(&msg, NULL,  NULL, node, 0);
        /* Specify the complex type only if it is global. */
        if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
    	msg = xmlStrcat(msg, BAD_CAST " [");
    	msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
    	msg = xmlStrcat(msg, BAD_CAST "]");
    	FREE_AND_NULL(str)
        }
        msg = xmlStrcat(msg, BAD_CAST ": ");
        msg = xmlStrcat(msg, (const xmlChar *) message);
        /*
        * Note that is does not make sense to report that we have a
        * wildcard here, since the wildcard might be unfolded into
        * multiple transitions.
        */
        if (nbval + nbneg > 0) {
    	if (nbval + nbneg > 1) {
    	    str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
    	} else
    	    str = xmlStrdup(BAD_CAST ". Expected is ( ");
    	nsName = NULL;
        	    
    	for (i = 0; i < nbval + nbneg; i++) {
    	    cur = values[i];
    	    /*
    	    * Get the local name.
    	    */
    	    localName = NULL;
    	    
    	    end = cur;
    	    if (*end == '*') {
    		localName = xmlStrdup(BAD_CAST "*");
    		*end++;
    	    } else {
    		while ((*end != 0) && (*end != '|'))
    		    end++;
    		localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
    	    }		
    	    if (*end != 0) {		    
    		*end++;
    		/*
    		* Skip "*|*" if they come with negated expressions, since
    		* they represent the same negated wildcard.
    		*/
    		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
    		    /*
    		    * Get the namespace name.
    		    */
    		    cur = end;
    		    if (*end == '*') {
    			nsName = xmlStrdup(BAD_CAST "{*}");
    		    } else {
    			while (*end != 0)
    			    end++;
    			
    			if (i >= nbval)
    			    nsName = xmlStrdup(BAD_CAST "{##other:");
    			else
    			    nsName = xmlStrdup(BAD_CAST "{");
    			
    			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
    			nsName = xmlStrcat(nsName, BAD_CAST "}");
    		    }
    		    str = xmlStrcat(str, BAD_CAST nsName);
    		    FREE_AND_NULL(nsName)
    		} else {
    		    FREE_AND_NULL(localName);
    		    continue;
    		}
    	    }	        
    	    str = xmlStrcat(str, BAD_CAST localName);
    	    FREE_AND_NULL(localName);
    		
    	    if (i < nbval + nbneg -1)
    		str = xmlStrcat(str, BAD_CAST ", ");
    	}	
    	str = xmlStrcat(str, BAD_CAST " )");
    	msg = xmlStrcat(msg, BAD_CAST str);
    	FREE_AND_NULL(str)
        }    
        msg = xmlStrcat(msg, BAD_CAST ".\n");
        xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);    	
        xmlFree(msg);
    }
    
    /**
     * xmlSchemaPMissingAttrErr:
     * @ctxt: the schema validation context
     * @ownerDes: the designation of  the owner
     * @ownerName: the name of the owner
     * @ownerItem: the owner as a schema object
     * @ownerElem: the owner as an element node
     * @node: the parent element node of the missing attribute node
     * @type: the corresponding type of the attribute node
     *
     * Reports an illegal attribute.
     */
    static void
    xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
    			 xmlParserErrors error,			 
    			 xmlChar **ownerDes,
    			 xmlSchemaTypePtr ownerItem,
    			 xmlNodePtr ownerElem,
    			 const char *name,
    			 const char *message)
    {
        xmlChar *des = NULL;
    
        if (ownerDes == NULL)
    	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
        else if (*ownerDes == NULL) {
    	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
    	des = *ownerDes;
        } else 
    	des = *ownerDes;      
        if (message != NULL)
    	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
        else	
    	xmlSchemaPErr(ctxt, ownerElem, error, 
    	    "%s: The attribute '%s' is required but missing.\n", 
    	    BAD_CAST des, BAD_CAST name);
        if (ownerDes == NULL)
    	FREE_AND_NULL(des);
    }
    
    /**
     * xmlSchemaCompTypeToString:
     * @type: the type of the schema item
     *
     * Returns the component name of a schema item.
     */
    static const char *
    xmlSchemaCompTypeToString(xmlSchemaTypeType type)
    {
        switch (type) {
    	case XML_SCHEMA_TYPE_SIMPLE:
    	    return("simple type definition");
    	case XML_SCHEMA_TYPE_COMPLEX:
    	    return("complex type definition");
    	case XML_SCHEMA_TYPE_ELEMENT:
    	    return("element declaration");
    	case XML_SCHEMA_TYPE_ATTRIBUTE:
    	    return("attribute declaration");
    	case XML_SCHEMA_TYPE_GROUP:
    	    return("model group definition");
    	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
    	    return("attribute group definition");
    	case XML_SCHEMA_TYPE_NOTATION:
    	    return("notation declaration");
    	default:
    	    return("Not a schema component");
        }
    }
    /**
     * xmlSchemaPResCompAttrErr:
     * @ctxt: the schema validation context
     * @error: the error code
     * @ownerDes: the designation of  the owner
     * @ownerItem: the owner as a schema object
     * @ownerElem: the owner as an element node
     * @name: the name of the attribute holding the QName 
     * @refName: the referenced local name
     * @refURI: the referenced namespace URI
     * @message: optional message
     *
     * Used to report QName attribute values that failed to resolve
     * to schema components.
     */
    static void
    xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
    			 xmlParserErrors error,			 
    			 xmlChar **ownerDes,
    			 xmlSchemaTypePtr ownerItem,
    			 xmlNodePtr ownerElem,
    			 const char *name,
    			 const xmlChar *refName,
    			 const xmlChar *refURI,
    			 xmlSchemaTypeType refType,
    			 const char *refTypeStr)
    {
        xmlChar *des = NULL, *strA = NULL;
    
        if (ownerDes == NULL)
    	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
        else if (*ownerDes == NULL) {
    	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
    	des = *ownerDes;
        } else
    	des = *ownerDes;
        if (refTypeStr == NULL)
    	refTypeStr = xmlSchemaCompTypeToString(refType);    
    	xmlSchemaPErrExt(ctxt, ownerElem, error, 
    	    NULL, NULL, NULL,
    	    "%s, attribute '%s': The QName value %s does not resolve to a(n) "
    	    "%s.\n", BAD_CAST des, BAD_CAST name, 
    	    xmlSchemaFormatNsUriLocal(&strA, refURI, refName), 
    	    BAD_CAST refTypeStr, NULL);
        if (ownerDes == NULL)
    	FREE_AND_NULL(des)
        FREE_AND_NULL(strA)
    }
    
    /**
     * xmlSchemaPCustomAttrErr:
     * @ctxt: the schema parser context
     * @error: the error code
     * @ownerDes: the designation of the owner
     * @ownerItem: the owner as a schema object
     * @attr: the illegal attribute node 
     *
     * Reports an illegal attribute during the parse.
     */
    static void
    xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
    			xmlParserErrors error,	
    			xmlChar **ownerDes,
    			xmlSchemaTypePtr ownerItem,
    			xmlAttrPtr attr,
    			const char *msg)
    {
        xmlChar *des = NULL;
    
        if (ownerDes == NULL)
    	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
        else if (*ownerDes == NULL) {
    	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
    	des = *ownerDes;
        } else 
    	des = *ownerDes;    
        xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
    	"%s, attribute '%s': %s.\n", 
    	BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
        if (ownerDes == NULL)
    	FREE_AND_NULL(des);
    }
    
    /**
     * xmlSchemaPIllegalAttrErr:
     * @ctxt: the schema parser context
     * @error: the error code
     * @ownerDes: the designation of the attribute's owner
     * @ownerItem: the attribute's owner item
     * @attr: the illegal attribute node 
     *
     * Reports an illegal attribute during the parse.
     */
    static void
    xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
    			 xmlParserErrors error,	
    			 xmlChar **ownerDes,
    			 xmlSchemaTypePtr ownerItem,
    			 xmlAttrPtr attr)
    {
        xmlChar *des = NULL, *strA = NULL;
    
        if (ownerDes == NULL)
    	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
        else if (*ownerDes == NULL) {
    	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
    	des = *ownerDes;
        } else 
    	des = *ownerDes;    
        xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error, 
    	"%s: The attribute '%s' is not allowed.\n", BAD_CAST des, 
    	xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
        if (ownerDes == NULL)
    	FREE_AND_NULL(des);
        FREE_AND_NULL(strA);
    }
    
    /**
     * xmlSchemaPAquireDes:
     * @des: the first designation 
     * @itemDes: the second designation
     * @item: the schema item 
     * @itemElem: the node of the schema item
     *
     * Creates a designation for an item.
     */
    static void
    xmlSchemaPAquireDes(xmlChar **des,
    		    xmlChar **itemDes, 
    		    xmlSchemaTypePtr item,
    		    xmlNodePtr itemElem)
    {
        if (itemDes == NULL)
    	xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
        else if (*itemDes == NULL) {
    	xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
    	*des = *itemDes;
        } else 
    	*des = *itemDes;  
    }
    
    /**
     * xmlSchemaPCustomErr:
     * @ctxt: the schema parser context
     * @error: the error code
     * @itemDes: the designation of the schema item
     * @item: the schema item
     * @itemElem: the node of the schema item
     * @message: the error message
     * @str1: an optional param for the error message
     * @str2: an optional param for the error message
     * @str3: an optional param for the error message
     *
     * Reports an error during parsing.
     */
    static void
    xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
    		    xmlParserErrors error,	
    		    xmlChar **itemDes,
    		    xmlSchemaTypePtr item,
    		    xmlNodePtr itemElem,
    		    const char *message,
    		    const xmlChar *str1,
    		    const xmlChar *str2,
    		    const xmlChar *str3)
    {
        xmlChar *des = NULL, *msg = NULL;
    
        xmlSchemaPAquireDes(&des, itemDes, item, itemElem);   
        msg = xmlStrdup(BAD_CAST "%s: ");
        msg = xmlStrcat(msg, (const xmlChar *) message);
        msg = xmlStrcat(msg, BAD_CAST ".\n");
        if ((itemElem == NULL) && (item != NULL))
    	itemElem = item->node;
        xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL, 
    	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
        if (itemDes == NULL)
    	FREE_AND_NULL(des);
        FREE_AND_NULL(msg);
    }
    
    /**
     * xmlSchemaPCustomErr:
     * @ctxt: the schema parser context
     * @error: the error code
     * @itemDes: the designation of the schema item
     * @item: the schema item
     * @itemElem: the node of the schema item
     * @message: the error message
     * @str1: the optional param for the error message
     *
     * Reports an error during parsing.
     */
    static void
    xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
    		    xmlParserErrors error,	
    		    xmlChar **itemDes,
    		    xmlSchemaTypePtr item,
    		    xmlNodePtr itemElem,
    		    const char *message,
    		    const xmlChar *str1)
    {
        xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
    	str1, NULL, NULL);
    }
    
    /**
     * xmlSchemaPAttrUseErr:
     * @ctxt: the schema parser context
     * @error: the error code
     * @itemDes: the designation of the schema type
     * @item: the schema type
     * @itemElem: the node of the schema type
     * @attr: the invalid schema attribute
     * @message: the error message
     * @str1: the optional param for the error message
     *
     * Reports an attribute use error during parsing.
     */
    static void
    xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
    		    xmlParserErrors error,	
    		    xmlChar **itemDes,
    		    xmlSchemaTypePtr item,
    		    xmlNodePtr itemElem,
    		    const xmlSchemaAttributePtr attr,
    		    const char *message,
    		    const xmlChar *str1)
    {
        xmlChar *des = NULL, *strA = NULL, *msg = NULL;
    
        xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
        xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr), 
    	xmlSchemaGetAttrName(attr));
        msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
        msg = xmlStrcat(msg, (const xmlChar *) message);
        msg = xmlStrcat(msg, BAD_CAST ".\n");
        if ((itemElem == NULL) && (item != NULL))
    	itemElem = item->node;
        xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL, 
    	(const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
        if (itemDes == NULL)
    	FREE_AND_NULL(des);
        FREE_AND_NULL(strA);
        xmlFree(msg);
    }
    
    /**
     * xmlSchemaPIllegalFacetAtomicErr:
     * @ctxt: the schema parser context
     * @error: the error code
     * @itemDes: the designation of the type
     * @item: the schema type
     * @baseItem: the base type of type
     * @facet: the illegal facet
     *
     * Reports an illegal facet for atomic simple types.
     */
    static void
    xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
    			  xmlParserErrors error,	
    			  xmlChar **itemDes,
    			  xmlSchemaTypePtr item,
    			  xmlSchemaTypePtr baseItem,
    			  xmlSchemaFacetPtr facet)
    {
        xmlChar *des = NULL, *strT = NULL;
    
        xmlSchemaPAquireDes(&des, itemDes, item, item->node);
        xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
    	"%s: The facet '%s' is not allowed on types derived from the "
    	"type %s.\n",
    	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
    	xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
    	NULL, NULL);
        if (itemDes == NULL)
    	FREE_AND_NULL(des);
        FREE_AND_NULL(strT);
    }
    
    /**
     * xmlSchemaPIllegalFacetListUnionErr:
     * @ctxt: the schema parser context
     * @error: the error code
     * @itemDes: the designation of the schema item involved
     * @item: the schema item involved
     * @facet: the illegal facet
     *
     * Reports an illegal facet for <list> and <union>.
     */
    static void
    xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
    			  xmlParserErrors error,	
    			  xmlChar **itemDes,
    			  xmlSchemaTypePtr item,
    			  xmlSchemaFacetPtr facet)
    {
        xmlChar *des = NULL, *strT = NULL;
    
        xmlSchemaPAquireDes(&des, itemDes, item, item->node);
        xmlSchemaPErr(ctxt, item->node, error, 
    	"%s: The facet '%s' is not allowed.\n", 
    	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
        if (itemDes == NULL)
    	FREE_AND_NULL(des);
        FREE_AND_NULL(strT);
    }
    
    /**
     * xmlSchemaPMutualExclAttrErr:
     * @ctxt: the schema validation context
     * @error: the error code
     * @elemDes: the designation of the parent element node
     * @attr: the bad attribute node
     * @type: the corresponding type of the attribute node
     *
     * Reports an illegal attribute.
     */
    static void
    xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
    			 xmlParserErrors error,
    			 xmlChar **ownerDes,
    			 xmlSchemaTypePtr ownerItem,
    			 xmlAttrPtr attr,			 
    			 const char *name1,
    			 const char *name2)
    {
        xmlChar *des = NULL;
    
        if (ownerDes == NULL)
    	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);	
        else if (*ownerDes == NULL) {
    	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
    	des = *ownerDes;
        } else 
    	des = *ownerDes;  
        xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
    	"%s: The attributes '%s' and '%s' are mutually exclusive.\n", 
    	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
        if (ownerDes == NULL)
    	FREE_AND_NULL(des)
    }
    
    /**
     * xmlSchemaPSimpleTypeErr:
     * @ctxt:  the schema validation context
     * @error: the error code
     * @type: the type specifier
     * @ownerDes: the designation of the owner
     * @ownerItem: the schema object if existent 
     * @node: the validated node
     * @value: the validated value
     *
     * Reports a simple type validation error.
     * TODO: Should this report the value of an element as well?
     */
    static void
    xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt, 
    			xmlParserErrors error,
    			xmlChar **ownerDes,
    			xmlSchemaTypePtr ownerItem,
    			xmlNodePtr node,
    			xmlSchemaTypePtr type,
    			const char *typeDes,
    			const xmlChar *value,
    			const char *message,
    			const xmlChar *str1,
    			const xmlChar *str2)
    {
        xmlChar *des = NULL, *strA = NULL, *strT = NULL;    
        
        if (ownerDes == NULL)
    	xmlSchemaPRequestItemDes(&des, ownerItem, node);
        else if (*ownerDes == NULL) {
    	xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
    	des = *ownerDes;
        } else 
    	des = *ownerDes;   
        if (type != NULL)
    	typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
        if (message == NULL) {
    	/*
    	* Use default messages.
    	*/
    	if (node->type == XML_ATTRIBUTE_NODE) {
    	    xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
    		"%s, attribute '%s' [%s]: The value '%s' is not "
    		"valid.\n", 
    		BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns, 
    		node->name), BAD_CAST typeDes, value, NULL);
    	} else {
    	    xmlSchemaPErr(ctxt, node, error, 
    		"%s [%s]: The character content is not valid.\n",
    		BAD_CAST des, BAD_CAST typeDes);
    	}
        } else {
    	xmlChar *msg;
    
    	msg = xmlStrdup(BAD_CAST "%s");
    	if (node->type == XML_ATTRIBUTE_NODE)
    	    msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
    	msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
    	msg = xmlStrcat(msg, (const xmlChar *) message);
    	msg = xmlStrcat(msg, BAD_CAST ".\n");
    	if (node->type == XML_ATTRIBUTE_NODE) {
    	    xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
    		(const char *) msg, 
    		BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, 
    		node->ns, node->name), BAD_CAST typeDes, str1, str2);
    	} else {
    	    xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
    		(const char *) msg, 
    		BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
    	}
    	xmlFree(msg);
        }
        /* Cleanup. */
        FREE_AND_NULL(strA)
        FREE_AND_NULL(strT)
        if (ownerDes == NULL)
    	FREE_AND_NULL(des)
    }
    
    /**
     * xmlSchemaPContentErr:
     * @ctxt: the schema parser context
     * @error: the error code
     * @onwerDes: the designation of the holder of the content
     * @ownerItem: the owner item of the holder of the content
     * @ownerElem: the node of the holder of the content
     * @child: the invalid child node
     * @message: the optional error message
     * @content: the optional string describing the correct content
     *
     * Reports an error concerning the content of a schema element.
     */
    static void
    xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt, 
    		     xmlParserErrors error,
    		     xmlChar **ownerDes,
    		     xmlSchemaTypePtr ownerItem,
    		     xmlNodePtr ownerElem,		     
    		     xmlNodePtr child,
    		     const char *message,
    		     const char *content)
    {
        xmlChar *des = NULL;
        
        if (ownerDes == NULL)
    	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
        else if (*ownerDes == NULL) {
    	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
    	des = *ownerDes;
        } else 
    	des = *ownerDes;   
        if (message != NULL)
    	xmlSchemaPErr2(ctxt, ownerElem, child, error, 
    	    "%s: %s.\n", 
    	    BAD_CAST des, BAD_CAST message);
        else {
    	if (content != NULL) {
    	    xmlSchemaPErr2(ctxt, ownerElem, child, error, 
    		"%s: The content is not valid. Expected is %s.\n", 
    		BAD_CAST des, BAD_CAST content);
    	} else {
    	    xmlSchemaPErr2(ctxt, ownerElem, child, error, 
    		"%s: The content is not valid.\n", 
    		BAD_CAST des, NULL);
    	}
        }
        if (ownerDes == NULL)
    	FREE_AND_NULL(des)
    }   
    
    /**
     * xmlSchemaVIllegalAttrErr:
     * @ctxt: the schema validation context
     * @error: the error code
     * @attr: the illegal attribute node
     *
     * Reports an illegal attribute.
     */
    static void
    xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
    			 xmlParserErrors error,
    			 xmlAttrPtr attr)
    {
        xmlChar *strE = NULL, *strA = NULL;
        
        xmlSchemaVErr(ctxt, (xmlNodePtr) attr, 	
    	error,
    	/* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
    	"%s: The attribute '%s' is not allowed.\n",
    	xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
    	xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
        FREE_AND_NULL(strE)
        FREE_AND_NULL(strA)
    }
    
    
    static int
    xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
    {
        switch (item->type) {
    	case XML_SCHEMA_TYPE_COMPLEX:
    	case XML_SCHEMA_TYPE_SIMPLE:
    	case XML_SCHEMA_TYPE_GROUP:
    	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
    		return(1);
    	    break;
    	case XML_SCHEMA_TYPE_ELEMENT:
    	    if ( ((xmlSchemaElementPtr) item)->flags & 
    		XML_SCHEMAS_ELEM_GLOBAL)
    		return(1);
    	    break;
    	case XML_SCHEMA_TYPE_ATTRIBUTE:
    	    if ( ((xmlSchemaAttributePtr) item)->flags & 
    		XML_SCHEMAS_ATTR_GLOBAL)
    		return(1);
    	    break;
    	/* Note that attribute groups are always global. */
    	default:
    	    return(1);
        }
        return (0);
    }
    
    /**
     * xmlSchemaVCustomErr:
     * @ctxt: the schema validation context
     * @error: the error code
     * @node: the validated node
     * @type: the schema type of the validated node
     * @message: the error message
     * @str1: the optional param for the message
     *
     * Reports a validation error.
     */
    static void
    xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
    		    xmlParserErrors error,			    
    		    xmlNodePtr node,
    		    xmlSchemaTypePtr type,
    		    const char *message,
    		    const xmlChar *str1)
    {
        xmlChar *msg = NULL, *str = NULL;
        
        if (node == NULL) {
    	xmlSchemaVErr(ctxt, NULL,
    	    XML_SCHEMAV_INTERNAL,
    	    "Internal error: xmlSchemaVCustomErr, no node "
    	    "given.\n", NULL, NULL);
    	return;
        }
        /* TODO: Are the HTML and DOCB doc nodes expected here? */
        if (node->type != XML_DOCUMENT_NODE) {
    	xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
    	if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
    	    msg = xmlStrcat(msg, BAD_CAST " [");
    	    msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
    	    msg = xmlStrcat(msg, BAD_CAST "]");
    	}
    	msg = xmlStrcat(msg, BAD_CAST ": ");
        } else
    	msg = xmlStrdup((const xmlChar *) "");
        msg = xmlStrcat(msg, (const xmlChar *) message);
        msg = xmlStrcat(msg, BAD_CAST ".\n");   
        xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
        FREE_AND_NULL(msg)
        FREE_AND_NULL(str)
    }
    
    /**
     * xmlSchemaVWildcardErr:
     * @ctxt: the schema validation context
     * @error: the error code
     * @node: the validated node
     * @wild: the wildcard used
     * @message: the error message
     *
     * Reports an validation-by-wildcard error.
     */
    static void
    xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
    		    xmlParserErrors error,			    
    		    xmlNodePtr node,
    		    xmlSchemaWildcardPtr wild,
    		    const char *message)
    {
        xmlChar *des = NULL, *msg = NULL;
    
        xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
        msg = xmlStrdup(BAD_CAST "%s [");
        msg = xmlStrcat(msg, xmlSchemaWildcardPCToString(wild->processContents));
        msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
        msg = xmlStrcat(msg, (const xmlChar *) message);
        msg = xmlStrcat(msg, BAD_CAST ".\n");
        xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
        FREE_AND_NULL(des);
        FREE_AND_NULL(msg);
    }
    
    /**
     * xmlSchemaVMissingAttrErr:
     * @ctxt: the schema validation context
     * @node: the parent element node of the missing attribute node
     * @type: the corresponding type of the attribute node
     *
     * Reports an illegal attribute.
     */
    static void
    xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
    			 xmlNodePtr elem,
    			 xmlSchemaAttributePtr type)
    {
        const xmlChar *name, *uri;
        xmlChar *strE = NULL, *strA = NULL;
    
        if (type->ref != NULL) {				
    	name = type->ref;
    	uri = type->refNs;
        } else {
    	name = type->name;
    	uri = type->targetNamespace;
        }			    
        xmlSchemaVErr(ctxt, elem, 
    	XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
    	/* XML_SCHEMAS_ERR_MISSING, */
    	"%s: The attribute %s is required but missing.\n",
    	xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
    	xmlSchemaFormatNsUriLocal(&strA, uri, name));
        FREE_AND_NULL(strE)
        FREE_AND_NULL(strA)
    }
    
    /************************************************************************
     * 									*
     * 			Allocation functions				*
     * 									*
     ************************************************************************/
    
    /**
     * xmlSchemaNewSchemaForParserCtxt:
     * @ctxt:  a schema validation context
     *
     * 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) {
            xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
            return (NULL);
        }
        memset(ret, 0, sizeof(xmlSchema));
        ret->dict = ctxt->dict;
        xmlDictReference(ret->dict);
    
        return (ret);
    }
    
    /**
     * xmlSchemaNewSchema:
     * @ctxt:  a schema validation context
     *
     * Allocate a new Schema structure.
     *
     * Returns the newly allocated structure or NULL in case or error
     */
    static xmlSchemaAssemblePtr
    xmlSchemaNewAssemble(void)
    {
        xmlSchemaAssemblePtr ret;
    
        ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
        if (ret == NULL) {
            /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
            return (NULL);
        }
        memset(ret, 0, sizeof(xmlSchemaAssemble));
        ret->items = NULL;
        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
     * @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) {
            xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
            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);
    }
    
    /**
     * xmlSchemaFreeImport:
     * @import:  a schema import structure
     *
     * Deallocate an import structure
     */
    static void
    xmlSchemaFreeImport(xmlSchemaImportPtr import)
    {
        if (import == NULL)
            return;
    
        xmlSchemaFree(import->schema);
        xmlFreeDoc(import->doc);
        xmlFree(import);
    }
    
    /**
     * xmlSchemaFreeInclude:
     * @include:  a schema include structure
     *
     * Deallocate an include structure
     */
    static void
    xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
    {
        if (include == NULL)
            return;
    
        xmlFreeDoc(include->doc);
        xmlFree(include);
    }
    
    /**
     * xmlSchemaFreeIncludeList:
     * @includes:  a schema include list
     *
     * Deallocate an include structure
     */
    static void
    xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
    {
        xmlSchemaIncludePtr next;
    
        while (includes != NULL) {
            next = includes->next;
    	xmlSchemaFreeInclude(includes);
    	includes = next;
        }
    }
    
    /**
     * xmlSchemaFreeNotation:
     * @schema:  a schema notation structure
     *
     * Deallocate a Schema Notation structure.
     */
    static void
    xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
    {
        if (nota == NULL)
            return;
        xmlFree(nota);
    }
    
    /**
     * xmlSchemaFreeAttribute:
     * @schema:  a schema attribute structure
     *
     * Deallocate a Schema Attribute structure.
     */
    static void
    xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
    {
        if (attr == NULL)
            return;
        if (attr->annot != NULL) 
    	xmlSchemaFreeAnnot(attr->annot);
        if (attr->defVal != NULL)
    	xmlSchemaFreeValue(attr->defVal);
        xmlFree(attr);
    }
    
    /**
     * xmlSchemaFreeWildcardNsSet:
     * set:  a schema wildcard namespace
     *
     * Deallocates a list of wildcard constraint structures.
     */
    static void
    xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
    {
        xmlSchemaWildcardNsPtr next;
        
        while (set != NULL) {
    	next = set->next;
    	xmlFree(set);
    	set = next;
        }
    }
    
    /**
     * xmlSchemaFreeWildcard:
     * @wildcard:  a wildcard structure
     *
     * Deallocates a wildcard structure.
     */
    void
    xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
    {
        if (wildcard == NULL)
            return;
        if (wildcard->annot != NULL)
            xmlSchemaFreeAnnot(wildcard->annot);
        if (wildcard->nsSet != NULL) 
    	xmlSchemaFreeWildcardNsSet(wildcard->nsSet);    
        if (wildcard->negNsSet != NULL) 
    	xmlFree(wildcard->negNsSet);    
        xmlFree(wildcard);
    }
    
    /**
     * xmlSchemaFreeAttributeGroup:
     * @schema:  a schema attribute group structure
     *
     * Deallocate a Schema Attribute Group structure.
     */
    static void
    xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
    {
        if (attr == NULL)
            return;
        if (attr->annot != NULL)
            xmlSchemaFreeAnnot(attr->annot);
        if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) && 
    	(attr->attributeWildcard != NULL))
    	xmlSchemaFreeWildcard(attr->attributeWildcard);
    
        xmlFree(attr);
    }
    
    /**
     * xmlSchemaFreeAttributeUseList:
     * @attrUse:  an attribute link
     *
     * Deallocate a list of schema attribute uses.
     */
    static void
    xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
    {
        xmlSchemaAttributeLinkPtr next;
    
        while (attrUse != NULL) {
    	next = attrUse->next;
    	xmlFree(attrUse);
    	attrUse = next;
        }    
    }
    
    /**
     * xmlSchemaFreeTypeLinkList:
     * @alink: a type link
     *
     * Deallocate a list of types.
     */
    static void
    xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
    {
        xmlSchemaTypeLinkPtr next;
    
        while (link != NULL) {
    	next = link->next;
    	xmlFree(link);
    	link = next;
        }    
    }
    
    #ifdef IDC_ENABLED
    static void
    xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
    {
        xmlSchemaIDCStateObjPtr next;
        while (sto != NULL) {
    	next = sto->next;
    	if (sto->history != NULL)
    	    xmlFree(sto->history);
    	if (sto->xpathCtxt != NULL)
    	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
    	xmlFree(sto);
    	sto = next;
        }
    }
    
    /**
     * xmlSchemaFreeIDC:
     * @idc: a identity-constraint definition
     *
     * Deallocates an identity-constraint definition.
     */
    static void
    xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
    {
        xmlSchemaIDCSelectPtr cur, prev;
    
        if (idcDef == NULL)
    	return;
        if (idcDef->annot != NULL)
            xmlSchemaFreeAnnot(idcDef->annot);
        if (idcDef->ref != NULL)
    	xmlFree(idcDef->ref);
        /* Selector */
        if (idcDef->selector != NULL) {
    	if (idcDef->selector->xpathComp != NULL)
    	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
    	xmlFree(idcDef->selector);
        }
        /* Fields */
        if (idcDef->fields != NULL) {
    	cur = idcDef->fields;
    	do {
    	    prev = cur;
    	    cur = cur->next;
    	    if (prev->xpathComp != NULL)
    		xmlFreePattern((xmlPatternPtr) prev->xpathComp);
    	    xmlFree(prev);	    
    	} while (cur != NULL);
        }
        xmlFree(idcDef);
    }
    #endif /* IDC_ENABLED */
    
    /**
     * xmlSchemaFreeElement:
     * @schema:  a schema element structure
     *
     * Deallocate a Schema Element structure.
     */
    static void
    xmlSchemaFreeElement(xmlSchemaElementPtr elem)
    {
        if (elem == NULL)
            return;
        if (elem->annot != NULL)
            xmlSchemaFreeAnnot(elem->annot);
        if (elem->contModel != NULL)
            xmlRegFreeRegexp(elem->contModel);
        if (elem->defVal != NULL)
    	xmlSchemaFreeValue(elem->defVal);
        xmlFree(elem);
    }
    
    /**
     * xmlSchemaFreeFacet:
     * @facet:  a schema facet structure
     *
     * Deallocate a Schema Facet structure.
     */
    void
    xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
    {
        if (facet == NULL)
            return;
        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->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;
            }
        }
        if (type->type != XML_SCHEMA_TYPE_BASIC) {
    	if (type->attributeUses != NULL)
    	    xmlSchemaFreeAttributeUseList(type->attributeUses);
    	if ((type->attributeWildcard != NULL) &&
    	    ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
    	    (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
    	    /*
    	    * NOTE: The only case where an attribute wildcard
    	    * is not owned, is if a complex type inherits it
    	    * from a base type.
    	    */
    	    xmlSchemaFreeWildcard(type->attributeWildcard);
    	}
        }
        if (type->memberTypes != NULL)
    	xmlSchemaFreeTypeLinkList(type->memberTypes);
        if (type->facetSet != NULL) {
    	xmlSchemaFacetLinkPtr next, link;
    
    	link = type->facetSet;
    	do {
    	    next = link->next;
    	    xmlFree(link);
    	    link = next;
    	} while (link != NULL);
        }  
        if (type->contModel != NULL)
            xmlRegFreeRegexp(type->contModel);
        xmlFree(type);
    }
    
    /**
     * xmlSchemaFreeTypeList:
     * @type:  a schema type structure
     *
     * Deallocate a Schema Type structure.
     */
    static void
    xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
    {
        xmlSchemaTypePtr next;
    
        while (type != NULL) {
            next = type->redef;
    	xmlSchemaFreeType(type);
    	type = next;
        }
    }
    
    /**
     * xmlSchemaFree:
     * @schema:  a schema structure
     *
     * Deallocate a Schema structure.
     */
    void
    xmlSchemaFree(xmlSchemaPtr schema)
    {
        if (schema == NULL)
            return;
    
        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) xmlSchemaFreeTypeList);
        if (schema->groupDecl != NULL)
            xmlHashFree(schema->groupDecl,
                        (xmlHashDeallocator) xmlSchemaFreeType);
    #ifdef IDC_ENABLED
        if (schema->idcDef != NULL)
            xmlHashFree(schema->idcDef,
                        (xmlHashDeallocator) xmlSchemaFreeIDC);
    #endif
        if (schema->schemasImports != NULL)
    	xmlHashFree(schema->schemasImports,
    		    (xmlHashDeallocator) xmlSchemaFreeImport);
        if (schema->includes != NULL) {
            xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
        }
        if (schema->annot != NULL)
            xmlSchemaFreeAnnot(schema->annot);
        if (schema->doc != NULL && !schema->preserve)
            xmlFreeDoc(schema->doc);
        xmlDictFree(schema->dict);    
        xmlFree(schema);
    }
    
    /************************************************************************
     * 									*
     * 			Debug functions					*
     * 									*
     ************************************************************************/
    
    #ifdef LIBXML_OUTPUT_ENABLED
    
    /**
     * 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 * namespace ATTRIBUTE_UNUSED,
                         const xmlChar * context ATTRIBUTE_UNUSED)
    {
        if (elem == NULL)
            return;
    
        if (elem->flags & XML_SCHEMAS_ELEM_REF) {
    	fprintf(output, "Particle: %s", name);
    	fprintf(output, ", term element: %s", elem->ref);
    	if (elem->refNs != NULL)
    	    fprintf(output, " ns %s", elem->refNs);
        } else { 
    	fprintf(output, "Element");
    	if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
    	    fprintf(output, " (global)");
    	fprintf(output, ": %s ", elem->name);
    	if (namespace != NULL)
    	    fprintf(output, "ns %s", namespace);
        }
        fprintf(output, "\n");
        if ((elem->minOccurs != 1) || (elem->maxOccurs != 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");
        }
        /*
        * Misc other properties.
        */
        if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
    	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
    	(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
    	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
    	(elem->id != NULL)) {
    	fprintf(output, "  props: ");
    	if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
    	    fprintf(output, "[fixed] ");
    	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
    	    fprintf(output, "[default] ");
    	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
    	    fprintf(output, "[abstract] ");
    	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
    	    fprintf(output, "[nillable] ");
    	if (elem->id != NULL)
    	    fprintf(output, "[id: '%s'] ", elem->id);
    	fprintf(output, "\n");
        }
        /*
        * Default/fixed value.
        */
        if (elem->value != NULL)
    	fprintf(output, "  value: '%s'\n", elem->value);
        /*
        * Type.
        */
        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");
        }
        /*
        * Substitution group.
        */
        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");
        }
    }
    
    /**
     * 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 ");
        if (type->targetNamespace != NULL)
    	fprintf(output, "ns %s ", type->targetNamespace);
        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, "[unknown type %d] ", type->type);
                break;
        }    
        fprintf(output, "content: ");
        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:
    	/* not used. */
                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, "  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->base != NULL) {
            fprintf(output, "  base type: %s", type->base);
    	if (type->baseNs != NULL)
    	    fprintf(output, " ns %s\n", type->baseNs);
    	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 (output == NULL)
            return;
        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);
    }
    
    #ifdef IDC_ENABLED
    #ifdef DEBUG_IDC
    /**
     * xmlSchemaDebugDumpIDCTable: 
     * @vctxt: the WXS validation context
     *
     * Displays the current IDC table for debug purposes.
     */
    static void
    xmlSchemaDebugDumpIDCTable(FILE * output,
    			   const xmlChar *namespaceName,
    			   const xmlChar *localName,
    			   xmlSchemaPSVIIDCBindingPtr bind)
    {
        xmlChar *str = NULL, *value;    
        xmlSchemaPSVIIDCNodePtr tab;
        xmlSchemaPSVIIDCKeyPtr key;
        int i, j, res;
        
        fprintf(output, "IDC: TABLES on %s\n", 
    	xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
        FREE_AND_NULL(str)
    
        if (bind == NULL)
    	return;
        do {
    	fprintf(output, "IDC:   BINDING %s\n", 
    	    xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
    	    bind->definition->name));
    	FREE_AND_NULL(str)	
    	for (i = 0; i < bind->nbNodes; i++) {
    	    tab = bind->nodeTable[i];
    	    fprintf(output, "         ( ");
    	    for (j = 0; j < bind->definition->nbFields; j++) {
    		key = tab->keys[j];		
    		if ((key != NULL) && (key->compValue != NULL)) {
    #ifdef IDC_VALUE_SUPPORT
    		    res = xmlSchemaGetCanonValue(key->compValue, &value);
    #else
    		    value = xmlStrdup(BAD_CAST "dummy-value");
    		    res = 0;
    #endif
    		    if (res >= 0)
    			fprintf(output, "\"%s\" ", value);
    		    else
    			fprintf(output, "CANON-VALUE-FAILED ");
    		    if (res == 0) 
    			FREE_AND_NULL(value)
    		} else if (key != NULL)
    		    fprintf(output, "(no val), ");
    		else
    		    fprintf(output, "(key missing), ");
    	    }
    	    fprintf(output, ")\n");
    	}
    	bind = bind->next;
        } while (bind != NULL);
    }
    #endif /* DEBUG_IDC */
    #endif /* IDC_ENABLED */
    #endif /* LIBXML_OUTPUT_ENABLED */
    
    /************************************************************************
     *									*
     * 			Utilities					*
     *									*
     ************************************************************************/
    
    /**
     * xmlSchemaGetPropNode:
     * @node: the element node 
     * @name: the name of the attribute
     *
     * Seeks an attribute with a name of @name in
     * no namespace.
     *
     * Returns the attribute or NULL if not present. 
     */
    static xmlAttrPtr
    xmlSchemaGetPropNode(xmlNodePtr node, const char *name) 
    {
        xmlAttrPtr prop;
    
        if ((node == NULL) || (name == NULL)) 
    	return(NULL);
        prop = node->properties;
        while (prop != NULL) {
            if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))	    
    	    return(prop);
    	prop = prop->next;
        }
        return (NULL);
    }
    
    /**
     * xmlSchemaGetPropNodeNs:
     * @node: the element node 
     * @uri: the uri
     * @name: the name of the attribute
     *
     * Seeks an attribute with a local name of @name and
     * a namespace URI of @uri.
     *
     * Returns the attribute or NULL if not present. 
     */
    static xmlAttrPtr
    xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name) 
    {
        xmlAttrPtr prop;
    
        if ((node == NULL) || (name == NULL)) 
    	return(NULL);
        prop = node->properties;
        while (prop != NULL) {
    	if ((prop->ns != NULL) &&
    	    xmlStrEqual(prop->name, BAD_CAST name) &&
    	    xmlStrEqual(prop->ns->href, BAD_CAST uri))
    	    return(prop);
    	prop = prop->next;
        }
        return (NULL);
    }
    
    static const xmlChar *
    xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
    {
        xmlChar *val;
        const xmlChar *ret;
    
        val = xmlNodeGetContent(node);
        if (val == NULL)
            return(NULL);
        ret = xmlDictLookup(ctxt->dict, val, -1);
        xmlFree(val);
        return(ret);    
    }
    
    /**
     * xmlSchemaGetProp:
     * @ctxt: the parser context
     * @node: the node
     * @name: the property name
     * 
     * Read a attribute value and internalize the string
     *
     * Returns the string or NULL if not present.
     */
    static const xmlChar *
    xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
                     const char *name)
    {
        xmlChar *val;
        const xmlChar *ret;
    
        val = xmlGetProp(node, BAD_CAST name);
        if (val == NULL)
            return(NULL);
        ret = xmlDictLookup(ctxt->dict, val, -1);
        xmlFree(val);
        return(ret);
    }
    
    /************************************************************************
     * 									*
     * 			Parsing functions				*
     * 									*
     ************************************************************************/
    
    /**
     * xmlSchemaGetElem:
     * @schema:  the schema context
     * @name:  the element name
     * @ns:  the element namespace
     *
     * Lookup a global element declaration in the schema.
     *
     * Returns the element declaration or NULL if not found.
     */
    static xmlSchemaElementPtr
    xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
                     const xmlChar * namespace)
    {
        xmlSchemaElementPtr ret;
    
        if ((name == NULL) || (schema == NULL))
            return (NULL);
            
            ret = xmlHashLookup2(schema->elemDecl, name, namespace);
            if ((ret != NULL) &&
    	    (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
                return (ret);
        } else
    	ret = NULL;
        /*
         * This one was removed, since top level element declarations have
         * the target namespace specified in targetNamespace of the <schema>
         * information element, even if elementFormDefault is "unqualified".
         */
        
        /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
            if (xmlStrEqual(namespace, schema->targetNamespace))
    	    ret = xmlHashLookup2(schema->elemDecl, name, NULL);
    	else
    	    ret = xmlHashLookup2(schema->elemDecl, name, namespace);
            if ((ret != NULL) &&
    	    ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
                return (ret);
    	}
        */
        
        /*
        * Removed since imported components will be hold by the main schema only.
        *
        if (namespace == NULL)
    	import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
        else
        import = xmlHashLookup(schema->schemasImports, namespace);
        if (import != NULL) {
    	ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
    	if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
    	    return (ret);
    	} else
    	    ret = NULL;
        }
        */
    #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);
    }
    
    /**
     * 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) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
                return (ret);
        }
        ret = xmlSchemaGetPredefinedType(name, namespace);
        if (ret != NULL)
    	return (ret);
        /*
        * Removed, since the imported components will be grafted on the
        * main schema only.    
        if (namespace == NULL)
    	import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
        else
        import = xmlHashLookup(schema->schemasImports, namespace);
        if (import != NULL) {
    	ret = xmlSchemaGetType(import->schema, name, namespace);
    	if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
    	    return (ret);
    	} else
    	    ret = NULL;
        }
        */
    #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);
    }
    
    /**
     * xmlSchemaGetAttribute:
     * @schema:  the context of the schema 
     * @name:  the name of the attribute
     * @ns:  the target namespace of the attribute 
     *
     * Lookup a an attribute in the schema or imported schemas
     *
     * Returns the attribute declaration or NULL if not found.
     */
    static xmlSchemaAttributePtr
    xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
                     const xmlChar * namespace)
    {
        xmlSchemaAttributePtr ret;
    
        if ((name == NULL) || (schema == NULL))
            return (NULL);
        
        
        ret = xmlHashLookup2(schema->attrDecl, name, namespace);
        if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
    	return (ret); 
        else
    	ret = NULL;
        /*
        * Removed, since imported components will be hold by the main schema only.
        *
        if (namespace == NULL)
    	import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
        else
    	import = xmlHashLookup(schema->schemasImports, namespace);	
        if (import != NULL) {
    	ret = xmlSchemaGetAttribute(import->schema, name, namespace);
    	if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
    	    return (ret);
    	} else
    	    ret = NULL;
        }
        */
    #ifdef DEBUG
        if (ret == NULL) {
            if (namespace == NULL)
                fprintf(stderr, "Unable to lookup attribute %s", name);
            else
                fprintf(stderr, "Unable to lookup attribute %s:%s", name,
                        namespace);
        }
    #endif
        return (ret);
    }
    
    /**
     * xmlSchemaGetAttributeGroup:
     * @schema:  the context of the schema 
     * @name:  the name of the attribute group
     * @ns:  the target namespace of the attribute group 
     *
     * Lookup a an attribute group in the schema or imported schemas
     *
     * Returns the attribute group definition or NULL if not found.
     */
    static xmlSchemaAttributeGroupPtr
    xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
                     const xmlChar * namespace)
    {
        xmlSchemaAttributeGroupPtr ret;
    
        if ((name == NULL) || (schema == NULL))
            return (NULL);
        
        
        ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
        if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
    	return (ret);  
        else
    	ret = NULL;
        /*
        * Removed since imported components will be hold by the main schema only.
        *
        if (namespace == NULL)
    	import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
        else
    	import = xmlHashLookup(schema->schemasImports, namespace);	
        if (import != NULL) {
    	ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
    	if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
    	    return (ret);
    	else
    	    ret = NULL;
        }
        */
    #ifdef DEBUG
        if (ret == NULL) {
            if (namespace == NULL)
                fprintf(stderr, "Unable to lookup attribute group %s", name);
            else
                fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
                        namespace);
        }
    #endif
        return (ret);
    }
    
    /**
     * xmlSchemaGetGroup:
     * @schema:  the context of the schema 
     * @name:  the name of the group
     * @ns:  the target namespace of the group 
     *
     * Lookup a group in the schema or imported schemas
     *
     * Returns the group definition or NULL if not found.
     */
    static xmlSchemaTypePtr
    xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
                     const xmlChar * namespace)
    {
        xmlSchemaTypePtr ret;
    
        if ((name == NULL) || (schema == NULL))
            return (NULL);
        
        
        ret = xmlHashLookup2(schema->groupDecl, name, namespace);
        if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
    	return (ret);  
        else
    	ret = NULL;
        /*
        * Removed since imported components will be hold by the main schema only.
        *
        if (namespace == NULL)
    	import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
        else
    	import = xmlHashLookup(schema->schemasImports, namespace);	
        if (import != NULL) {
    	ret = xmlSchemaGetGroup(import->schema, name, namespace);
    	if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
    	    return (ret);
    	else
    	    ret = NULL;
        }
        */
    #ifdef DEBUG
        if (ret == NULL) {
            if (namespace == NULL)
                fprintf(stderr, "Unable to lookup group %s", name);
            else
                fprintf(stderr, "Unable to lookup group %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_CH(*str)))
                return (0);
            str++;
        }
        return (1);
    }
    
    /**
     * xmlSchemaAddAssembledItem:
     * @ctxt:  a schema parser context
     * @schema:  the schema being built
     * @item:  the item
     *
     * Add a item to the schema's list of current items.
     * This is used if the schema was already constructed and
     * new schemata need to be added to it.
     * *WARNING* this interface is highly subject to change.
     *
     * Returns 0 if suceeds and -1 if an internal error occurs.
     */
    static int
    xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
    			   xmlSchemaTypePtr item)
    {
        static int growSize = 100;
        xmlSchemaAssemblePtr ass;
    
        ass = ctxt->assemble;
        if (ass->sizeItems < 0) {
    	/* If disabled. */
    	return (0);
        }
        if (ass->sizeItems <= 0) {
    	ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
    	if (ass->items == NULL) {
    	    xmlSchemaPErrMemory(ctxt,
    		"allocating new item buffer", NULL);
    	    return (-1);
    	}	
    	ass->sizeItems = growSize;
        } else if (ass->sizeItems <= ass->nbItems) {
    	ass->sizeItems *= 2;
    	ass->items = (void **) xmlRealloc(ass->items, 
    	    ass->sizeItems * sizeof(xmlSchemaTypePtr));
    	if (ass->items == NULL) {
    	    xmlSchemaPErrMemory(ctxt,
    		"growing item buffer", NULL);
    	    ass->sizeItems = 0;
    	    return (-1);
    	}	
        }
        /* ass->items[ass->nbItems++] = (void *) item; */
        ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
        return (0);
    }
    
    /**
     * xmlSchemaAddNotation:
     * @ctxt:  a schema parser context
     * @schema:  the schema being built
     * @name:  the item name
     *
     * Add an XML schema annotation 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 = xmlHashCreateDict(10, ctxt->dict);
        if (schema->notaDecl == NULL)
            return (NULL);
    
        ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
        if (ret == NULL) {
            xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
            return (NULL);
        }
        memset(ret, 0, sizeof(xmlSchemaNotation));
        ret->name = xmlDictLookup(ctxt->dict, name, -1);
        val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
                               ret);
        if (val != 0) {
    	/*
    	* TODO: This should never happen, since a unique name will be computed.
    	* If it fails, then an other internal error must have occured.
    	*/
    	xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
    		      XML_SCHEMAP_REDEFINED_NOTATION,
                          "Annotation declaration '%s' is already declared.\n",
                          name, NULL);
            xmlFree(ret);
            return (NULL);
        }
        return (ret);
    }
    
    
    /**
     * xmlSchemaAddAttribute:
     * @ctxt:  a schema parser context
     * @schema:  the schema being built
     * @name:  the item name
     * @namespace:  the namespace
     *
     * 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, const xmlChar * namespace,
    		      xmlNodePtr node, int topLevel)
    {
        xmlSchemaAttributePtr ret = NULL;
        int val;
    
        if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
            return (NULL);
    
    #ifdef DEBUG
        fprintf(stderr, "Adding attribute %s\n", name);
        if (namespace != NULL)
    	fprintf(stderr, "  target namespace %s\n", namespace);
    #endif
    
        if (schema->attrDecl == NULL)
            schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
        if (schema->attrDecl == NULL)
            return (NULL);
    
        ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
        if (ret == NULL) {
            xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
            return (NULL);
        }
        memset(ret, 0, sizeof(xmlSchemaAttribute));
        ret->name = xmlDictLookup(ctxt->dict, name, -1);
        ret->targetNamespace = namespace;
        val = xmlHashAddEntry3(schema->attrDecl, name,
                               namespace, ctxt->container, ret);
        if (val != 0) {
    	if (topLevel) {
    	    xmlSchemaPCustomErr(ctxt,
    		XML_SCHEMAP_REDEFINED_ATTR,
    		NULL, NULL, node,
    		"A global attribute declaration with the name '%s' does "
    		"already exist", name);
    	    xmlFree(ret);	    
    	    return (NULL);
    	} else {
    	    char buf[30];
    	    /*
    	    * Using the ctxt->container for xmlHashAddEntry3 is ambigious
    	    * in the scenario:
    	    * 1. multiple top-level complex types have different target
    	    *    namespaces but have the SAME NAME; this can happen if
    	    *	 schemata are  imported
    	    * 2. those complex types contain attributes with an equal name
    	    * 3. those attributes are in no namespace 
    	    * We will compute a new context string.
    	    */	    
    	    snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
    	    val = xmlHashAddEntry3(schema->attrDecl, name,
    		namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
    
    	    if (val != 0) {
    		xmlSchemaPCustomErr(ctxt,
    		    XML_SCHEMAP_INTERNAL,
    		    NULL, NULL, node,
    		    "Internal error: xmlSchemaAddAttribute, "
    		    "a dublicate attribute declaration with the name '%s' "
    		    "could not be added to the hash.", name);
    		xmlFree(ret);
    		return (NULL);
    	    }	    
    	}
        }
        if (ctxt->assemble != NULL)
    	xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret); 
        return (ret);
    }
    
    /**
     * xmlSchemaAddAttributeGroup:
     * @ctxt:  a schema parser 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,
    			   xmlNodePtr node)
    {
        xmlSchemaAttributeGroupPtr ret = NULL;
        int val;
    
        if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
            return (NULL);
    
        if (schema->attrgrpDecl == NULL)
            schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
        if (schema->attrgrpDecl == NULL)
            return (NULL);
    
        ret =
            (xmlSchemaAttributeGroupPtr)
            xmlMalloc(sizeof(xmlSchemaAttributeGroup));
        if (ret == NULL) {
            xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
            return (NULL);
        }
        memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
        ret->name = xmlDictLookup(ctxt->dict, name, -1);
        val = xmlHashAddEntry3(schema->attrgrpDecl, name,
                               schema->targetNamespace, ctxt->container, ret);
        if (val != 0) {
    	xmlSchemaPCustomErr(ctxt,
    	    XML_SCHEMAP_REDEFINED_ATTRGROUP,
    	    NULL, NULL, node,
    	    "A global attribute group definition with the name '%s' does already exist", name);
            xmlFree(ret);
            return (NULL);
        }
        if (ctxt->assemble != NULL)	
    	xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
        return (ret);
    }
    
    /**
     * xmlSchemaAddElement:
     * @ctxt:  a schema parser 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,
    		    xmlNodePtr node, int topLevel)
    {
        xmlSchemaElementPtr ret = NULL;
        int val;
    
        if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
            return (NULL);
    
    #ifdef DEBUG
        fprintf(stderr, "Adding element %s\n", name);
        if (namespace != NULL)
    	fprintf(stderr, "  target namespace %s\n", namespace);
    #endif
    
        if (schema->elemDecl == NULL)
            schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
        if (schema->elemDecl == NULL)
            return (NULL);
    
        ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
        if (ret == NULL) {
            xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
            return (NULL);
        }
        memset(ret, 0, sizeof(xmlSchemaElement));
        ret->name = xmlDictLookup(ctxt->dict, name, -1);
        val = xmlHashAddEntry3(schema->elemDecl, name,
                               namespace, ctxt->container, ret);
        if (val != 0) {
    	if (topLevel) {
    	    xmlSchemaPCustomErr(ctxt,
    		XML_SCHEMAP_REDEFINED_ELEMENT,
    		NULL, NULL, node,
    		"A global element declaration with the name '%s' does "
    		"already exist", name);
                xmlFree(ret);
                return (NULL);
    	} else {
    	    char buf[30]; 
    
    	    snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
    	    val = xmlHashAddEntry3(schema->elemDecl, name, 
    		namespace, (xmlChar *) buf, ret);
    	    if (val != 0) {
    		xmlSchemaPCustomErr(ctxt,
    		    XML_SCHEMAP_INTERNAL,
    		    NULL, NULL, node,
    		    "Internal error: xmlSchemaAddElement, "
    		    "a dublicate element declaration with the name '%s' "
    		    "could not be added to the hash.", name);
    		xmlFree(ret);
    		return (NULL);
    	    }
    	}
            
        }
        if (ctxt->assemble != NULL)	
    	xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
        return (ret);
    }
    
    /**
     * xmlSchemaAddType:
     * @ctxt:  a schema parser context
     * @schema:  the schema being built
     * @name:  the item name
     * @namespace:  the namespace
     *
     * Add an XML schema item
     * *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, const xmlChar * namespace,
    		 xmlNodePtr node)
    {
        xmlSchemaTypePtr ret = NULL;
        int val;
    
        if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
            return (NULL);
    
    #ifdef DEBUG
        fprintf(stderr, "Adding type %s\n", name);
        if (namespace != NULL)
    	fprintf(stderr, "  target namespace %s\n", namespace);
    #endif
    
        if (schema->typeDecl == NULL)
            schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
        if (schema->typeDecl == NULL)
            return (NULL);
    
        ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
        if (ret == NULL) {
            xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
            return (NULL);
        }
        memset(ret, 0, sizeof(xmlSchemaType));
        ret->name = xmlDictLookup(ctxt->dict, name, -1);
        ret->redef = NULL;
        val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
        if (val != 0) {	
            if (ctxt->includes == 0) {	    
    	    xmlSchemaPCustomErr(ctxt,
    		XML_SCHEMAP_REDEFINED_TYPE,
    		NULL, NULL, node, 
    		"A global type definition with the name '%s' does already exist", name);            	    
    	    xmlFree(ret);
    	    return (NULL);
    	} else {
    	    xmlSchemaTypePtr prev;
    
    	    prev = xmlHashLookup2(schema->typeDecl, name, namespace);
    	    if (prev == NULL) {
    		xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
    		    XML_ERR_INTERNAL_ERROR,
    		    "Internal error: xmlSchemaAddType, on type "
    		    "'%s'.\n",
    		    name, NULL);
    		xmlFree(ret);
    		return (NULL);
    	    }
    	    ret->redef = prev->redef;
    	    prev->redef = ret;
    	}
        }
        ret->minOccurs = 1;
        ret->maxOccurs = 1;
        ret->attributeUses = NULL;
        ret->attributeWildcard = NULL;
        if (ctxt->assemble != NULL)	
    	xmlSchemaAddAssembledItem(ctxt,ret);
        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, const xmlChar *namespaceName,
    		  xmlNodePtr node)
    {
        xmlSchemaTypePtr ret = NULL;
        int val;
    
        if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
            return (NULL);
    
        if (schema->groupDecl == NULL)
            schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
        if (schema->groupDecl == NULL)
            return (NULL);
    
        ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
        if (ret == NULL) {
            xmlSchemaPErrMemory(ctxt, "adding group", NULL);
            return (NULL);
        }
        memset(ret, 0, sizeof(xmlSchemaType));
        ret->name = xmlDictLookup(ctxt->dict, name, -1);
        val =
            xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
                             ret);
        if (val != 0) {
    	xmlSchemaPCustomErr(ctxt,
    		XML_SCHEMAP_REDEFINED_GROUP,
    		NULL, NULL, node,
    		"A global model group definition with the name '%s' does already exist", name);    
            xmlFree(ret);
            return (NULL);
        }
        ret->minOccurs = 1;
        ret->maxOccurs = 1;
        if (ctxt->assemble != NULL)	
    	xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
        return (ret);
    }
    
    /**
     * xmlSchemaNewWildcardNs:
     * @ctxt:  a schema validation context
     *
     * Creates a new wildcard namespace constraint.
     *
     * Returns the new struture or NULL in case of error
     */
    static xmlSchemaWildcardNsPtr
    xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
    {
        xmlSchemaWildcardNsPtr ret;
    
        ret = (xmlSchemaWildcardNsPtr) 
    	xmlMalloc(sizeof(xmlSchemaWildcardNs));
        if (ret == NULL) {
    	xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
    	return (NULL);    
        }
        ret->value = NULL;
        ret->next = NULL;
        return (ret);
    }
    
    /**
     * xmlSchemaAddWildcard:
     * @ctxt:  a schema validation context
     * Adds a wildcard. It corresponds to a 
     * xsd:anyAttribute and is used as storage for namespace 
     * constraints on a xsd:any.
     *
     * Returns the new struture or NULL in case of error
     */
    static xmlSchemaWildcardPtr
    xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
    {
        xmlSchemaWildcardPtr ret = NULL;
    
        if (ctxt == NULL)
            return (NULL);
    
        ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
        if (ret == NULL) {
            xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
            return (NULL);
        }
        memset(ret, 0, sizeof(xmlSchemaWildcard));
        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 const xmlChar *
    xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
                    const char *name, const xmlChar ** namespace)
    {
        const xmlChar *val;
        xmlNsPtr ns;
        const xmlChar *ret, *prefix;
        int len;
        xmlAttrPtr attr;
    
        *namespace = NULL;
        attr = xmlSchemaGetPropNode(node, name);
        if (attr == NULL)
    	return (NULL);
        val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
    
        if (val == NULL)
            return (NULL);
    
        if (!strchr((char *) val, ':')) {
    	ns = xmlSearchNs(node->doc, node, 0);
    	if (ns) {
    	    *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
    	    return (val);
    	}
        }
        ret = xmlSplitQName3(val, &len);
        if (ret == NULL) {
            return (val);
        }
        ret = xmlDictLookup(ctxt->dict, ret, -1);
        prefix = xmlDictLookup(ctxt->dict, val, len);
    
        ns = xmlSearchNs(node->doc, node, prefix);
        if (ns == NULL) {
            xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED, 
    	    NULL, NULL, (xmlNodePtr) attr, 
    	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
    	    "The QName value '%s' has no corresponding namespace "
    	    "declaration in scope", val, NULL);
        } else {
            *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
        }
        return (ret);
    }
    
    /**
     * xmlSchemaPValAttrNodeQNameValue:
     * @ctxt:  a schema parser context
     * @schema: the schema context
     * @ownerDes: the designation of the parent element
     * @ownerItem: the parent as a schema object
     * @value:  the QName value 
     * @local: the resulting local part if found, the attribute value otherwise
     * @uri:  the resulting namespace URI if found
     *
     * Extracts the local name and the URI of a QName value and validates it.
     * This one is intended to be used on attribute values that
     * should resolve to schema components.
     *
     * Returns 0, in case the QName is valid, a positive error code
     * if not valid and -1 if an internal error occurs.
     */
    static int
    xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt, 
    				       xmlSchemaPtr schema,
    				       xmlChar **ownerDes,
    				       xmlSchemaTypePtr ownerItem,
    				       xmlAttrPtr attr,
    				       const xmlChar *value,
    				       const xmlChar **uri,
    				       const xmlChar **prefix,
    				       const xmlChar **local)
    {
        const xmlChar *pref;
        xmlNsPtr ns;
        int len, ret;
        
        *uri = NULL;
        *local = NULL;
        if (prefix != 0)
    	*prefix = NULL;
        ret = xmlValidateQName(value, 1);
        if (ret > 0) {		
    	xmlSchemaPSimpleTypeErr(ctxt, 
    	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 
    	    ownerDes, ownerItem, (xmlNodePtr) attr, 
    	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 
    	    "QName", value, 
    	    NULL, NULL, NULL);	
    	*local = value;
    	return (ctxt->err); 
        } else if (ret < 0)
    	return (-1);
       
        if (!strchr((char *) value, ':')) {	
    	ns = xmlSearchNs(attr->doc, attr->parent, 0);
    	if (ns)
    	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
    	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
    	    /*
    	    * This one takes care of included schemas with no
    	    * target namespace.
    	    */
    	    *uri = schema->targetNamespace;
    	}	
    	*local = value;
    	return (0);
        }
        /*
        * At this point xmlSplitQName3 has to return a local name.
        */
        *local = xmlSplitQName3(value, &len);
        *local = xmlDictLookup(ctxt->dict, *local, -1);
        pref = xmlDictLookup(ctxt->dict, value, len);
        if (prefix != 0)
    	*prefix = pref;
        ns = xmlSearchNs(attr->doc, attr->parent, pref);
        if (ns == NULL) {
    	xmlSchemaPSimpleTypeErr(ctxt, 
    	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
    	    ownerDes, ownerItem, (xmlNodePtr) attr, 
    	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
    	    "The QName value '%s' has no corresponding namespace "
    	    "declaration in scope", value, NULL);
    	return (ctxt->err);
        } else {
            *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
        }    
        return (0);
    }
    
    /**
     * xmlSchemaPValAttrNodeQName:
     * @ctxt:  a schema parser context
     * @schema: the schema context
     * @ownerDes: the designation of the owner element
     * @ownerItem: the owner as a schema object
     * @attr:  the attribute node
     * @local: the resulting local part if found, the attribute value otherwise
     * @uri:  the resulting namespace URI if found
     *
     * Extracts and validates the QName of an attribute value.
     * This one is intended to be used on attribute values that
     * should resolve to schema components.
     *
     * Returns 0, in case the QName is valid, a positive error code
     * if not valid and -1 if an internal error occurs.
     */
    static int
    xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt, 
    				       xmlSchemaPtr schema,
    				       xmlChar **ownerDes,
    				       xmlSchemaTypePtr ownerItem,
    				       xmlAttrPtr attr,
    				       const xmlChar **uri,
    				       const xmlChar **prefix,
    				       const xmlChar **local)
    {
        const xmlChar *value;
    
        value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
        return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, 
    	ownerDes, ownerItem, attr, value, uri, prefix, local));
    }
    
    /**
     * xmlSchemaPValAttrQName:
     * @ctxt:  a schema parser context
     * @schema: the schema context
     * @ownerDes: the designation of the parent element
     * @ownerItem: the owner as a schema object
     * @ownerElem:  the parent node of the attribute
     * @name:  the name of the attribute
     * @local: the resulting local part if found, the attribute value otherwise
     * @uri:  the resulting namespace URI if found
     *
     * Extracts and validates the QName of an attribute value.
     *
     * Returns 0, in case the QName is valid, a positive error code
     * if not valid and -1 if an internal error occurs.
     */
    static int
    xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt, 
    				   xmlSchemaPtr schema, 
    				   xmlChar **ownerDes,
    				   xmlSchemaTypePtr ownerItem,
    				   xmlNodePtr ownerElem,
    				   const char *name,
    				   const xmlChar **uri,
    				   const xmlChar **prefix,
    				   const xmlChar **local)
    {
        xmlAttrPtr attr;
    
        attr = xmlSchemaGetPropNode(ownerElem, name);
        if (attr == NULL) {
    	*local = NULL;
    	*uri = NULL;
    	return (0);    
        }
        return (xmlSchemaPValAttrNodeQName(ctxt, schema, 
    	ownerDes, ownerItem, attr, uri, prefix, local));
    }
    
    /**
     * xmlSchemaPValAttrID:
     * @ctxt:  a schema parser context
     * @schema: the schema context
     * @ownerDes: the designation of the parent element
     * @ownerItem: the owner as a schema object
     * @ownerElem:  the parent node of the attribute
     * @name:  the name of the attribute
     *
     * Extracts and validates the ID of an attribute value.
     *
     * Returns 0, in case the ID is valid, a positive error code
     * if not valid and -1 if an internal error occurs.
     */
    static int
    xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
    		    xmlChar **ownerDes,
    		    xmlSchemaTypePtr ownerItem,
    		    xmlNodePtr ownerElem,
    		    const xmlChar *name)
    {
        int ret;
        xmlChar *value;
        xmlAttrPtr attr; 
    
        value = xmlGetNoNsProp(ownerElem, name);
        if (value == NULL)
    	return (0);
    
        attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
        if (attr == NULL)
    	return (-1);
    
        ret = xmlValidateNCName(BAD_CAST value, 1);
        if (ret == 0) {	
    	/*
    	* NOTE: the IDness might have already be declared in the DTD
    	*/
    	if (attr->atype != XML_ATTRIBUTE_ID) {
    	    xmlIDPtr res;
    	    xmlChar *strip;
    	    
    	    /* 
    	    * TODO: Use xmlSchemaStrip here; it's not exported at this
    	    * moment.
    	    */
    	    strip = xmlSchemaCollapseString(BAD_CAST value);	    
    	    if (strip != NULL)
    		value = strip;		
        	    res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
    	    if (res == NULL) {
    		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
    		xmlSchemaPSimpleTypeErr(ctxt, 
    		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 
    		    ownerDes, ownerItem, (xmlNodePtr) attr, 
    		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID), 
    		    NULL, NULL, "The ID '%s' is already defined",
    		    BAD_CAST value, NULL);
    	    } else
    		attr->atype = XML_ATTRIBUTE_ID;
    	    if (strip != NULL)
    		xmlFree(strip);
    	}
        } else if (ret > 0) {
    	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
    	xmlSchemaPSimpleTypeErr(ctxt, 
    	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, 
    	    ownerDes, ownerItem, (xmlNodePtr) attr, 
    	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID), 
    	    NULL, BAD_CAST value, NULL, NULL, NULL);	
        }
        xmlFree(value);
    
        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,
    		int min, int max, int def, const char *expected)
    {
        const xmlChar *val, *cur;
        int ret = 0;
        xmlAttrPtr attr;
    
        attr = xmlSchemaGetPropNode(node, "maxOccurs");
        if (attr == NULL)
    	return (def);
        val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
    
        if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
    	if (max != UNBOUNDED) {
    	    xmlSchemaPSimpleTypeErr(ctxt, 
    		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
    		/* XML_SCHEMAP_INVALID_MINOCCURS, */
    		NULL, NULL, (xmlNodePtr) attr, NULL, expected,
    		val, NULL, NULL, NULL);
    	    return (def);
    	} else 
    	    return (UNBOUNDED);  /* encoding it with -1 might be another option */
        }
    
        cur = val;
        while (IS_BLANK_CH(*cur))
            cur++;
        if (*cur == 0) {
            xmlSchemaPSimpleTypeErr(ctxt, 
    	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
    	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
    	    NULL, NULL, (xmlNodePtr) attr, NULL, expected,
    	    val, NULL, NULL, NULL);
    	return (def);
        }
        while ((*cur >= '0') && (*cur <= '9')) {
            ret = ret * 10 + (*cur - '0');
            cur++;
        }
        while (IS_BLANK_CH(*cur))
            cur++;
        /*
        * TODO: Restrict the maximal value to Integer.
        */
        if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
    	xmlSchemaPSimpleTypeErr(ctxt, 
    	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
    	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
    	    NULL, NULL, (xmlNodePtr) attr, NULL, expected,
    	    val, NULL, NULL, NULL);
            return (def);
        }
        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, 
    		int min, int max, int def, const char *expected)
    {
        const xmlChar *val, *cur;
        int ret = 0;
        xmlAttrPtr attr;
    
        attr = xmlSchemaGetPropNode(node, "minOccurs");
        if (attr == NULL)
    	return (def);
        val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
        cur = val;
        while (IS_BLANK_CH(*cur))
            cur++;
        if (*cur == 0) {
            xmlSchemaPSimpleTypeErr(ctxt, 
    	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
    	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
    	    NULL, NULL, (xmlNodePtr) attr, NULL, expected,
    	    val, NULL, NULL, NULL);
            return (def);
        }
        while ((*cur >= '0') && (*cur <= '9')) {
            ret = ret * 10 + (*cur - '0');
            cur++;
        }
        while (IS_BLANK_CH(*cur))
            cur++;
        /*
        * TODO: Restrict the maximal value to Integer.
        */
        if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
    	xmlSchemaPSimpleTypeErr(ctxt, 
    	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
    	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
    	    NULL, NULL, (xmlNodePtr) attr, NULL, expected,
    	    val, NULL, NULL, NULL);
            return (def);
        }
        return (ret);
    }
    
    /**
     * xmlSchemaPGetBoolNodeValue:
     * @ctxt:  a schema validation context
     * @ownerDes:  owner designation
     * @ownerItem:  the owner as a schema item
     * @node: the node holding the value
     *
     * Converts a boolean string value into 1 or 0.
     *
     * Returns 0 or 1.
     */
    static int
    xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,			   
    			   xmlChar **ownerDes,
    			   xmlSchemaTypePtr ownerItem,
    			   xmlNodePtr node)
    {
        xmlChar *value = NULL;
        int res = 0;
       
        value = xmlNodeGetContent(node);
        /* 
        * 3.2.2.1 Lexical representation
        * An instance of a datatype that is defined as