diff options
Diffstat (limited to 'xmlschemas.c')
-rw-r--r-- | xmlschemas.c | 1871 |
1 files changed, 1228 insertions, 643 deletions
diff --git a/xmlschemas.c b/xmlschemas.c index afa7010..76bf3fd 100644 --- a/xmlschemas.c +++ b/xmlschemas.c @@ -66,9 +66,9 @@ /* #define ENABLE_PARTICLE_RESTRICTION 1 */ -#define DUMP_CONTENT_MODEL +/* #define ENABLE_REDEFINE */ -#define XML_SCHEMA_SAX_ENABLED +#define DUMP_CONTENT_MODEL #ifdef LIBXML_READER_ENABLED /* #define XML_SCHEMA_READER_ENABLED */ @@ -100,8 +100,6 @@ static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *) "attribute decl."; static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *) "attribute use"; -static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *) - "complex type"; static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *) "model group"; #if 0 @@ -199,19 +197,52 @@ typedef xmlSchemaAssemble *xmlSchemaAssemblePtr; typedef struct _xmlSchemaItemList xmlSchemaItemList; typedef xmlSchemaItemList *xmlSchemaItemListPtr; - struct _xmlSchemaItemList { void **items; /* used for dynamic addition of schemata */ int nbItems; /* used for dynamic addition of schemata */ int sizeItems; /* used for dynamic addition of schemata */ }; +/* +typedef struct _xmlSchemaItemListChain xmlSchemaItemListChain; +typedef xmlSchemaItemListChain xmlSchemaItemListChainPtr; +struct _xmlSchemaItemListChain { + xmlSchemaItemListChainPtr next; + xmlSchemaItemListPtr list; +} +*/ + +/* +typedef struct _xmlSchemaItemListChain xmlSchemaItemListChain; +typedef xmlSchemaItemListChain xmlSchemaItemListChainPtr; +struct _xmlSchemaItemListChain { + xmlSchemaItemListChainPtr next; + xmlSchemaItemListPtr list; +} +*/ + typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt; typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr; struct _xmlSchemaAbstractCtxt { int type; }; +/** + * xmlSchemaContainer: + */ +typedef struct _xmlSchemaContainer xmlSchemaContainer; +typedef xmlSchemaContainer *xmlSchemaContainerPtr; +struct _xmlSchemaContainer { + xmlSchemaItemListPtr typeDefs; + xmlSchemaItemListPtr attrDecls; + xmlSchemaItemListPtr elemDecls; + xmlSchemaItemListPtr attrGroupDefs; + xmlSchemaItemListPtr modelGroupDefs; + xmlSchemaItemListPtr notationDecls; + xmlSchemaItemListPtr annotations; + xmlSchemaItemListPtr locals; +}; + #define XML_SCHEMA_CTXT_PARSER 1 #define XML_SCHEMA_CTXT_VALIDATOR 2 @@ -224,8 +255,8 @@ struct _xmlSchemaParserCtxt { int nberrors; xmlStructuredErrorFunc serror; - xmlSchemaPtr topschema; /* The main schema */ - xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */ + /* 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, ... */ @@ -258,6 +289,8 @@ struct _xmlSchemaParserCtxt { int nbLocalImports; xmlHashTablePtr substGroups; int isS4S; + int isRedefine; + xmlSchemaContainerPtr compContainer; }; #define XML_SCHEMAS_ATTR_UNKNOWN 1 @@ -289,6 +322,26 @@ struct _xmlSchemaBasicItem { xmlSchemaTypeType type; }; +#define XML_SCHEMA_SCHEMA_REF_IMPORT 1 +#define XML_SCHEMA_SCHEMA_REF_INCLUDE 2 +#define XML_SCHEMA_SCHEMA_REF_REDEFINE 3 + +#define XML_SCHEMA_SCHEMA_REF_REL_CHILD 1 +#define XML_SCHEMA_SCHEMA_REF_REL_PARENT 2 +/** + * xmlSchemaSchemaRef: + * + * Used to create a graph of schema relationships. + */ +typedef struct _xmlSchemaSchemaRef xmlSchemaSchemaRef; +typedef xmlSchemaSchemaRef *xmlSchemaSchemaRefPtr; +struct _xmlSchemaSchemaRef { + xmlSchemaSchemaRefPtr next; + int type; /* E.g. XML_SCHEMA_SCHEMA_REF_IMPORT */ + int relation; + xmlSchemaPtr schema; +}; + /** * xmlSchemaAnnotItem: * @@ -462,6 +515,9 @@ typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr; struct _xmlSchemaPSVIIDCNode { xmlNodePtr node; xmlSchemaPSVIIDCKeyPtr *keys; + int nodeLine; + int nodeQNameID; + }; /** @@ -552,14 +608,17 @@ struct _xmlSchemaIDCMatcher { * Holds information of an element node. */ struct _xmlSchemaNodeInfo { - xmlNodePtr node; int nodeType; + xmlNodePtr node; + int nodeLine; const xmlChar *localName; const xmlChar *nsName; const xmlChar *value; xmlSchemaValPtr val; /* the pre-computed value if any */ xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */ + int flags; /* combination of node info flags */ + int valNeeded; int normVal; @@ -588,8 +647,9 @@ struct _xmlSchemaNodeInfo { typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo; typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr; struct _xmlSchemaAttrInfo { - xmlNodePtr node; int nodeType; + xmlNodePtr node; + int nodeLine; const xmlChar *localName; const xmlChar *nsName; const xmlChar *value; @@ -674,6 +734,7 @@ struct _xmlSchemaValidCtxt { int sizeAttrInfos; int skipDepth; + xmlSchemaItemListPtr nodeQNames; }; /* @@ -722,6 +783,11 @@ struct _xmlSchemaSubstGroup { static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, xmlNodePtr node); +#ifdef ENABLE_REDEFINE +static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, + xmlNodePtr node); +#endif static void xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl, xmlSchemaParserCtxtPtr ctxt, const xmlChar * name); @@ -796,6 +862,16 @@ xmlSchemaCompTypeToString(xmlSchemaTypeType type) return(BAD_CAST "model group (all)"); case XML_SCHEMA_TYPE_PARTICLE: return(BAD_CAST "particle"); + case XML_SCHEMA_TYPE_IDC_UNIQUE: + return(BAD_CAST "IDC (unique)"); + case XML_SCHEMA_TYPE_IDC_KEY: + return(BAD_CAST "IDC (key)"); + case XML_SCHEMA_TYPE_IDC_KEYREF: + return(BAD_CAST "IDC (keyref)"); + case XML_SCHEMA_TYPE_ANY: + return(BAD_CAST "wildcard (any)"); + case XML_SCHEMA_EXTRA_QNAMEREF: + return(BAD_CAST "[helper component] QName reference"); default: return(BAD_CAST "Not a schema component"); } @@ -1560,9 +1636,10 @@ xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt, * Handle a validation error */ static void -xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt, - int error, xmlNodePtr node, const char *msg, - const xmlChar *str1, const xmlChar *str2, const xmlChar *str3) +xmlSchemaErr3Line(xmlSchemaAbstractCtxtPtr ctxt, + int error, xmlNodePtr node, int line, const char *msg, + const xmlChar *str1, const xmlChar *str2, + const xmlChar *str3) { xmlStructuredErrorFunc schannel = NULL; xmlGenericErrorFunc channel = NULL; @@ -1571,7 +1648,6 @@ xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt, if (ctxt != NULL) { if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) { xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt; - int line = 0; const char *file = NULL; vctxt->nberrors++; @@ -1579,15 +1655,41 @@ xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt, channel = vctxt->error; schannel = vctxt->serror; data = vctxt->userData; - if ((node == NULL) && (vctxt->depth >= 0) && - (vctxt->inode != NULL)) { - node = vctxt->inode->node; - } - if ((node == NULL) && (vctxt->parserCtxt != NULL) && - (vctxt->parserCtxt->input != NULL)) { - file = vctxt->parserCtxt->input->filename; - line = vctxt->parserCtxt->input->line; - } + + /* + * Error node. If we specify a line number, then + * do not channel any node to the error function. + */ + if (line == 0) { + if ((node == NULL) && + (vctxt->depth >= 0) && + (vctxt->inode != NULL)) { + node = vctxt->inode->node; + } + /* + * Get filename and line if no node-tree. + */ + if ((node == NULL) && + (vctxt->parserCtxt != NULL) && + (vctxt->parserCtxt->input != NULL)) { + file = vctxt->parserCtxt->input->filename; + line = vctxt->parserCtxt->input->line; + } + } else { + /* + * Override the given node's (if any) position + * and channel only the given line number. + */ + node = NULL; + /* + * Get filename. + */ + if (vctxt->doc != NULL) + file = (const char *) vctxt->doc->URL; + else if ((vctxt->parserCtxt != NULL) && + (vctxt->parserCtxt->input != NULL)) + file = vctxt->parserCtxt->input->filename; + } __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV, error, XML_ERR_ERROR, file, line, @@ -1613,6 +1715,26 @@ xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt, } } +/** + * xmlSchemaErr3: + * @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 +xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt, + int error, xmlNodePtr node, const char *msg, + const xmlChar *str1, const xmlChar *str2, const xmlChar *str3) +{ + xmlSchemaErr3Line(actxt, error, node, 0, msg, str1, str2, str3); +} + static void xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt, int error, xmlNodePtr node, const char *msg, @@ -1699,9 +1821,11 @@ xmlSchemaFormatNodeForError(xmlChar ** msg, } static void -xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt, +xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt, const char *funcName, - const char *message) + const char *message, + const xmlChar *str1, + const xmlChar *str2) { xmlChar *msg = NULL; @@ -1713,16 +1837,35 @@ xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt, if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL, - (const char *) msg, NULL, NULL); + (const char *) msg, str1, str2); - else if (actxt->type == XML_SCHEMA_CTXT_PARSER) + else if (actxt->type == XML_SCHEMA_CTXT_PARSER) xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL, - (const char *) msg, NULL, NULL); + (const char *) msg, str1, str2); FREE_AND_NULL(msg) } static void +xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt, + const char *funcName, + const char *message) +{ + xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL); +} + +static void +xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt, + const char *funcName, + const char *message, + const xmlChar *str1, + const xmlChar *str2) +{ + xmlSchemaInternalErr2((xmlSchemaAbstractCtxtPtr) pctxt, funcName, message, + str1, str2); +} + +static void xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt, xmlParserErrors error, xmlNodePtr node, @@ -1741,6 +1884,30 @@ xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt, FREE_AND_NULL(msg) } +static void +xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt, + xmlParserErrors error, + xmlSchemaPSVIIDCNodePtr idcNode, + xmlSchemaTypePtr type ATTRIBUTE_UNUSED, + const char *message, + const xmlChar *str1, + const xmlChar *str2) +{ + xmlChar *msg = NULL, *qname = NULL; + + msg = xmlStrdup(BAD_CAST "Element '%s': "); + msg = xmlStrcat(msg, (const xmlChar *) message); + msg = xmlStrcat(msg, BAD_CAST ".\n"); + xmlSchemaErr3Line((xmlSchemaAbstractCtxtPtr) vctxt, + error, NULL, idcNode->nodeLine, (const char *) msg, + xmlSchemaFormatQName(&qname, + vctxt->nodeQNames->items[idcNode->nodeQNameID +1], + vctxt->nodeQNames->items[idcNode->nodeQNameID]), + str1, str2); + FREE_AND_NULL(qname); + FREE_AND_NULL(msg); +} + static int xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt, xmlNodePtr node) @@ -1879,7 +2046,7 @@ xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt, xmlChar *str = NULL, *msg = NULL; xmlChar *localName, *nsName; const xmlChar *cur, *end; - int i; + int i, is_not; xmlSchemaFormatNodeForError(&msg, actxt, node); msg = xmlStrcat(msg, (const xmlChar *) message); @@ -1898,6 +2065,16 @@ xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt, for (i = 0; i < nbval + nbneg; i++) { cur = values[i]; + if (cur == NULL) + continue; + if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') && + (cur[3] == ' ')) { + is_not = 1; + cur += 4; + str = xmlStrcat(str, BAD_CAST "##other"); + } else { + is_not = 0; + } /* * Get the local name. */ @@ -2088,6 +2265,7 @@ xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt, #define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg); #define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg); +#define PERROR_INT2(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) ctxt, func, msg); #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg); @@ -2537,8 +2715,10 @@ xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt, else xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL); } else { + msg = xmlStrcat(msg, BAD_CAST message); + msg = xmlStrcat(msg, BAD_CAST ".\n"); xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL, - "%s%s.\n", msg, BAD_CAST message, str1, str2, NULL); + (const char*) msg, str1, str2, NULL, NULL, NULL); } /* Cleanup. */ FREE_AND_NULL(msg) @@ -2711,7 +2891,7 @@ xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) } static xmlSchemaItemListPtr -xmlSchemaNewItemList(void) +xmlSchemaItemListCreate(void) { xmlSchemaItemListPtr ret; @@ -2725,6 +2905,98 @@ xmlSchemaNewItemList(void) return (ret); } +static void +xmlSchemaItemListClear(xmlSchemaItemListPtr list) +{ + if (list->items != NULL) { + xmlFree(list->items); + list->items = NULL; + } + list->nbItems = 0; + list->sizeItems = 0; +} + +static int +xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item) +{ + if (list->items == NULL) { + list->items = (void **) xmlMalloc( + 20 * sizeof(void *)); + if (list->items == NULL) { + xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); + return(-1); + } + list->sizeItems = 20; + } else if (list->sizeItems <= list->nbItems) { + list->sizeItems *= 2; + list->items = (void **) xmlRealloc(list->items, + list->sizeItems * sizeof(void *)); + if (list->items == NULL) { + xmlSchemaPErrMemory(NULL, "growing item list", NULL); + list->sizeItems = 0; + return(-1); + } + } + /* ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item; */ + list->items[list->nbItems++] = item; + return(0); +} + +/** + * xmlSchemaItemListFree: + * @annot: a schema type structure + * + * Deallocate a annotation structure + */ +static void +xmlSchemaItemListFree(xmlSchemaItemListPtr list) +{ + if (list == NULL) + return; + if (list->items != NULL) + xmlFree(list->items); + xmlFree(list); +} + +static xmlSchemaContainerPtr +xmlSchemaContainerCreate(void) +{ + xmlSchemaContainerPtr ret; + + ret = (xmlSchemaContainerPtr) xmlMalloc(sizeof(xmlSchemaContainer)); + if (ret == NULL) { + xmlSchemaPErrMemory(NULL, "allocating component container", + NULL); + return(NULL); + } + memset(ret, 0, sizeof(xmlSchemaContainer)); + return(ret); +} + +static void +xmlSchemaContainerFree(xmlSchemaContainerPtr cont) +{ + if (cont == NULL) + return; + if (cont->typeDefs != NULL) + xmlSchemaItemListFree(cont->typeDefs); + if (cont->attrDecls != NULL) + xmlSchemaItemListFree(cont->attrDecls); + if (cont->elemDecls != NULL) + xmlSchemaItemListFree(cont->elemDecls); + if (cont->attrGroupDefs != NULL) + xmlSchemaItemListFree(cont->attrGroupDefs); + if (cont->modelGroupDefs != NULL) + xmlSchemaItemListFree(cont->modelGroupDefs); + if (cont->notationDecls != NULL) + xmlSchemaItemListFree(cont->notationDecls); + if (cont->annotations != NULL) + xmlSchemaItemListFree(cont->annotations); + if (cont->locals != NULL) + xmlSchemaItemListFree(cont->locals); + xmlFree(cont); +} + /** * xmlSchemaAddElementSubstitutionMember: * @pctxt: a schema parser context @@ -2763,7 +3035,7 @@ xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt, NULL); return (-1); } - substGroup->members = xmlSchemaNewItemList(); + substGroup->members = xmlSchemaItemListCreate(); if (substGroup->members == NULL) { xmlFree(substGroup); return (-1); @@ -2835,22 +3107,6 @@ xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt, } /** - * xmlSchemaFreeItemList: - * @annot: a schema type structure - * - * Deallocate a annotation structure - */ -static void -xmlSchemaFreeItemList(xmlSchemaItemListPtr list) -{ - if (list == NULL) - return; - if (list->items != NULL) - xmlFree(list->items); - xmlFree(list); -} - -/** * xmlSchemaFreeAnnot: * @annot: a schema type structure * @@ -2861,7 +3117,17 @@ xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot) { if (annot == NULL) return; - xmlFree(annot); + if (annot->next == NULL) { + xmlFree(annot); + } else { + xmlSchemaAnnotPtr prev; + + do { + prev = annot; + annot = annot->next; + xmlFree(prev); + } while (annot != NULL); + } } /** @@ -3043,7 +3309,7 @@ xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item) if (item == NULL) return; if (item->members != NULL) - xmlSchemaFreeItemList(item->members); + xmlSchemaItemListFree(item->members); xmlFree(item); } @@ -3051,39 +3317,15 @@ static int xmlSchemaAddVolatile(xmlSchemaPtr schema, xmlSchemaBasicItemPtr item) { - xmlSchemaItemListPtr list; - if (schema->volatiles == NULL) { - schema->volatiles = (void *) xmlSchemaNewItemList(); + schema->volatiles = (void *) xmlSchemaItemListCreate(); if (schema->volatiles == NULL) { xmlSchemaPErrMemory(NULL, "allocating list of volatiles", NULL); return (-1); } } - list = (xmlSchemaItemListPtr) schema->volatiles; - if (list->items == NULL) { - list->items = (void **) xmlMalloc( - 20 * sizeof(xmlSchemaBasicItemPtr)); - if (list->items == NULL) { - xmlSchemaPErrMemory(NULL, - "allocating new volatile item buffer", NULL); - return (-1); - } - list->sizeItems = 20; - } else if (list->sizeItems <= list->nbItems) { - list->sizeItems *= 2; - list->items = (void **) xmlRealloc(list->items, - list->sizeItems * sizeof(xmlSchemaTypePtr)); - if (list->items == NULL) { - xmlSchemaPErrMemory(NULL, - "growing volatile item buffer", NULL); - list->sizeItems = 0; - return (-1); - } - } - ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item; - return (0); + return(xmlSchemaItemListAdd((xmlSchemaItemListPtr) schema->volatiles, item)); } /** @@ -3218,6 +3460,9 @@ xmlSchemaFreeType(xmlSchemaTypePtr type) } } if (type->type != XML_SCHEMA_TYPE_BASIC) { + /* + * TODO: Why is this restricted to non built-in types? + */ if (type->attributeUses != NULL) xmlSchemaFreeAttributeUseList(type->attributeUses); } @@ -3333,7 +3578,7 @@ xmlSchemaFreeVolatiles(xmlSchemaPtr schema) } } } - xmlSchemaFreeItemList(list); + xmlSchemaItemListFree(list); } } /** @@ -3894,35 +4139,19 @@ xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, */ static xmlSchemaElementPtr xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name, - const xmlChar * namespace) + const xmlChar * nsName) { xmlSchemaElementPtr ret; if ((name == NULL) || (schema == NULL)) return (NULL); - ret = xmlHashLookup2(schema->elemDecl, name, namespace); + ret = xmlHashLookup2(schema->elemDecl, name, nsName); 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. @@ -3963,18 +4192,25 @@ xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name, */ static xmlSchemaTypePtr xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name, - const xmlChar * namespace) + const xmlChar * nsName) { 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)) + ret = xmlHashLookup2(schema->typeDecl, name, nsName); + if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) { + if (ret->redef != NULL) { + /* + * Return the last redefinition. + */ + return(ret->redef); + } return (ret); + } } - ret = xmlSchemaGetPredefinedType(name, namespace); + ret = xmlSchemaGetPredefinedType(name, nsName); if (ret != NULL) return (ret); /* @@ -3994,14 +4230,14 @@ xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name, */ #ifdef DEBUG if (ret == NULL) { - if (namespace == NULL) + if (nsName == NULL) fprintf(stderr, "Unable to lookup type %s", name); else fprintf(stderr, "Unable to lookup type %s:%s", name, - namespace); + nsName); } #endif - return (ret); + return (NULL); } /** @@ -4548,8 +4784,8 @@ xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, */ static xmlSchemaTypePtr xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, - const xmlChar * name, const xmlChar * namespace, - xmlNodePtr node) + const xmlChar * name, const xmlChar * nsName, + xmlNodePtr node, int topLevel) { xmlSchemaTypePtr ret = NULL; int val; @@ -4557,12 +4793,6 @@ xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, 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) @@ -4576,25 +4806,37 @@ xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, memset(ret, 0, sizeof(xmlSchemaType)); ret->name = xmlDictLookup(ctxt->dict, name, -1); ret->redef = NULL; - val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret); + val = xmlHashAddEntry2(schema->typeDecl, name, nsName, 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); + if (! ctxt->isRedefine) { + xmlChar *str = NULL; + if (topLevel) { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_REDEFINED_TYPE, + NULL, NULL, node, + "A global type definition with the name '%s' does " + "already exist", + xmlSchemaFormatQName(&str, nsName, name)); + } else { + xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, + NULL, NULL, node, "Internal error: xmlSchemaAddType, " + "local type '%s' has a duplicate", + xmlSchemaFormatQName(&str, nsName, name)); + } xmlFree(ret); + FREE_AND_NULL(str); return (NULL); } else { xmlSchemaTypePtr prev; - prev = xmlHashLookup2(schema->typeDecl, name, namespace); + /* + * REDEFINE: Add a redefinition. + */ + TODO + prev = xmlHashLookup2(schema->typeDecl, name, nsName); if (prev == NULL) { - xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc, - XML_ERR_INTERNAL_ERROR, - "Internal error: xmlSchemaAddType, on type " - "'%s'.\n", - name, NULL); + PERROR_INT2("xmlSchemaAddType", "hash list didn't return " + "a type component, but should"); xmlFree(ret); return (NULL); } @@ -4977,7 +5219,7 @@ xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt, return (-1); if (!strchr((char *) value, ':')) { - ns = xmlSearchNs(attr->doc, attr->parent, 0); + ns = xmlSearchNs(attr->doc, attr->parent, NULL); if (ns) *uri = xmlDictLookup(ctxt->dict, ns->href, -1); else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) { @@ -8048,6 +8290,7 @@ xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, xmlNodePtr child = NULL; const xmlChar *attrValue = NULL; xmlAttrPtr attr; + int hasRestriction = 0; if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) return (NULL); @@ -8071,6 +8314,18 @@ xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, if (ctxt->isS4S) { xmlSchemaTypePtr biType; + if (ctxt->isRedefine) { + /* + * REDEFINE: Disallow redefinition of built-in-types. + * TODO: It seems that the spec does not say anything + * about this case. + */ + xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, + NULL, NULL, node, + "Redefinition of built-in simple types is not " + "supported", NULL); + return(NULL); + } biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs); if (biType != NULL) return (biType); @@ -8085,7 +8340,8 @@ xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, * Parse as local simple type definition. */ snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1); - type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node); + type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, + node, 0); if (type == NULL) return (NULL); type->node = node; @@ -8115,7 +8371,8 @@ xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, * * Note that attrValue is the value of the attribute "name" here. */ - type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node); + type = xmlSchemaAddType(ctxt, schema, attrValue, + schema->targetNamespace, node, 1); if (type == NULL) return (NULL); type->node = node; @@ -8186,9 +8443,10 @@ xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING, NULL, type, node, child, NULL, "(annotation?, (restriction | list | union))"); - } else if (IS_SCHEMA(child, "restriction")) { + } else if (IS_SCHEMA(child, "restriction")) { xmlSchemaParseRestriction(ctxt, schema, child, - XML_SCHEMA_TYPE_SIMPLE); + XML_SCHEMA_TYPE_SIMPLE); + hasRestriction = 1; child = child->next; } else if (IS_SCHEMA(child, "list")) { xmlSchemaParseList(ctxt, schema, child); @@ -8202,9 +8460,21 @@ xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, NULL, type, node, child, NULL, "(annotation?, (restriction | list | union))"); } + /* + * REDEFINE: SPEC src-redefine (5) + * "Within the [children], each <simpleType> must have a + * <restriction> among its [children] ... the ·actual value· of whose + * base [attribute] must be the same as the ·actual value· of its own + * name attribute plus target namespace;" + */ + if (topLevel && ctxt->isRedefine && (! hasRestriction)) { + xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, + NULL, NULL, node, "This is a redefinition, thus the " + "<simpleType> must have a <restriction> child", NULL); + } + ctxt->parentItem = oldParentItem; ctxt->ctxtType = oldCtxtType; - return (type); } @@ -8476,73 +8746,6 @@ xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root) } -/** - * xmlSchemaImportSchema - * - * @ctxt: a schema validation context - * @schemaLocation: an URI defining where to find the imported schema - * - * import a XML schema - * *WARNING* this interface is highly subject to change - * - * Returns -1 in case of error and 1 in case of success. - */ -#if 0 -static xmlSchemaImportPtr -xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt, - const xmlChar *schemaLocation) -{ - xmlSchemaImportPtr import; - xmlSchemaParserCtxtPtr newctxt; - - newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt)); - if (newctxt == NULL) { - xmlSchemaPErrMemory(ctxt, "allocating schema parser context", - NULL); - return (NULL); - } - memset(newctxt, 0, sizeof(xmlSchemaParserCtxt)); - /* Keep the same dictionnary for parsing, really */ - xmlDictReference(ctxt->dict); - newctxt->dict = ctxt->dict; - newctxt->includes = 0; - newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1); - - xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning, - ctxt->userData); - - import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport)); - if (import == NULL) { - xmlSchemaPErrMemory(NULL, "allocating imported schema", - NULL); - xmlSchemaFreeParserCtxt(newctxt); - return (NULL); - } - - memset(import, 0, sizeof(xmlSchemaImport)); - import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1); - import->schema = xmlSchemaParse(newctxt); - - if (import->schema == NULL) { - /* FIXME use another error enum here ? */ - xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL, - "Failed to import schema from location \"%s\".\n", - schemaLocation, NULL); - - xmlSchemaFreeParserCtxt(newctxt); - /* The schemaLocation is held by the dictionary. - if (import->schemaLocation != NULL) - xmlFree((xmlChar *)import->schemaLocation); - */ - xmlFree(import); - return NULL; - } - - xmlSchemaFreeParserCtxt(newctxt); - return import; -} -#endif - static void xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema) { @@ -8679,7 +8882,11 @@ xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt, xmlSchemaParseInclude(ctxt, schema, child); ctxt->includes--; } else if (IS_SCHEMA(child, "redefine")) { +#ifdef ENABLE_REDEFINE + xmlSchemaParseRedefine(ctxt, schema, child); +#else TODO +#endif } child = child->next; } @@ -8756,6 +8963,49 @@ xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt, return (ret); } +#ifdef ENABLE_REDEFINE +static xmlSchemaSchemaRefPtr +xmlSchemaSchemaRefCreate(void) +{ + xmlSchemaSchemaRefPtr ret; + + ret = (xmlSchemaSchemaRefPtr) xmlMalloc(sizeof(xmlSchemaSchemaRef)); + if (ret == NULL) { + xmlSchemaPErrMemory(NULL, "allocating schema reference", NULL); + return(NULL); + } + memset(ret, 0, sizeof(xmlSchemaSchemaRef)); + return(ret); +} + +static void +xmlSchemaSchemaRefFree(xmlSchemaSchemaRefPtr ref) +{ + xmlFree(ref); +} +#endif + +static xmlSchemaParserCtxtPtr +xmlSchemaParserCtxtCreate(void) +{ + xmlSchemaParserCtxtPtr ret; + + ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt)); + if (ret == NULL) { + xmlSchemaPErrMemory(NULL, "allocating schema parser context", + NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaParserCtxt)); + ret->type = XML_SCHEMA_CTXT_PARSER; + ret->compContainer = xmlSchemaContainerCreate(); + if (ret->compContainer == NULL) { + xmlSchemaFreeParserCtxt(ret); + return(NULL); + } + return(ret); +} + /** * xmlSchemaNewParserCtxtUseDict: * @URL: the location of the schema @@ -8770,18 +9020,10 @@ static xmlSchemaParserCtxtPtr xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict) { xmlSchemaParserCtxtPtr ret; - /* - if (URL == NULL) - return (NULL); - */ - ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt)); - if (ret == NULL) { - xmlSchemaPErrMemory(NULL, "allocating schema parser context", - NULL); + ret = xmlSchemaParserCtxtCreate(); + if (ret == NULL) return (NULL); - } - memset(ret, 0, sizeof(xmlSchemaParserCtxt)); ret->dict = dict; xmlDictReference(dict); if (URL != NULL) @@ -9053,14 +9295,17 @@ xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt, oldURL = pctxt->URL; /* TODO: Is using the doc->URL here correct? */ pctxt->URL = node->doc->URL; + oldLocImps = pctxt->localImports; pctxt->localImports = NULL; oldNumLocImps = pctxt->nbLocalImports; pctxt->nbLocalImports = 0; oldSizeLocImps = pctxt->sizeLocalImports; pctxt->sizeLocalImports = 0; + oldFlags = schema->flags; oldIsS4S = pctxt->isS4S; + xmlSchemaClearSchemaDefaults(schema); oldTNS = schema->targetNamespace; schema->targetNamespace = targetNamespace; @@ -9103,7 +9348,7 @@ xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt, * not valid and -1 in case of an internal error. */ static int -xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, +xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, xmlNodePtr node) { xmlNodePtr child; @@ -9114,7 +9359,7 @@ xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, xmlDocPtr doc; int ret = 0; - if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) return (-1); /* @@ -9126,12 +9371,12 @@ xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && (!xmlStrEqual(attr->name, BAD_CAST "namespace")) && (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) { - xmlSchemaPIllegalAttrErr(ctxt, + xmlSchemaPIllegalAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, NULL, attr); } } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { - xmlSchemaPIllegalAttrErr(ctxt, + xmlSchemaPIllegalAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, NULL, attr); } @@ -9140,26 +9385,26 @@ xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, /* * Extract and validate attributes. */ - if (xmlSchemaPValAttr(ctxt, NULL, NULL, node, + if (xmlSchemaPValAttr(pctxt, NULL, NULL, node, "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &namespaceName) != 0) { - xmlSchemaPSimpleTypeErr(ctxt, - XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI, + xmlSchemaPSimpleTypeErr(pctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, NULL, node, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL, namespaceName, NULL, NULL, NULL); - return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI); + return (pctxt->err); } - if (xmlSchemaPValAttr(ctxt, NULL, NULL, node, + if (xmlSchemaPValAttr(pctxt, NULL, NULL, node, "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0) { - xmlSchemaPSimpleTypeErr(ctxt, - XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI, + xmlSchemaPSimpleTypeErr(pctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, NULL, node, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL, namespaceName, NULL, NULL, NULL); - return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI); + return (pctxt->err); } /* * And now for the children... @@ -9173,8 +9418,8 @@ xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, child = child->next; } if (child != NULL) { - xmlSchemaPContentErr(ctxt, - XML_SCHEMAP_UNKNOWN_IMPORT_CHILD, + xmlSchemaPContentErr(pctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, NULL, NULL, node, child, NULL, "(annotation?)"); } @@ -9188,13 +9433,13 @@ xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, * targetNamespace [attribute]. */ if (xmlStrEqual(schema->targetNamespace, namespaceName)) { - xmlSchemaPCustomErr(ctxt, + xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_IMPORT_1_1, NULL, NULL, node, "The value of the attribute 'namespace' must not match " "the target namespace '%s' of the importing schema", schema->targetNamespace); - return (XML_SCHEMAP_SRC_IMPORT_1_1); + return (pctxt->err); } } else { /* @@ -9202,34 +9447,36 @@ xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, * <schema> must have a targetNamespace [attribute]. */ if (schema->targetNamespace == NULL) { - xmlSchemaPCustomErr(ctxt, + xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_IMPORT_1_2, NULL, NULL, node, "The attribute 'namespace' must be existent if " "the importing schema has no target namespace", NULL); - return (XML_SCHEMAP_SRC_IMPORT_1_2); + return (pctxt->err); } } /* * Add the namespace to the list of locally imported namespace. + * TODO: This could be removed if the schema-graph is ready. I.e. + * use the graph for this info instead. */ - if (ctxt->localImports == NULL) { - ctxt->localImports = (const xmlChar **) xmlMalloc(10 * + if (pctxt->localImports == NULL) { + pctxt->localImports = (const xmlChar **) xmlMalloc(10 * sizeof(const xmlChar*)); - ctxt->sizeLocalImports = 10; - ctxt->nbLocalImports = 0; - } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) { - ctxt->sizeLocalImports *= 2; - ctxt->localImports = (const xmlChar **) xmlRealloc( - (xmlChar **) ctxt->localImports, - ctxt->sizeLocalImports * sizeof(const xmlChar*)); + pctxt->sizeLocalImports = 10; + pctxt->nbLocalImports = 0; + } else if (pctxt->sizeLocalImports <= pctxt->nbLocalImports) { + pctxt->sizeLocalImports *= 2; + pctxt->localImports = (const xmlChar **) xmlRealloc( + (xmlChar **) pctxt->localImports, + pctxt->sizeLocalImports * sizeof(const xmlChar*)); } - ctxt->localImports[ctxt->nbLocalImports++] = namespaceName; + pctxt->localImports[pctxt->nbLocalImports++] = namespaceName; /* * Locate and aquire the schema document. */ - ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt, + ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) pctxt, schema, node, namespaceName, schemaLocation, &doc, &targetNamespace, 0); if (ret != 0) { @@ -9237,7 +9484,7 @@ xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, xmlFreeDoc(doc); return (ret); } else if (doc != NULL) { - xmlSchemaParseForImpInc(ctxt, schema, targetNamespace, + xmlSchemaParseForImpInc(pctxt, schema, targetNamespace, xmlDocGetRootElement(doc)); } @@ -9245,120 +9492,31 @@ xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, } /** - * xmlSchemaParseInclude: - * @ctxt: a schema validation context + * xmlSchemaParseIncludedDoc: + * @pctxt: a schema validation context * @schema: the schema being built * @node: a subtree containing XML Schema informations * - * parse a XML schema Include definition + * Parse an included (and to-be-redefined) XML schema document. * - * Returns -1 in case of error, 0 if the declaration is improper and - * 1 in case of success. + * Returns 0 on success, a positive error code on errors and + * -1 in case of an internal or API error. */ static int -xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, - xmlNodePtr node) +xmlSchemaParseIncludedDoc(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, + xmlNodePtr node, const xmlChar *schemaLocation, + int *located) { - xmlNodePtr child = NULL; - const xmlChar *schemaLocation, *targetNamespace; + const xmlChar *targetNamespace; xmlDocPtr doc = NULL; xmlNodePtr root = NULL; xmlSchemaIncludePtr include = NULL; int wasConvertingNs = 0; - xmlAttrPtr attr; xmlParserCtxtPtr parserCtxt; - - if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) - return (-1); - - /* - * Check for illegal attributes. - */ - attr = node->properties; - while (attr != NULL) { - if (attr->ns == NULL) { - if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && - (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) { - xmlSchemaPIllegalAttrErr(ctxt, - XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, - NULL, NULL, attr); - } - } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { - xmlSchemaPIllegalAttrErr(ctxt, - XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, - NULL, NULL, attr); - } - attr = attr->next; - } - /* - * Extract and validate attributes. - */ - xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id"); - /* - * Preliminary step, extract the URI-Reference for the include and - * make an URI from the base. - */ - attr = xmlSchemaGetPropNode(node, "schemaLocation"); - if (attr != NULL) { - xmlChar *base = NULL; - xmlChar *uri = NULL; - - if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr, - xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0) - goto exit_invalid; - base = xmlNodeGetBase(node->doc, node); - if (base == NULL) { - uri = xmlBuildURI(schemaLocation, node->doc->URL); - } else { - uri = xmlBuildURI(schemaLocation, base); - xmlFree(base); - } - if (uri == NULL) { - xmlSchemaPErr(ctxt, - node, - XML_SCHEMAP_INTERNAL, - "Internal error: xmlSchemaParseInclude, " - "could not build an URI from the schemaLocation.\n", - NULL, NULL); - goto exit_failure; - } - schemaLocation = xmlDictLookup(ctxt->dict, uri, -1); - xmlFree(uri); - } else { - xmlSchemaPMissingAttrErr(ctxt, - XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI, - NULL, node, "schemaLocation", NULL); - goto exit_invalid; - } - /* - * And now for the children... - */ - child = node->children; - while (IS_SCHEMA(child, "annotation")) { - /* - * the annotations here are simply discarded ... - * TODO: really? - */ - child = child->next; - } - if (child != NULL) { - xmlSchemaPContentErr(ctxt, - XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD, - NULL, NULL, node, child, NULL, - "(annotation?)"); - } - /* - * Report self-inclusion. - */ - if (xmlStrEqual(schemaLocation, ctxt->URL)) { - xmlSchemaPCustomErr(ctxt, - XML_SCHEMAP_SRC_INCLUDE, - NULL, NULL, node, - "The schema document '%s' cannot include itself.", - schemaLocation); - return (XML_SCHEMAP_SRC_INCLUDE); - } + if (located == NULL) + return(-1); + (*located) = 0; /* * Check if this one was already processed to avoid incorrect * duplicate component errors and infinite circular inclusion. @@ -9366,6 +9524,7 @@ xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, include = schema->includes; while (include != NULL) { if (xmlStrEqual(include->schemaLocation, schemaLocation)) { + (*located) = 1; targetNamespace = include->origTargetNamespace; if (targetNamespace == NULL) { /* @@ -9376,7 +9535,7 @@ xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, include->targetNamespace)) { goto check_targetNamespace; } - } else { + } else { goto check_targetNamespace; } } @@ -9393,60 +9552,50 @@ xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, goto exit_failure; } - if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) { + if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) { xmlDictFree(parserCtxt->dict); - parserCtxt->dict = ctxt->dict; + parserCtxt->dict = pctxt->dict; xmlDictReference(parserCtxt->dict); } doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation, NULL, SCHEMAS_PARSE_OPTIONS); xmlFreeParserCtxt(parserCtxt); - if (doc == NULL) { - /* - * TODO: It is not an error for the ·actual value· of the - * schemaLocation [attribute] to fail to resolve it all, in which - * case no corresponding inclusion is performed. - * So do we need a warning report here? - */ - xmlSchemaPCustomErr(ctxt, - XML_SCHEMAP_FAILED_LOAD, - NULL, NULL, node, - "Failed to load the document '%s' for inclusion", schemaLocation); - goto exit_invalid; + if (doc == NULL) { + goto exit_not_located; } - + (*located) = 1; /* * Then extract the root of the schema */ root = xmlDocGetRootElement(doc); if (root == NULL) { - xmlSchemaPCustomErr(ctxt, + xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_NOROOT, NULL, NULL, node, "The included document '%s' has no document " "element", schemaLocation); - goto exit_invalid; + goto exit_error; } /* * Remove all the blank text nodes */ - xmlSchemaCleanupDoc(ctxt, root); + xmlSchemaCleanupDoc(pctxt, root); /* * Check the schemas top level element */ if (!IS_SCHEMA(root, "schema")) { - xmlSchemaPCustomErr(ctxt, + xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_NOT_SCHEMA, NULL, NULL, node, "The document '%s' to be included is not a schema document", schemaLocation); - goto exit_invalid; + goto exit_error; } - targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace"); + targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace"); /* * 2.1 SII has a targetNamespace [attribute], and its ·actual * value· is identical to the ·actual value· of the targetNamespace @@ -9455,22 +9604,22 @@ xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, check_targetNamespace: if (targetNamespace != NULL) { if (schema->targetNamespace == NULL) { - xmlSchemaPCustomErr(ctxt, + xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_INCLUDE, NULL, NULL, node, "The target namespace of the included schema " "'%s' has to be absent, since the including schema " "has no target namespace", schemaLocation); - goto exit_invalid; + goto exit_error; } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) { - xmlSchemaPCustomErrExt(ctxt, + xmlSchemaPCustomErrExt(pctxt, XML_SCHEMAP_SRC_INCLUDE, NULL, NULL, node, "The target namespace '%s' of the included schema '%s' " "differs from '%s' of the including schema", targetNamespace, schemaLocation, schema->targetNamespace); - goto exit_invalid; + goto exit_error; } } else if (schema->targetNamespace != NULL) { if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) { @@ -9491,13 +9640,14 @@ check_targetNamespace: * the moment. * TODO: Check when the namespace in wildcards for chameleons needs * to be converted: before we built wildcard intersections or after. + * Answer: after! */ /* * Register the include. */ include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude)); if (include == NULL) { - xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL); + xmlSchemaPErrMemory(pctxt, "allocating include entry", NULL); goto exit_failure; } memset(include, 0, sizeof(xmlSchemaInclude)); @@ -9529,7 +9679,7 @@ check_targetNamespace: /* * Compile the included schema. */ - xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root); + xmlSchemaParseForImpInc(pctxt, schema, schema->targetNamespace, root); exit: /* @@ -9538,15 +9688,18 @@ exit: if ((wasConvertingNs == 0) && (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS)) schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS; - return (1); + return (0); -exit_invalid: +exit_error: if (doc != NULL) { if (include != NULL) include->doc = NULL; xmlFreeDoc(doc); } - return (ctxt->err); + return (pctxt->err); + +exit_not_located: + return(0); exit_failure: if (doc != NULL) { @@ -9557,6 +9710,259 @@ exit_failure: return (-1); } + +static int +xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaPtr schema, + xmlNodePtr node, + xmlChar **schemaLocation, + int isRedefine) +{ + xmlAttrPtr attr; + + if ((pctxt == NULL) || (schema == NULL) || (node == NULL) || + (schemaLocation == NULL)) + return (-1); + + *schemaLocation = NULL; + /* + * Check for illegal attributes. + * Applies for both <include> and <redefine>. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) { + xmlSchemaPIllegalAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, + NULL, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, + NULL, NULL, attr); + } + attr = attr->next; + } + xmlSchemaPValAttrID(pctxt, NULL, NULL, node, BAD_CAST "id"); + /* + * Preliminary step, extract the URI-Reference and make an URI + * from the base. + */ + /* + * Attribute "schemaLocation" is mandatory. + */ + attr = xmlSchemaGetPropNode(node, "schemaLocation"); + if (attr != NULL) { + xmlChar *base = NULL; + xmlChar *uri = NULL; + + if (xmlSchemaPValAttrNode(pctxt, NULL, NULL, attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), + (const xmlChar **) schemaLocation) != 0) + goto exit_error; + base = xmlNodeGetBase(node->doc, node); + if (base == NULL) { + uri = xmlBuildURI(*schemaLocation, node->doc->URL); + } else { + uri = xmlBuildURI(*schemaLocation, base); + xmlFree(base); + } + if (uri == NULL) { + PERROR_INT("xmlSchemaParseIncludeOrRedefine", + "could not build an URI from the schemaLocation") + goto exit_failure; + } + (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1); + xmlFree(uri); + } else { + xmlSchemaPMissingAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, "schemaLocation", NULL); + goto exit_error; + } + /* + * Report self-inclusion and self-redefinition. + */ + if (xmlStrEqual(*schemaLocation, pctxt->URL)) { + if (isRedefine) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_SRC_REDEFINE, + NULL, NULL, node, + "The schema document '%s' cannot redefine itself.", + *schemaLocation); + } else { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_SRC_INCLUDE, + NULL, NULL, node, + "The schema document '%s' cannot include itself.", + *schemaLocation); + } + goto exit_error; + } + + return(0); +exit_error: + return(pctxt->err); +exit_failure: + return(-1); +} + +static int +xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaPtr schema, + xmlNodePtr node, + int isRedefine) +{ + xmlNodePtr child = NULL; + const xmlChar *schemaLocation = NULL; + int res = 0, located = 0, hasRedefinitions = 0; + + if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) + return (-1); + + /* + * Parse attributes. Note that the returned schemaLocation will + * be already converted to an absolute URI. + */ + res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema, + node, (xmlChar **) (&schemaLocation), isRedefine); + if (res != 0) + return(res); + + /* + * Include the schema. + */ + res = xmlSchemaParseIncludedDoc(pctxt, schema, node, + schemaLocation, &located); + if (res != 0) + return(res); + + /* + * And now for the children... + */ + child = node->children; + + if (isRedefine) { + /* + * Parse (simpleType | complexType | group | attributeGroup))* + */ + pctxt->isRedefine = 1; + while (IS_SCHEMA(child, "annotation") || + IS_SCHEMA(child, "simpleType") || + IS_SCHEMA(child, "complexType") || + IS_SCHEMA(child, "group") || + IS_SCHEMA(child, "attributeGroup")) { + if (IS_SCHEMA(child, "annotation")) { + /* + * TODO: discard or not? + */ + } else if (IS_SCHEMA(child, "simpleType")) { + xmlSchemaParseSimpleType(pctxt, schema, child, 1); + } else if (IS_SCHEMA(child, "complexType")) { + xmlSchemaParseComplexType(pctxt, schema, child, 1); + hasRedefinitions = 1; + } else if (IS_SCHEMA(child, "group")) { + TODO + hasRedefinitions = 1; + /* xmlSchemaParseModelGroupDefinition(pctxt, schema, child); */ + } else if (IS_SCHEMA(child, "attributeGroup")) { + TODO + hasRedefinitions = 1; + /* xmlSchemaParseAttributeGroup(pctxt, schema, child, 1); */ + } + child = child->next; + } + pctxt->isRedefine = 0; + } else { + if (IS_SCHEMA(child, "annotation")) { + /* + * TODO: discard or not? + */ + child = child->next; + } + } + if (child != NULL) { + res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED; + if (isRedefine) { + xmlSchemaPContentErr(pctxt, + res, + NULL, NULL, node, child, NULL, + "(annotation | (simpleType | complexType | group | attributeGroup))*"); + } else { + xmlSchemaPContentErr(pctxt, + res, + NULL, NULL, node, child, NULL, + "(annotation?)"); + } + } + if (!located) { + /* + * TODO: This is all *not* yet OK, since we get a !located if the + * document was not an XML document as well :-( + */ + if (!isRedefine) { + /* + * WARNING for <include>: + * We will raise an error if the schema cannot be located + * for inclusions, since the that was the feedback from the + * schema people. I.e. the following spec piece will *not* be + * satisfied: + * SPEC src-include: "It is not an error for the ·actual value· of the + * schemaLocation [attribute] to fail to resolve it all, in which + * case no corresponding inclusion is performed. + * So do we need a warning report here?" + */ + res = XML_SCHEMAP_SRC_INCLUDE; + xmlSchemaPCustomErr(pctxt, res, + NULL, NULL, node, + "Failed to load the document '%s' for inclusion", + schemaLocation); + } else if (hasRedefinitions) { + /* + * SPEC src-redefine (1) + * "If there are any element information items among the [children] + * other than <annotation> then the ·actual value· of the + * schemaLocation [attribute] must successfully resolve." + * TODO: Ask the WG if a the location has to resolve here as well! + */ + res = XML_SCHEMAP_SRC_REDEFINE; + xmlSchemaPCustomErr(pctxt, res, + NULL, NULL, node, + "Failed to load the document '%s' for redefinition", + schemaLocation); + } + } + return(res); +} + +#ifdef ENABLE_REDEFINE +static int +xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, + xmlNodePtr node) +{ + int res; + + res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, 1); + if (res != 0) + return(res); + return(0); +} +#endif + +static int +xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, + xmlNodePtr node) +{ + int res; + + res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, 0); + if (res != 0) + return(res); + return(0); +} + /** * xmlSchemaParseModelGroup: * @ctxt: a schema validation context @@ -9805,22 +10211,54 @@ xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, */ xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id"); /* - * Attribute "base" - mandatory if inside a complex type. + * Attribute */ /* - * SPEC (1.2) "otherwise (<restriction> has no <simpleType> " + * Extract the base type. The "base" attribute is mandatory if inside + * a complex type or if redefining. + * + * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> " * among its [children]), the simple type definition which is * the {content type} of the type definition ·resolved· to by * the ·actual value· of the base [attribute]" */ - if ((xmlSchemaPValAttrQName(ctxt, schema, + if (xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL, node, "base", - &(type->baseNs), &(type->base)) == 0) && - (type->base == NULL) && - (type->type == XML_SCHEMA_TYPE_COMPLEX)) { - xmlSchemaPMissingAttrErr(ctxt, - XML_SCHEMAP_S4S_ATTR_MISSING, - type, node, "base", NULL); + &(type->baseNs), &(type->base)) == 0) + { + if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) { + xmlSchemaPMissingAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + type, node, "base", NULL); + } else if ((ctxt->isRedefine) && + (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) + { + if (type->base == NULL) { + xmlSchemaPMissingAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + type, node, "base", NULL); + } else if ((! xmlStrEqual(type->base, type->name)) || + (! xmlStrEqual(type->baseNs, type->targetNamespace))) + { + xmlChar *str1 = NULL, *str2 = NULL; + /* + * REDEFINE: SPEC src-redefine (5) + * "Within the [children], each <simpleType> must have a + * <restriction> among its [children] ... the ·actual value· of + * whose base [attribute] must be the same as the ·actual value· + * of its own name attribute plus target namespace;" + */ + xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE, + NULL, NULL, node, "This is a redefinition, but the QName " + "value '%s' of the 'base' attribute does not match the " + "type's designation '%s'", + xmlSchemaFormatQName(&str1, type->baseNs, type->base), + xmlSchemaFormatQName(&str1, type->targetNamespace, + type->name), NULL); + FREE_AND_NULL(str1); + FREE_AND_NULL(str2); + } + } } /* * And now for the children... @@ -10174,14 +10612,17 @@ xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, */ static int xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt, - xmlSchemaPtr schema, xmlNodePtr node) + xmlSchemaPtr schema, xmlNodePtr node, + int *hasRestrictionOrExtension) { xmlSchemaTypePtr type; xmlNodePtr child = NULL; xmlAttrPtr attr; - if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + if ((ctxt == NULL) || (schema == NULL) || (node == NULL) || + (hasRestrictionOrExtension == NULL)) return (-1); + *hasRestrictionOrExtension = 0; /* Not a component, don't create it. */ type = ctxt->ctxtType; type->contentType = XML_SCHEMA_CONTENT_SIMPLE; @@ -10218,13 +10659,27 @@ xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt, xmlSchemaParseAnnotation(ctxt, schema, child)); child = child->next; } + if (child == NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_MISSING, + NULL, NULL, node, NULL, NULL, + "(annotation?, (restriction | extension))"); + } + if (child == NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_MISSING, + NULL, NULL, node, NULL, NULL, + "(annotation?, (restriction | extension))"); + } if (IS_SCHEMA(child, "restriction")) { xmlSchemaParseRestriction(ctxt, schema, child, XML_SCHEMA_TYPE_SIMPLE_CONTENT); + (*hasRestrictionOrExtension) = 1; child = child->next; } else if (IS_SCHEMA(child, "extension")) { xmlSchemaParseExtension(ctxt, schema, child, XML_SCHEMA_TYPE_SIMPLE_CONTENT); + (*hasRestrictionOrExtension) = 1; child = child->next; } if (child != NULL) { @@ -10249,14 +10704,17 @@ xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt, */ static int xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt, - xmlSchemaPtr schema, xmlNodePtr node) + xmlSchemaPtr schema, xmlNodePtr node, + int *hasRestrictionOrExtension) { xmlSchemaTypePtr type; xmlNodePtr child = NULL; xmlAttrPtr attr; - if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + if ((ctxt == NULL) || (schema == NULL) || (node == NULL) || + (hasRestrictionOrExtension == NULL)) return (-1); + *hasRestrictionOrExtension = 0; /* Not a component, don't create it. */ type = ctxt->ctxtType; /* @@ -10298,13 +10756,27 @@ xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt, xmlSchemaParseAnnotation(ctxt, schema, child)); child = child->next; } + if (child == NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_MISSING, + NULL, NULL, node, NULL, + NULL, "(annotation?, (restriction | extension))"); + } + if (child == NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_MISSING, + NULL, NULL, node, NULL, + NULL, "(annotation?, (restriction | extension))"); + } if (IS_SCHEMA(child, "restriction")) { xmlSchemaParseRestriction(ctxt, schema, child, XML_SCHEMA_TYPE_COMPLEX_CONTENT); + (*hasRestrictionOrExtension) = 1; child = child->next; } else if (IS_SCHEMA(child, "extension")) { xmlSchemaParseExtension(ctxt, schema, child, XML_SCHEMA_TYPE_COMPLEX_CONTENT); + (*hasRestrictionOrExtension) = 1; child = child->next; } if (child != NULL) { @@ -10336,9 +10808,8 @@ xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, const xmlChar *oldcontainer, *name = NULL; xmlAttrPtr attr; const xmlChar *attrValue; - xmlChar *des = NULL; /* The reported designation. */ char buf[40]; - int final = 0, block = 0; + int final = 0, block = 0, hasRestrictionOrExtension = 0; if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) @@ -10353,10 +10824,10 @@ xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL); return (NULL); } else if (xmlSchemaPValAttrNode(ctxt, - (xmlChar **) &xmlSchemaElemDesCT, NULL, attr, + NULL, NULL, attr, xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { return (NULL); - } + } } if (topLevel == 0) { @@ -10364,7 +10835,8 @@ xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, * Parse as local complex type definition. */ snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1); - type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node); + type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, + node, 0); if (type == NULL) return (NULL); name = type->name; @@ -10377,7 +10849,8 @@ xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, /* * Parse as global complex type definition. */ - type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node); + type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, + node, 1); if (type == NULL) return (NULL); type->node = node; @@ -10401,7 +10874,7 @@ xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, /* * Attribute "mixed". */ - if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type, + if (xmlSchemaPGetBoolNodeValue(ctxt, NULL, type, (xmlNodePtr) attr)) type->flags |= XML_SCHEMAS_TYPE_MIXED; } else if (topLevel) { @@ -10414,7 +10887,7 @@ xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, /* * Attribute "abstract". */ - if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type, + if (xmlSchemaPGetBoolNodeValue(ctxt, NULL, type, (xmlNodePtr) attr)) type->flags |= XML_SCHEMAS_TYPE_ABSTRACT; } else if (xmlStrEqual(attr->name, BAD_CAST "final")) { @@ -10458,17 +10931,17 @@ xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, } else { xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, - &des, type, attr); + NULL, type, attr); } } else { xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, - &des, type, attr); + NULL, type, attr); } } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, - &des, type, attr); + NULL, type, attr); } attr = attr->next; } @@ -10503,20 +10976,28 @@ xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, ctxt->ctxtType = type; if (IS_SCHEMA(child, "simpleContent")) { /* + * <complexType><simpleContent>... * 3.4.3 : 2.2 * Specifying mixed='true' when the <simpleContent> * alternative is chosen has no effect */ if (type->flags & XML_SCHEMAS_TYPE_MIXED) type->flags ^= XML_SCHEMAS_TYPE_MIXED; - xmlSchemaParseSimpleContent(ctxt, schema, child); + xmlSchemaParseSimpleContent(ctxt, schema, child, + &hasRestrictionOrExtension); child = child->next; } else if (IS_SCHEMA(child, "complexContent")) { + /* + * <complexType><complexContent>... + */ type->contentType = XML_SCHEMA_CONTENT_EMPTY; - xmlSchemaParseComplexContent(ctxt, schema, child); + xmlSchemaParseComplexContent(ctxt, schema, child, + &hasRestrictionOrExtension); child = child->next; } else { /* + * E.g <complexType><sequence>... or <complexType><attribute>... etc. + * * SPEC * "...the third alternative (neither <simpleContent> nor * <complexContent>) is chosen. This case is understood as shorthand @@ -10563,12 +11044,20 @@ xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, if (child != NULL) { xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, - &des, type, node, child, + NULL, type, node, child, NULL, "(annotation?, (simpleContent | complexContent | " "((group | all | choice | sequence)?, ((attribute | " "attributeGroup)*, anyAttribute?))))"); } - FREE_AND_NULL(des); + /* + * REDEFINE: SPEC src-redefine (5) + */ + if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) { + xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, + NULL, NULL, node, "This is a redefinition, thus the " + "<complexType> must have a <restriction> or <extension> " + "grand-child", NULL); + } ctxt->container = oldcontainer; ctxt->ctxtType = ctxtType; return (type); @@ -10605,6 +11094,9 @@ xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) ctxt->isS4S = 0; if (IS_SCHEMA(node, "schema")) { xmlSchemaImportPtr import; +#ifdef ENABLE_REDEFINE + xmlSchemaSchemaRefPtr ref; +#endif schema = xmlSchemaNewSchema(ctxt); if (schema == NULL) @@ -10632,14 +11124,23 @@ xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) * if all schemata are constructed dynamically fired by the * instance or if the schema to be used was specified via * the API. + * TODO */ +#ifdef ENABLE_REDEFINE + ref = xmlSchemaSchemaRefCreate(); + if (ref == NULL) { + xmlSchemaFree(schema); + schema = NULL; + return NULL; + } + ref->schema = schema; +#endif + import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), schema->targetNamespace); if (import == NULL) { - xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT, - NULL, NULL, (xmlNodePtr) ctxt->doc, - "Internal error: xmlSchemaParseSchema, " - "failed to add an import entry", NULL); + xmlSchemaPInternalErr(ctxt, "xmlSchemaParseSchema", + "failed to add an import entry", NULL, NULL); xmlSchemaFree(schema); schema = NULL; return (NULL); @@ -10764,14 +11265,9 @@ xmlSchemaNewParserCtxt(const char *URL) if (URL == NULL) return (NULL); - ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt)); - if (ret == NULL) { - xmlSchemaPErrMemory(NULL, "allocating schema parser context", - NULL); - return (NULL); - } - memset(ret, 0, sizeof(xmlSchemaParserCtxt)); - ret->type = XML_SCHEMA_CTXT_PARSER; + ret = xmlSchemaParserCtxtCreate(); + if (ret == NULL) + return(NULL); ret->dict = xmlDictCreate(); ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1); ret->includes = 0; @@ -10795,17 +11291,12 @@ xmlSchemaNewMemParserCtxt(const char *buffer, int size) if ((buffer == NULL) || (size <= 0)) return (NULL); - - ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt)); - if (ret == NULL) { - xmlSchemaPErrMemory(NULL, "allocating schema parser context", - NULL); - return (NULL); - } - memset(ret, 0, sizeof(xmlSchemaParserCtxt)); + ret = xmlSchemaParserCtxtCreate(); + if (ret == NULL) + return(NULL); ret->buffer = buffer; ret->size = size; - ret->dict = xmlDictCreate(); + ret->dict = xmlDictCreate(); return (ret); } @@ -10825,14 +11316,9 @@ xmlSchemaNewDocParserCtxt(xmlDocPtr doc) if (doc == NULL) return (NULL); - - ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt)); - if (ret == NULL) { - xmlSchemaPErrMemory(NULL, "allocating schema parser context", - NULL); - return (NULL); - } - memset(ret, 0, sizeof(xmlSchemaParserCtxt)); + ret = xmlSchemaParserCtxtCreate(); + if (ret == NULL) + return(NULL); ret->doc = doc; ret->dict = xmlDictCreate(); /* The application has responsibility for the document */ @@ -10866,6 +11352,7 @@ xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt) if (ctxt->substGroups != NULL) xmlHashFree(ctxt->substGroups, (xmlHashDeallocator) xmlSchemaFreeSubstGroup); + xmlSchemaContainerFree(ctxt->compContainer); xmlDictFree(ctxt->dict); xmlFree(ctxt); } @@ -10878,11 +11365,10 @@ xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt) static void xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt, - xmlSchemaParticlePtr particle) + xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end) { - xmlAutomataStatePtr start; + xmlAutomataStatePtr start, tmp; xmlSchemaElementPtr elemDecl, member; - xmlAutomataStatePtr end; xmlSchemaSubstGroupPtr substGroup; int i; @@ -10891,7 +11377,8 @@ xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt, * Wrap the substitution group with a CHOICE. */ start = pctxt->state; - end = xmlAutomataNewState(pctxt->am); + if (end == NULL) + end = xmlAutomataNewState(pctxt->am); substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl); if (substGroup == NULL) { xmlSchemaPErr(pctxt, GET_NODE(particle), @@ -10901,7 +11388,22 @@ xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt, "available.\n", elemDecl->name, NULL); return; } - if (particle->maxOccurs == 1) { + if (counter >= 0) { + /* + * NOTE that we put the declaration in, even if it's abstract, + */ + tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter); + xmlAutomataNewTransition2(pctxt->am, tmp, end, + elemDecl->name, elemDecl->targetNamespace, elemDecl); + /* + * Add subst. group members. + */ + for (i = 0; i < substGroup->members->nbItems; i++) { + member = (xmlSchemaElementPtr) substGroup->members->items[i]; + xmlAutomataNewTransition2(pctxt->am, tmp, end, + member->name, member->targetNamespace, member); + } + } else if (particle->maxOccurs == 1) { /* * NOTE that we put the declaration in, even if it's abstract, */ @@ -10914,14 +11416,12 @@ xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt, */ for (i = 0; i < substGroup->members->nbItems; i++) { member = (xmlSchemaElementPtr) substGroup->members->items[i]; - xmlAutomataNewEpsilon(pctxt->am, - xmlAutomataNewTransition2(pctxt->am, - start, NULL, - member->name, member->targetNamespace, member), - end); + tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL, + member->name, member->targetNamespace, + 1, 1, member); + xmlAutomataNewEpsilon(pctxt->am, tmp, end); } } else { - int counter; xmlAutomataStatePtr hop; int maxOccurs = particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1; @@ -10938,8 +11438,8 @@ xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt, elemDecl->name, elemDecl->targetNamespace, elemDecl), hop); /* - * Add subst. group members. - */ + * Add subst. group members. + */ for (i = 0; i < substGroup->members->nbItems; i++) { member = (xmlSchemaElementPtr) substGroup->members->items[i]; xmlAutomataNewEpsilon(pctxt->am, @@ -10965,7 +11465,7 @@ xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt, /* * Substitution groups. */ - xmlSchemaBuildContentModelForSubstGroup(ctxt, particle); + xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL); } else { xmlSchemaElementPtr elemDecl; xmlAutomataStatePtr start; @@ -10977,8 +11477,9 @@ xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt, if (particle->maxOccurs == 1) { start = ctxt->state; ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, - elemDecl->name, elemDecl->targetNamespace, elemDecl); - } else if ((particle->maxOccurs >= UNBOUNDED) && (particle->minOccurs < 2)) { + elemDecl->name, elemDecl->targetNamespace, elemDecl); + } else if ((particle->maxOccurs >= UNBOUNDED) && + (particle->minOccurs < 2)) { /* Special case. */ start = ctxt->state; ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, @@ -11013,22 +11514,16 @@ xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt, * Generate the automata sequence needed for that type */ static void -xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt, +xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt, xmlSchemaParticlePtr particle, const xmlChar * name) { if (particle == NULL) { - xmlSchemaPErr(ctxt, NULL, - XML_SCHEMAP_INTERNAL, - "Internal error: xmlSchemaBuildAContentModel, " - "particle is NULL.\n", NULL, NULL); + PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL"); return; } if (particle->children == NULL) { - xmlSchemaPErr(ctxt, GET_NODE(particle), - XML_SCHEMAP_INTERNAL, - "Internal error: xmlSchemaBuildAContentModel, " - "no term on particle.\n", NULL, NULL); + PERROR_INT("xmlSchemaBuildAContentModel", "no term on particle"); return; } @@ -11040,8 +11535,8 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt, wild = (xmlSchemaWildcardPtr) particle->children; - start = ctxt->state; - end = xmlAutomataNewState(ctxt->am); + start = pctxt->state; + end = xmlAutomataNewState(pctxt->am); if (particle->maxOccurs == 1) { if (wild->any == 1) { @@ -11050,43 +11545,32 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt, * * 1. the {"*", "*"} for elements in a namespace. */ - ctxt->state = - xmlAutomataNewTransition2(ctxt->am, + pctxt->state = + xmlAutomataNewTransition2(pctxt->am, start, NULL, BAD_CAST "*", BAD_CAST "*", wild); - xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); /* * 2. the {"*"} for elements in no namespace. */ - ctxt->state = - xmlAutomataNewTransition2(ctxt->am, + pctxt->state = + xmlAutomataNewTransition2(pctxt->am, start, NULL, BAD_CAST "*", NULL, wild); - xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); } else if (wild->nsSet != NULL) { ns = wild->nsSet; do { - ctxt->state = start; - ctxt->state = xmlAutomataNewTransition2(ctxt->am, - ctxt->state, NULL, BAD_CAST "*", ns->value, wild); - xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end); + pctxt->state = start; + pctxt->state = xmlAutomataNewTransition2(pctxt->am, + pctxt->state, NULL, BAD_CAST "*", ns->value, wild); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); ns = ns->next; } while (ns != NULL); } else if (wild->negNsSet != NULL) { - - /* - * Lead nodes with the negated namespace to the sink-state - * {"*", "##other"}. - */ - ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, - BAD_CAST "*", wild->negNsSet->value, wild); - /* - * Open a door for nodes with any other namespace - * {"*", "*"} - */ - ctxt->state = xmlAutomataNewTransition2(ctxt->am, - start, NULL, BAD_CAST "*", BAD_CAST "*", wild); - xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end); + pctxt->state = xmlAutomataNewNegTrans(pctxt->am, + start, end, BAD_CAST "*", wild->negNsSet->value, + wild); } } else { int counter; @@ -11096,48 +11580,43 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt, int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1; - counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs); - hop = xmlAutomataNewState(ctxt->am); + counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs); + hop = xmlAutomataNewState(pctxt->am); if (wild->any == 1) { - ctxt->state = - xmlAutomataNewTransition2(ctxt->am, + pctxt->state = + xmlAutomataNewTransition2(pctxt->am, start, NULL, BAD_CAST "*", BAD_CAST "*", wild); - xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop); - ctxt->state = - xmlAutomataNewTransition2(ctxt->am, + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); + pctxt->state = + xmlAutomataNewTransition2(pctxt->am, start, NULL, BAD_CAST "*", NULL, wild); - xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); } else if (wild->nsSet != NULL) { ns = wild->nsSet; do { - ctxt->state = - xmlAutomataNewTransition2(ctxt->am, + pctxt->state = + xmlAutomataNewTransition2(pctxt->am, start, NULL, BAD_CAST "*", ns->value, wild); - xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); ns = ns->next; } while (ns != NULL); } else if (wild->negNsSet != NULL) { - xmlAutomataStatePtr deadEnd; - - deadEnd = xmlAutomataNewState(ctxt->am); - ctxt->state = xmlAutomataNewTransition2(ctxt->am, - start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild); - ctxt->state = xmlAutomataNewTransition2(ctxt->am, - start, NULL, BAD_CAST "*", BAD_CAST "*", wild); - xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop); + pctxt->state = xmlAutomataNewNegTrans(pctxt->am, + start, hop, BAD_CAST "*", wild->negNsSet->value, + wild); } - xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter); - xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter); + xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter); + xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter); } if (particle->minOccurs == 0) { - xmlAutomataNewEpsilon(ctxt->am, start, end); + xmlAutomataNewEpsilon(pctxt->am, start, end); } - ctxt->state = end; + pctxt->state = end; break; } case XML_SCHEMA_TYPE_ELEMENT: - xmlSchemaBuildContentModelForElement(ctxt, particle); + xmlSchemaBuildContentModelForElement(pctxt, particle); break; case XML_SCHEMA_TYPE_SEQUENCE:{ xmlSchemaTreeItemPtr sub; @@ -11149,50 +11628,61 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt, if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) { sub = particle->children->children; while (sub != NULL) { - xmlSchemaBuildAContentModel(ctxt, + xmlSchemaBuildAContentModel(pctxt, (xmlSchemaParticlePtr) sub, name); sub = sub->next; } } else { - xmlAutomataStatePtr oldstate = ctxt->state; + xmlAutomataStatePtr oldstate = pctxt->state; if (particle->maxOccurs >= UNBOUNDED) { if (particle->minOccurs > 1) { xmlAutomataStatePtr tmp; int counter; - ctxt->state = xmlAutomataNewEpsilon(ctxt->am, + pctxt->state = xmlAutomataNewEpsilon(pctxt->am, oldstate, NULL); - oldstate = ctxt->state; + oldstate = pctxt->state; - counter = xmlAutomataNewCounter(ctxt->am, + counter = xmlAutomataNewCounter(pctxt->am, particle->minOccurs - 1, UNBOUNDED); sub = particle->children->children; while (sub != NULL) { - xmlSchemaBuildAContentModel(ctxt, + xmlSchemaBuildAContentModel(pctxt, (xmlSchemaParticlePtr) sub, name); sub = sub->next; } - tmp = ctxt->state; - xmlAutomataNewCountedTrans(ctxt->am, tmp, + tmp = pctxt->state; + xmlAutomataNewCountedTrans(pctxt->am, tmp, oldstate, counter); - ctxt->state = - xmlAutomataNewCounterTrans(ctxt->am, tmp, + pctxt->state = + xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL, counter); } else { + pctxt->state = xmlAutomataNewEpsilon(pctxt->am, + oldstate, NULL); + oldstate = pctxt->state; + sub = particle->children->children; while (sub != NULL) { - xmlSchemaBuildAContentModel(ctxt, + xmlSchemaBuildAContentModel(pctxt, (xmlSchemaParticlePtr) sub, name); sub = sub->next; } - xmlAutomataNewEpsilon(ctxt->am, ctxt->state, + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, oldstate); + /* + * epsilon needed to block previous trans from + * being allowed to enter back from another + * construct + */ + pctxt->state = xmlAutomataNewEpsilon(pctxt->am, + pctxt->state, NULL); if (particle->minOccurs == 0) { - xmlAutomataNewEpsilon(ctxt->am, - oldstate, ctxt->state); + xmlAutomataNewEpsilon(pctxt->am, + oldstate, pctxt->state); } } } else if ((particle->maxOccurs > 1) @@ -11200,40 +11690,40 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt, xmlAutomataStatePtr tmp; int counter; - ctxt->state = xmlAutomataNewEpsilon(ctxt->am, + pctxt->state = xmlAutomataNewEpsilon(pctxt->am, oldstate, NULL); - oldstate = ctxt->state; + oldstate = pctxt->state; - counter = xmlAutomataNewCounter(ctxt->am, + counter = xmlAutomataNewCounter(pctxt->am, particle->minOccurs - 1, particle->maxOccurs - 1); sub = particle->children->children; while (sub != NULL) { - xmlSchemaBuildAContentModel(ctxt, + xmlSchemaBuildAContentModel(pctxt, (xmlSchemaParticlePtr) sub, name); sub = sub->next; } - tmp = ctxt->state; - xmlAutomataNewCountedTrans(ctxt->am, + tmp = pctxt->state; + xmlAutomataNewCountedTrans(pctxt->am, tmp, oldstate, counter); - ctxt->state = - xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL, + pctxt->state = + xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL, counter); if (particle->minOccurs == 0) { - xmlAutomataNewEpsilon(ctxt->am, - oldstate, ctxt->state); + xmlAutomataNewEpsilon(pctxt->am, + oldstate, pctxt->state); } } else { sub = particle->children->children; while (sub != NULL) { - xmlSchemaBuildAContentModel(ctxt, + xmlSchemaBuildAContentModel(pctxt, (xmlSchemaParticlePtr) sub, name); sub = sub->next; } if (particle->minOccurs == 0) { - xmlAutomataNewEpsilon(ctxt->am, oldstate, - ctxt->state); + xmlAutomataNewEpsilon(pctxt->am, oldstate, + pctxt->state); } } } @@ -11243,8 +11733,8 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTreeItemPtr sub; xmlAutomataStatePtr start, end; - start = ctxt->state; - end = xmlAutomataNewState(ctxt->am); + start = pctxt->state; + end = xmlAutomataNewState(pctxt->am); /* * iterate over the subtypes and remerge the end with an @@ -11253,15 +11743,15 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt, if (particle->maxOccurs == 1) { sub = particle->children->children; while (sub != NULL) { - ctxt->state = start; - xmlSchemaBuildAContentModel(ctxt, + pctxt->state = start; + xmlSchemaBuildAContentModel(pctxt, (xmlSchemaParticlePtr) sub, name); - xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); sub = sub->next; } } else { int counter; - xmlAutomataStatePtr hop; + xmlAutomataStatePtr hop, base; int maxOccurs = particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1; int minOccurs = @@ -11272,27 +11762,26 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt, * which went through the choice. */ counter = - xmlAutomataNewCounter(ctxt->am, minOccurs, - maxOccurs); - hop = xmlAutomataNewState(ctxt->am); + xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs); + hop = xmlAutomataNewState(pctxt->am); + base = xmlAutomataNewState(pctxt->am); sub = particle->children->children; while (sub != NULL) { - ctxt->state = start; - xmlSchemaBuildAContentModel(ctxt, + pctxt->state = base; + xmlSchemaBuildAContentModel(pctxt, (xmlSchemaParticlePtr) sub, name); - xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); sub = sub->next; } - xmlAutomataNewCountedTrans(ctxt->am, hop, start, - counter); - xmlAutomataNewCounterTrans(ctxt->am, hop, end, - counter); + xmlAutomataNewEpsilon(pctxt->am, start, base); + xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter); + xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter); } if (particle->minOccurs == 0) { - xmlAutomataNewEpsilon(ctxt->am, start, end); + xmlAutomataNewEpsilon(pctxt->am, start, end); } - ctxt->state = end; + pctxt->state = end; break; } case XML_SCHEMA_TYPE_ALL:{ @@ -11304,16 +11793,14 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt, sub = (xmlSchemaParticlePtr) particle->children->children; if (sub == NULL) break; - start = ctxt->state; + start = pctxt->state; while (sub != NULL) { - ctxt->state = start; + pctxt->state = start; elemDecl = (xmlSchemaElementPtr) sub->children; if (elemDecl == NULL) { - xmlSchemaPErr(ctxt, NULL, - XML_SCHEMAP_INTERNAL, - "Internal error: xmlSchemaBuildAContentModel, " - "<element> particle a NULL term.\n", NULL, NULL); + PERROR_INT("xmlSchemaBuildAContentModel", + "<element> particle has no term"); return; }; /* @@ -11322,37 +11809,59 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt, * already ensured during the parse of the content of * <all>. */ - if ((sub->minOccurs == 1) && - (sub->maxOccurs == 1)) { - xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state, - ctxt->state, - elemDecl->name, - elemDecl->targetNamespace, - 1, 1, elemDecl); - } else if ((sub->minOccurs == 0) && - (sub->maxOccurs == 1)) { - - xmlAutomataNewCountTrans2(ctxt->am, ctxt->state, - ctxt->state, - elemDecl->name, - elemDecl->targetNamespace, - 0, - 1, - elemDecl); - } + if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) { + int counter; + + /* + * This is an abstract group, we need to share + * the same counter for all the element transitions + * derived from the group + */ + counter = xmlAutomataNewCounter(pctxt->am, + sub->minOccurs, sub->maxOccurs); + xmlSchemaBuildContentModelForSubstGroup(pctxt, + sub, counter, pctxt->state); + } else { + if ((sub->minOccurs == 1) && + (sub->maxOccurs == 1)) { + xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state, + pctxt->state, + elemDecl->name, + elemDecl->targetNamespace, + 1, 1, elemDecl); + } else if ((sub->minOccurs == 0) && + (sub->maxOccurs == 1)) { + + xmlAutomataNewCountTrans2(pctxt->am, pctxt->state, + pctxt->state, + elemDecl->name, + elemDecl->targetNamespace, + 0, + 1, + elemDecl); + } + } sub = (xmlSchemaParticlePtr) sub->next; } lax = particle->minOccurs == 0; - ctxt->state = - xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax); + pctxt->state = + xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax); break; } + case XML_SCHEMA_TYPE_GROUP: + /* + * If we hit a model group definition, then this means that + * it was empty, thus was not substituted for the containing + * model group. Just do nothing in this case. + */ + break; default: - xmlGenericError(xmlGenericErrorContext, - "Internal error: xmlSchemaBuildAContentModel, found " - "unexpected term of type %d in content model of complex " - "type '%s'.\n", - particle->children->type, name); + xmlSchemaPInternalErr(pctxt, "xmlSchemaBuildAContentModel", + "found unexpected term of type '%s' in content model of complex " + "type '%s'", + xmlSchemaCompTypeToString(particle->children->type), name); + xmlGenericError(xmlGenericErrorContext, + "Unexpected type: %d\n", particle->children->type); return; } } @@ -12748,7 +13257,7 @@ xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt, * declaration}'s {value constraint} . */ xmlSchemaGetEffectiveValueConstraint(base->attr, - &effFixed, &bEffValue, 0); + &effFixed, &bEffValue, NULL); /* * 2.1.3 ... one of the following must be true * @@ -12760,7 +13269,7 @@ xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt, const xmlChar *rEffValue = NULL; xmlSchemaGetEffectiveValueConstraint(base->attr, - &effFixed, &rEffValue, 0); + &effFixed, &rEffValue, NULL); /* * 2.1.3.2 R's ·effective value constraint· is * fixed with the same string as B's. @@ -13258,8 +13767,14 @@ xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item, ((item->type != XML_SCHEMA_TYPE_COMPLEX) && (item->type != XML_SCHEMA_TYPE_SIMPLE))) return; - xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType); - + if (item->redef != NULL) { + xmlSchemaTypePtr cur = item; + do { + xmlSchemaCheckTypeDefCircularInternal(ctxt, cur, cur->baseType); + cur = cur->redef; + } while (cur != NULL); + } else + xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType); } /** @@ -14298,7 +14813,7 @@ xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt, * SPEC (1) "If the {base type definition} is a complex type definition, * then all of the following must be true:" */ - if (base->type == XML_SCHEMA_TYPE_COMPLEX) { + if (IS_COMPLEX_TYPE(base)) { /* * SPEC (1.1) "The {final} of the {base type definition} must not * contain extension." @@ -15619,7 +16134,7 @@ xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt, res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val); if (res == -2) goto internal_error; - if (res == -1) { + if (res == 1) { xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1); } } @@ -16036,7 +16551,7 @@ xmlSchemaTypeFixup(xmlSchemaTypePtr type, snprintf(buf, 29, "#scST%d", ++(pctxt->counter)); tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1); content = xmlSchemaAddType(pctxt, - pctxt->schema, tmpname, tmpname, type->node); + pctxt->schema, tmpname, tmpname, type->node, 0); if (content == NULL) return; /* @@ -18355,8 +18870,6 @@ xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt) return (ret); } -#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate(); - static const xmlChar * xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt, const xmlChar *prefix) @@ -18392,7 +18905,6 @@ xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt, if (nsName != NULL) { const xmlChar *ret; - VAL_CREATE_DICT; ret = xmlDictLookup(vctxt->dict, nsName, -1); xmlFree(nsName); return (ret); @@ -18488,6 +19000,34 @@ xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt, return (ret); } +static int +xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt, + const xmlChar* lname, + const xmlChar* nsname) +{ + int i; + + lname = xmlDictLookup(vctxt->dict, lname, -1); + if (lname == NULL) + return(-1); + if (nsname != NULL) { + nsname = xmlDictLookup(vctxt->dict, nsname, -1); + if (nsname == NULL) + return(-1); + } + for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) { + if ((vctxt->nodeQNames->items [i] == lname) && + (vctxt->nodeQNames->items[i +1] == nsname)) + /* Already there */ + return(i); + } + /* Add new entry. */ + i = vctxt->nodeQNames->nbItems; + xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname); + xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname); + return(i); +} + /************************************************************************ * * * Validation of identity-constraints (IDC) * @@ -19056,6 +19596,32 @@ xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt, } /** + * xmlSchemaXPathPop: + * @vctxt: the WXS validation context + * + * Pops all XPath states. + * + * Returns 0 on success and -1 on internal errors. + */ +static int +xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt) +{ + xmlSchemaIDCStateObjPtr sto; + int res; + + if (vctxt->xpathStates == NULL) + return(0); + sto = vctxt->xpathStates; + do { + res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt); + if (res == -1) + return (-1); + sto = sto->next; + } while (sto != NULL); + return(0); +} + +/** * xmlSchemaXPathProcessHistory: * @vctxt: the WXS validation context * @type: the simple/complex type of the current node if any at all @@ -19399,7 +19965,7 @@ create_key: *keySeq = NULL; return(-1); } - memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode)); + memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode)); /* * Store the node-table item on global list. @@ -19411,11 +19977,27 @@ create_key: *keySeq = NULL; return (-1); } + ntItem->nodeQNameID = -1; + } else { + /* + * Save a cached QName for this node on the IDC node, to be + * able to report it, even if the node is not saved. + */ + ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt, + vctxt->inode->localName, vctxt->inode->nsName); + if (ntItem->nodeQNameID == -1) { + xmlFree(ntItem); + xmlFree(*keySeq); + *keySeq = NULL; + return (-1); + } } /* - * Init the node-table item. Consume the key-sequence. + * Init the node-table item: Save the node, position and + * consume the key-sequence. */ ntItem->node = vctxt->node; + ntItem->nodeLine = vctxt->inode->nodeLine; ntItem->keys = *keySeq; *keySeq = NULL; if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) { @@ -19886,6 +20468,7 @@ xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt) int i, j, k, res; xmlSchemaPSVIIDCKeyPtr *refKeys, *keys; xmlSchemaPSVIIDCKeyPtr refKey, key; + xmlSchemaPSVIIDCNodePtr refNode = NULL; /* * Find the referred key/unique. @@ -19903,8 +20486,9 @@ xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt) */ for (i = 0; i < refbind->nbNodes; i++) { res = 0; - if (bind != NULL) { - refKeys = refbind->nodeTable[i]->keys; + refNode = refbind->nodeTable[i]; + if (bind != NULL) { + refKeys = refNode->keys; for (j = 0; j < bind->nbNodes; j++) { keys = bind->nodeTable[j]->keys; for (k = 0; k < bind->definition->nbFields; k++) { @@ -19928,9 +20512,8 @@ xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt) } if (res == 0) { xmlChar *str = NULL, *strB = NULL; - /* TODO: Report the key-sequence. */ - xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, - XML_SCHEMAV_CVC_IDC, NULL, + xmlSchemaKeyrefErr(vctxt, + XML_SCHEMAV_CVC_IDC, refNode, (xmlSchemaTypePtr) refbind->definition, "No match found for key-sequence %s of key " "reference '%s'", @@ -20011,8 +20594,9 @@ xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt) static int xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt, xmlNodePtr attrNode, + int nodeLine, const xmlChar *localName, - const xmlChar *nsName, + const xmlChar *nsName, int ownedNames, xmlChar *value, int ownedValue) @@ -20026,6 +20610,7 @@ xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt, return (-1); } attr->node = attrNode; + attr->nodeLine = nodeLine; attr->state = XML_SCHEMAS_ATTR_UNKNOWN; attr->localName = localName; attr->nsName = nsName; @@ -20859,7 +21444,6 @@ xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt, * string. */ local = xmlSplitQName2(value, &prefix); - VAL_CREATE_DICT; if (local == NULL) *localName = xmlDictLookup(vctxt->dict, value, -1); else { @@ -21715,7 +22299,8 @@ eval_idcs: "calling xmlSchemaXPathEvaluate()"); goto internal_error; } - } + } else if (vctxt->xpathStates != NULL) + xmlSchemaXPathPop(vctxt); } /* @@ -21802,41 +22387,6 @@ xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt, return (-1); } *skip = 0; - if (wild->negNsSet != NULL) { - /* - * URGENT VAL TODO: Fix the content model to reject - * "##other" wildcards. - */ - if (xmlSchemaCheckCVCWildcardNamespace(wild, - vctxt->inode->nsName) != 0) { - if ((wild->minOccurs == 1) && (wild->maxOccurs == 1)) { - xmlSchemaNodeInfoPtr pinode = vctxt->elemInfos[vctxt->depth -1]; - /* - * VAL TODO: Workaround possible *only* if minOccurs and - * maxOccurs are 1. - */ - xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt, - /* VAL TODO: error code? */ - XML_SCHEMAV_ELEMENT_CONTENT, NULL, - (xmlSchemaTypePtr) wild, - "This element is not accepted by the wildcard", - 0, 0, NULL); - vctxt->skipDepth = vctxt->depth; - if ((pinode->flags & - XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) - pinode->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT; - vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED; - return (XML_SCHEMAV_ELEMENT_CONTENT); - } - if (wild->processContents == XML_SCHEMAS_ANY_SKIP) { - *skip = 1; - return (0); - } - vctxt->inode->typeDef = - xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); - return (0); - } - } if (wild->processContents == XML_SCHEMAS_ANY_SKIP) { /* * URGENT VAL TODO: Either we need to position the stream to the @@ -23179,7 +23729,6 @@ internal_error: * * ************************************************************************/ -#ifdef XML_SCHEMA_SAX_ENABLED /* * Process text content. */ @@ -23278,6 +23827,10 @@ xmlSchemaSAXHandleStartElementNs(void *ctx, goto internal_error; } ielem = vctxt->inode; + /* + * TODO: Is this OK? + */ + ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt); ielem->localName = localname; ielem->nsName = URI; ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY; @@ -23345,8 +23898,11 @@ xmlSchemaSAXHandleStartElementNs(void *ctx, */ value = xmlStrndup(attributes[j+3], attributes[j+4] - attributes[j+3]); + /* + * TODO: Set the node line. + */ ret = xmlSchemaValidatorPushAttribute(vctxt, - NULL, attributes[j], attributes[j+2], 0, + NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0, value, 1); if (ret == -1) { VERROR_INT("xmlSchemaSAXHandleStartElementNs", @@ -23419,7 +23975,6 @@ internal_error: xmlStopParser(vctxt->parserCtxt); return; } -#endif /************************************************************************ * * @@ -23447,6 +24002,8 @@ xmlSchemaNewValidCtxt(xmlSchemaPtr schema) } memset(ret, 0, sizeof(xmlSchemaValidCtxt)); ret->type = XML_SCHEMA_CTXT_VALIDATOR; + ret->dict = xmlDictCreate(); + ret->nodeQNames = xmlSchemaItemListCreate(); ret->schema = schema; return (ret); } @@ -23524,7 +24081,11 @@ xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt) break; xmlSchemaClearElemInfo(ei); } - } + } + xmlSchemaItemListClear(vctxt->nodeQNames); + /* Recreate the dict. */ + xmlDictFree(vctxt->dict); + vctxt->dict = xmlDictCreate(); } /** @@ -23602,6 +24163,8 @@ xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt) } xmlFree(ctxt->elemInfos); } + if (ctxt->nodeQNames != NULL) + xmlSchemaItemListFree(ctxt->nodeQNames); if (ctxt->dict != NULL) xmlDictFree(ctxt->dict); xmlFree(ctxt); @@ -23648,6 +24211,26 @@ xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt, } /** + * xmlSchemaSetValidStructuredErrors: + * @ctxt: a schema validation context + * @serror: the structured error function + * @ctx: the functions context + * + * Set the structured error callback + */ +void +xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt, + xmlStructuredErrorFunc serror, void *ctx) +{ + if (ctxt == NULL) + return; + ctxt->serror = serror; + ctxt->error = NULL; + ctxt->warning = NULL; + ctxt->userData = ctx; +} + +/** * xmlSchemaGetValidErrors: * @ctxt: a XML-Schema validation context * @err: the error function result @@ -23758,6 +24341,7 @@ xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt) goto internal_error; ielem = vctxt->inode; ielem->node = node; + ielem->nodeLine = node->line; ielem->localName = node->name; if (node->ns != NULL) ielem->nsName = node->ns->href; @@ -23777,6 +24361,11 @@ xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt) nsName = NULL; ret = xmlSchemaValidatorPushAttribute(vctxt, (xmlNodePtr) attr, + /* + * Note that we give it the line number of the + * parent element. + */ + ielem->nodeLine, attr->name, nsName, 0, xmlNodeListGetString(attr->doc, attr->children, 1), 1); if (ret == -1) { @@ -24246,24 +24835,24 @@ commentSplit(void *ctx, const xmlChar *value) * Varargs error callbacks to the user application, harder ... */ -static void -warningSplit(void *ctx, const char *msg, ...) { +static void XMLCDECL +warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; if ((ctxt != NULL) && (ctxt->user_sax != NULL) && (ctxt->user_sax->warning != NULL)) { TODO } } -static void -errorSplit(void *ctx, const char *msg, ...) { +static void XMLCDECL +errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; if ((ctxt != NULL) && (ctxt->user_sax != NULL) && (ctxt->user_sax->error != NULL)) { TODO } } -static void -fatalErrorSplit(void *ctx, const char *msg, ...) { +static void XMLCDECL +fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; if ((ctxt != NULL) && (ctxt->user_sax != NULL) && (ctxt->user_sax->fatalError != NULL)) { @@ -24643,7 +25232,6 @@ xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt, const char * filename, int options ATTRIBUTE_UNUSED) { -#ifdef XML_SCHEMA_SAX_ENABLED int ret; xmlParserInputBufferPtr input; @@ -24657,9 +25245,6 @@ xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt, ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE, NULL, NULL); return (ret); -#else - return (-1); -#endif /* XML_SCHEMA_SAX_ENABLED */ } #define bottom_xmlschemas |