Completion of the schema graph. Centralisation, more robustness of the
* xmlschemas.c include/libxml/schemasInternals.h
include/libxml/xmlerror.h: Completion of the schema graph.
Centralisation, more robustness of the schema document
aquisition story. Centralised and restructured component fixup.
Fixed attribute derivation when 'prohibiting' attribute uses.
Added warnings: when schema documents cannot be localized
during imports; when we get duplicate and pointless attribute
prohibitions. Changed error reports for IDCs to report
the relevant IDC designation as well (requested by GUY Fabrice).
Misc code-cleanup.
diff --git a/xmlschemas.c b/xmlschemas.c
index 76bf3fd..82c4bea 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -66,8 +66,12 @@
/* #define ENABLE_PARTICLE_RESTRICTION 1 */
+/* #define ENABLE_SCHEMA_SPACES */
+
/* #define ENABLE_REDEFINE */
+/* #define ENABLE_NAMED_LOCALS */
+
#define DUMP_CONTENT_MODEL
#ifdef LIBXML_READER_ENABLED
@@ -102,10 +106,6 @@
"attribute use";
static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
"model group";
-#if 0
-static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
- "model group ref.";
-#endif
#define IS_SCHEMA(node, type) \
((node != NULL) && (node->ns != NULL) && \
@@ -139,6 +139,10 @@
((item->type != XML_SCHEMA_TYPE_BASIC) && \
((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
+#define TYPE_IS_NOT_FIXEDUP_1(item) \
+ (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
+ (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
+
#define HAS_COMPLEX_CONTENT(item) \
((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
(item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
@@ -172,12 +176,62 @@
#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
-#define SUBST_GROUP_AFF(item) item->refDecl
+#define SUBST_GROUP_AFF(item) (item)->refDecl
+
+#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
#if 0
-#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
+#define WXS_GET_NEXT(item) \
+ xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
#endif
+#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
+
+#define HFAILURE if (res == -1) goto exit_failure;
+
+#define HERROR if (res != 0) goto exit_error;
+
+#define HSTOP(ctx) if ((ctx)->stop) goto exit;
+
+#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
+
+#define WXS_HAS_BUCKETS(ctx) \
+( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
+(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
+
+#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
+
+#define WXS_SCHEMA_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
+
+#define WXS_SCHEMA(ctx) (ctx)->schema
+
+#define ADD_LOCAL_ITEM(ctx, item) \
+ xmlSchemaAddItem(&(WXS_SCHEMA_BUCKET(ctx)->locals), item)
+
+#define ADD_GLOBAL_ITEM(ctx, item) \
+ xmlSchemaAddItem(&(WXS_SCHEMA_BUCKET(ctx)->globals), item)
+
+#define WXS_ADD_PENDING_ITEM(ctx, item) \
+ xmlSchemaAddItem(&((ctx)->constructor->pending), item)
+
+#define WXS_IS_RESTRICTION(t) \
+ ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
+
+#define WXS_IS_EXTENSION(t) \
+ ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
+
+/*
+* @b: The schema bucket
+*/
+#define WXS_IS_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
+ ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
+
+#define WXS_IS_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
+ ((t) == XML_SCHEMA_SCHEMA_IMPORT))
+
+#define IMPBUCKET_CAST(b) ((xmlSchemaImportPtr) (b))
+#define INCBUCKET_CAST(b) ((xmlSchemaIncludePtr) (b))
+
#define SUBSET_RESTRICTION 1<<0
#define SUBSET_EXTENSION 1<<1
#define SUBSET_SUBSTITUTION 1<<2
@@ -191,10 +245,6 @@
typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
-
-typedef struct _xmlSchemaItemList xmlSchemaAssemble;
-typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
-
typedef struct _xmlSchemaItemList xmlSchemaItemList;
typedef xmlSchemaItemList *xmlSchemaItemListPtr;
struct _xmlSchemaItemList {
@@ -203,44 +253,116 @@
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;
};
+typedef struct _xmlSchemaBucket xmlSchemaBucket;
+typedef xmlSchemaBucket *xmlSchemaBucketPtr;
+
+#define XML_SCHEMA_SCHEMA_MAIN 0
+#define XML_SCHEMA_SCHEMA_IMPORT 1
+#define XML_SCHEMA_SCHEMA_INCLUDE 2
+#define XML_SCHEMA_SCHEMA_REDEFINE 3
+
/**
- * xmlSchemaContainer:
+ * xmlSchemaSchemaRelation:
+ *
+ * Used to create a graph of schema relationships.
*/
-typedef struct _xmlSchemaContainer xmlSchemaContainer;
-typedef xmlSchemaContainer *xmlSchemaContainerPtr;
-struct _xmlSchemaContainer {
- xmlSchemaItemListPtr typeDefs;
- xmlSchemaItemListPtr attrDecls;
- xmlSchemaItemListPtr elemDecls;
- xmlSchemaItemListPtr attrGroupDefs;
- xmlSchemaItemListPtr modelGroupDefs;
- xmlSchemaItemListPtr notationDecls;
- xmlSchemaItemListPtr annotations;
+typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
+typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
+struct _xmlSchemaSchemaRelation {
+ xmlSchemaSchemaRelationPtr next;
+ int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
+ const xmlChar *importNamespace;
+ xmlSchemaBucketPtr bucket;
+};
+
+struct _xmlSchemaBucket {
+ int type;
+ const xmlChar *schemaLocation;
+ const xmlChar *origTargetNamespace;
+ const xmlChar *targetNamespace;
+ xmlDocPtr doc;
+ xmlSchemaSchemaRelationPtr relations;
+ int located;
+ int parsed;
+ int imported;
+ int preserveDoc;
+ xmlSchemaItemListPtr globals; /* Global components. */
+ xmlSchemaItemListPtr locals; /* Local components. */
+};
+
+/**
+ * xmlSchemaImport:
+ * (extends xmlSchemaBucket)
+ *
+ * Reflects a schema. Holds some information
+ * about the schema and its toplevel components. Duplicate
+ * toplevel components are not checked at this level.
+ */
+typedef struct _xmlSchemaImport xmlSchemaImport;
+typedef xmlSchemaImport *xmlSchemaImportPtr;
+struct _xmlSchemaImport {
+ int type; /* Main OR import OR include. */
+ const xmlChar *schemaLocation; /* The URI of the schema document. */
+ /* For chameleon includes, @origTargetNamespace will be NULL */
+ const xmlChar *origTargetNamespace;
+ /*
+ * For chameleon includes, @targetNamespace will be the
+ * targetNamespace of the including schema.
+ */
+ const xmlChar *targetNamespace;
+ xmlDocPtr doc; /* The schema node-tree. */
+ /* @relations will hold any included/imported/redefined schemas. */
+ xmlSchemaSchemaRelationPtr relations;
+ int located;
+ int parsed;
+ int imported;
+ int preserveDoc;
+ xmlSchemaItemListPtr globals;
xmlSchemaItemListPtr locals;
+ /* The imported schema. */
+ xmlSchemaPtr schema;
+};
+
+/*
+* (extends xmlSchemaBucket)
+*/
+typedef struct _xmlSchemaInclude xmlSchemaInclude;
+typedef xmlSchemaInclude *xmlSchemaIncludePtr;
+struct _xmlSchemaInclude {
+ int type;
+ const xmlChar *schemaLocation;
+ const xmlChar *origTargetNamespace;
+ const xmlChar *targetNamespace;
+ xmlDocPtr doc;
+ xmlSchemaSchemaRelationPtr relations;
+ int located;
+ int parsed;
+ int imported;
+ int preserveDoc;
+ xmlSchemaItemListPtr globals; /* Global components. */
+ xmlSchemaItemListPtr locals; /* Local components. */
+
+ /* The owning main or import schema bucket. */
+ xmlSchemaImportPtr ownerImport;
+};
+
+typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
+typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
+struct _xmlSchemaConstructionCtxt {
+ xmlSchemaPtr schema; /* The main schema. */
+ xmlDictPtr dict;
+ xmlSchemaItemListPtr buckets; /* List of schema buckets. */
+ /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
+ xmlSchemaBucketPtr bucket; /* The current schema bucket */
+ /* All Components of all schemas that need to be fixed. */
+ xmlSchemaItemListPtr pending;
+ xmlHashTablePtr substGroups;
};
#define XML_SCHEMA_CTXT_PARSER 1
@@ -248,18 +370,20 @@
struct _xmlSchemaParserCtxt {
int type;
- void *userData; /* user specific data block */
+ void *userData; /* user specific data block */
xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
xmlSchemaValidError err;
int nberrors;
xmlStructuredErrorFunc serror;
+ xmlSchemaConstructionCtxtPtr constructor;
+ int ownsConstructor; /* TODO: Move this to parser flags. */
+
/* xmlSchemaPtr topschema; The main schema */
/* xmlHashTablePtr namespaces; Hash table of namespaces to schemas */
xmlSchemaPtr schema; /* The schema in use */
- const xmlChar *container; /* the current element, group, ... */
int counter;
const xmlChar *URL;
@@ -278,19 +402,15 @@
xmlAutomataStatePtr state;
xmlDictPtr dict; /* dictionnary for interned string names */
- int includes; /* the inclusion level, 0 for root or imports */
xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
- xmlSchemaTypePtr parentItem; /* The current parent schema item */
- xmlSchemaAssemblePtr assemble;
+ xmlSchemaTypePtr parentItem; /* The current parent schema item */
int options;
xmlSchemaValidCtxtPtr vctxt;
- const xmlChar **localImports; /* list of locally imported namespaces */
- int sizeLocalImports;
- int nbLocalImports;
- xmlHashTablePtr substGroups;
int isS4S;
int isRedefine;
- xmlSchemaContainerPtr compContainer;
+ int xsiAssemble;
+ int stop; /* If the parser should stop; i.e. a critical error. */
+ const xmlChar *targetNamespace;
};
#define XML_SCHEMAS_ATTR_UNKNOWN 1
@@ -322,26 +442,6 @@
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:
*
@@ -438,6 +538,7 @@
const xmlChar *targetNamespace;
xmlNodePtr node;
int flags;
+ xmlSchemaModelGroupDefPtr redef; /* Redefinitions. */
};
typedef struct _xmlSchemaIDC xmlSchemaIDC;
@@ -737,31 +838,6 @@
xmlSchemaItemListPtr nodeQNames;
};
-/*
- * These are the entries in the schemas importSchemas hash table
- */
-typedef struct _xmlSchemaImport xmlSchemaImport;
-typedef xmlSchemaImport *xmlSchemaImportPtr;
-struct _xmlSchemaImport {
- const xmlChar *schemaLocation;
- xmlSchemaPtr schema; /* not used any more */
- xmlDocPtr doc;
- int isMain;
-};
-
-/*
- * These are the entries associated to includes in a schemas
- */
-typedef struct _xmlSchemaInclude xmlSchemaInclude;
-typedef xmlSchemaInclude *xmlSchemaIncludePtr;
-struct _xmlSchemaInclude {
- xmlSchemaIncludePtr next;
- const xmlChar *schemaLocation;
- xmlDocPtr doc;
- const xmlChar *origTargetNamespace;
- const xmlChar *targetNamespace;
-};
-
/**
* xmlSchemaSubstGroup:
*
@@ -783,20 +859,18 @@
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);
+static int
+xmlSchemaTypeFixup(xmlSchemaTypePtr type,
+ xmlSchemaParserCtxtPtr ctxt);
static const xmlChar *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
xmlNodePtr node);
-static void
+static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
xmlSchemaParserCtxtPtr ctxt);
static void
@@ -821,8 +895,9 @@
int subset);
static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
- xmlSchemaParserCtxtPtr ctxt,
- const xmlChar * name ATTRIBUTE_UNUSED);
+ xmlSchemaParserCtxtPtr ctxt);
+static void
+xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
/************************************************************************
* *
@@ -863,11 +938,14 @@
case XML_SCHEMA_TYPE_PARTICLE:
return(BAD_CAST "particle");
case XML_SCHEMA_TYPE_IDC_UNIQUE:
- return(BAD_CAST "IDC (unique)");
+ return(BAD_CAST "unique identity-constraint");
+ /* return(BAD_CAST "IDC (unique)"); */
case XML_SCHEMA_TYPE_IDC_KEY:
- return(BAD_CAST "IDC (key)");
+ return(BAD_CAST "key identity-constraint");
+ /* return(BAD_CAST "IDC (key)"); */
case XML_SCHEMA_TYPE_IDC_KEYREF:
- return(BAD_CAST "IDC (keyref)");
+ return(BAD_CAST "keyref identity-constraint");
+ /* return(BAD_CAST "IDC (keyref)"); */
case XML_SCHEMA_TYPE_ANY:
return(BAD_CAST "wildcard (any)");
case XML_SCHEMA_EXTRA_QNAMEREF:
@@ -1099,6 +1177,19 @@
xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
}
+static const xmlChar*
+xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
+{
+ xmlChar *str = NULL;
+
+ *buf = xmlStrcat(*buf, xmlSchemaCompTypeToString(idc->type));
+ *buf = xmlStrcat(*buf, BAD_CAST " '");
+ *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, idc));
+ *buf = xmlStrcat(*buf, BAD_CAST "'");
+ FREE_AND_NULL(str);
+ return(*buf);
+}
+
/**
* xmlSchemaWildcardPCToString:
* @pc: the type of processContents
@@ -1623,6 +1714,16 @@
extra);
}
+static void
+xmlSchemaPSimpleInternalErr(xmlNodePtr node,
+ const char *msg, const xmlChar *str)
+{
+ __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
+ msg, (const char *) str);
+}
+
+#define WXS_ERROR_TYPE_ERROR 1
+#define WXS_ERROR_TYPE_WARNING 2
/**
* xmlSchemaErr3:
* @ctxt: the validation context
@@ -1636,23 +1737,27 @@
* Handle a validation error
*/
static void
-xmlSchemaErr3Line(xmlSchemaAbstractCtxtPtr ctxt,
- int error, xmlNodePtr node, int line, const char *msg,
- const xmlChar *str1, const xmlChar *str2,
- const xmlChar *str3)
+xmlSchemaErr3Line(xmlSchemaAbstractCtxtPtr ctxt,
+ xmlErrorLevel errorLevel,
+ int error, xmlNodePtr node, int line, const char *msg,
+ const xmlChar *str1, const xmlChar *str2,
+ const xmlChar *str3)
{
xmlStructuredErrorFunc schannel = NULL;
xmlGenericErrorFunc channel = NULL;
- void *data = NULL;
+ void *data = NULL;
if (ctxt != NULL) {
if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
const char *file = NULL;
-
- vctxt->nberrors++;
- vctxt->err = error;
- channel = vctxt->error;
+ if (errorLevel != XML_ERR_WARNING) {
+ vctxt->nberrors++;
+ vctxt->err = error;
+ channel = vctxt->error;
+ } else {
+ channel = vctxt->warning;
+ }
schannel = vctxt->serror;
data = vctxt->userData;
@@ -1692,27 +1797,30 @@
}
__xmlRaiseError(schannel, channel, data, ctxt,
node, XML_FROM_SCHEMASV,
- error, XML_ERR_ERROR, file, line,
+ error, errorLevel, file, line,
(const char *) str1, (const char *) str2,
(const char *) str3, 0, 0, msg, str1, str2, str3);
} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
-
- pctxt->nberrors++;
- pctxt->err = error;
- channel = pctxt->error;
+ if (errorLevel != XML_ERR_WARNING) {
+ pctxt->nberrors++;
+ pctxt->err = error;
+ channel = pctxt->error;
+ } else {
+ channel = pctxt->warning;
+ }
schannel = pctxt->serror;
data = pctxt->userData;
__xmlRaiseError(schannel, channel, data, ctxt,
- node, XML_FROM_SCHEMASP,
- error, XML_ERR_ERROR, NULL, 0,
+ node, XML_FROM_SCHEMASP, error,
+ errorLevel, NULL, 0,
(const char *) str1, (const char *) str2,
(const char *) str3, 0, 0, msg, str1, str2, str3);
} else {
TODO
}
- }
+ }
}
/**
@@ -1732,7 +1840,8 @@
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);
+ xmlSchemaErr3Line(actxt, XML_ERR_ERROR, error, node, 0,
+ msg, str1, str2, str3);
}
static void
@@ -1800,6 +1909,12 @@
vctxt->inode->nsName, vctxt->inode->localName));
FREE_AND_NULL(str);
*msg = xmlStrcat(*msg, BAD_CAST "': ");
+ } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
+ /*
+ * Hmm, no node while parsing?
+ * Return an empty string, in case NULL will break something.
+ */
+ *msg = xmlStrdup(BAD_CAST "");
} else {
TODO
return (NULL);
@@ -1854,6 +1969,7 @@
xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
}
+#if 0
static void
xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
const char *funcName,
@@ -1861,9 +1977,10 @@
const xmlChar *str1,
const xmlChar *str2)
{
- xmlSchemaInternalErr2((xmlSchemaAbstractCtxtPtr) pctxt, funcName, message,
+ xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
str1, str2);
}
+#endif
static void
xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
@@ -1885,6 +2002,31 @@
}
static void
+xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
+ xmlParserErrors error,
+ xmlNodePtr node,
+ xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
+ const char *message,
+ const xmlChar *str1,
+ const xmlChar *str2,
+ const xmlChar *str3)
+{
+ xmlChar *msg = NULL;
+
+ xmlSchemaFormatNodeForError(&msg, actxt, node);
+ msg = xmlStrcat(msg, (const xmlChar *) message);
+ msg = xmlStrcat(msg, BAD_CAST ".\n");
+
+ /* URGENT TODO: Set the error code to something sane. */
+ xmlSchemaErr3Line(actxt, XML_ERR_WARNING, error, node, 0,
+ (const char *) msg, str1, str2, str3);
+
+ FREE_AND_NULL(msg)
+}
+
+
+
+static void
xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
xmlParserErrors error,
xmlSchemaPSVIIDCNodePtr idcNode,
@@ -1898,7 +2040,7 @@
msg = xmlStrdup(BAD_CAST "Element '%s': ");
msg = xmlStrcat(msg, (const xmlChar *) message);
msg = xmlStrcat(msg, BAD_CAST ".\n");
- xmlSchemaErr3Line((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaErr3Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
error, NULL, idcNode->nodeLine, (const char *) msg,
xmlSchemaFormatQName(&qname,
vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
@@ -2260,12 +2402,12 @@
}
#define VERROR(err, type, msg) \
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
+ xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
-#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
+#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
-#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
-#define PERROR_INT2(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) ctxt, func, msg);
+#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
+#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
@@ -2661,7 +2803,7 @@
{
xmlChar *msg = NULL;
- xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
+ xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
if (message == NULL) {
/*
* Use default messages.
@@ -2823,29 +2965,6 @@
}
/**
- * xmlSchemaNewSchema:
- * @ctxt: a schema validation context
- *
- * Allocate a new Schema structure.
- *
- * Returns the newly allocated structure or NULL in case or error
- */
-static xmlSchemaAssemblePtr
-xmlSchemaNewAssemble(void)
-{
- xmlSchemaAssemblePtr ret;
-
- ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
- if (ret == NULL) {
- /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
- return (NULL);
- }
- memset(ret, 0, sizeof(xmlSchemaAssemble));
- ret->items = NULL;
- return (ret);
-}
-
-/**
* xmlSchemaNewFacet:
*
* Allocate a new Facet structure.
@@ -2958,152 +3077,159 @@
xmlFree(list);
}
-static xmlSchemaContainerPtr
-xmlSchemaContainerCreate(void)
+static void
+xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
{
- xmlSchemaContainerPtr ret;
+ if (bucket == NULL)
+ return;
+ if (bucket->globals != NULL) {
+ xmlSchemaComponentListFree(bucket->globals);
+ xmlSchemaItemListFree(bucket->globals);
+ }
+ if (bucket->locals != NULL) {
+ xmlSchemaComponentListFree(bucket->locals);
+ xmlSchemaItemListFree(bucket->locals);
+ }
+ if (bucket->relations != NULL) {
+ xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
+ do {
+ prev = cur;
+ cur = cur->next;
+ xmlFree(prev);
+ } while (cur != NULL);
+ }
+ if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
+ xmlFreeDoc(bucket->doc);
+ }
+ if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
+ if (IMPBUCKET_CAST(bucket)->schema != NULL)
+ xmlSchemaFree(IMPBUCKET_CAST(bucket)->schema);
+ }
+ xmlFree(bucket);
+}
- ret = (xmlSchemaContainerPtr) xmlMalloc(sizeof(xmlSchemaContainer));
- if (ret == NULL) {
- xmlSchemaPErrMemory(NULL, "allocating component container",
- NULL);
+static xmlSchemaBucketPtr
+xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
+ int type,
+ const xmlChar *targetNamespace)
+{
+ xmlSchemaBucketPtr ret;
+ xmlSchemaConstructionCtxtPtr constr = pctxt->constructor;
+ int size;
+ xmlSchemaPtr mainSchema;
+
+ if (constr->schema == NULL) {
+ PERROR_INT("xmlSchemaBucketCreate",
+ "no main schema on constructor");
return(NULL);
}
- memset(ret, 0, sizeof(xmlSchemaContainer));
+ mainSchema = constr->schema;
+ /* Create the schema bucket. */
+ if (WXS_IS_INCREDEF(type))
+ size = sizeof(xmlSchemaInclude);
+ else
+ size = sizeof(xmlSchemaImport);
+ ret = (xmlSchemaBucketPtr) xmlMalloc(size);
+ if (ret == NULL) {
+ xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
+ return(NULL);
+ }
+ memset(ret, 0, size);
+ ret->targetNamespace = targetNamespace;
+ ret->type = type;
+ /*
+ * The following will assure that only the first bucket is marked as
+ * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
+ * For each following import buckets an xmlSchema will be created.
+ */
+ if (! WXS_HAS_BUCKETS(pctxt)) {
+ if (WXS_IS_INCREDEF(type)) {
+ PERROR_INT("xmlSchemaBucketCreate",
+ "first bucket but it's an include or redefine");
+ xmlSchemaBucketFree(ret);
+ return(NULL);
+ }
+ /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
+ ret->type = XML_SCHEMA_SCHEMA_MAIN;
+ /* Point to the *main* schema. */
+ IMPBUCKET_CAST(ret)->schema = mainSchema;
+ } else {
+ if (type == XML_SCHEMA_SCHEMA_MAIN) {
+ PERROR_INT("xmlSchemaBucketCreate",
+ "main bucket but it's not the first one");
+ xmlSchemaBucketFree(ret);
+ return(NULL);
+ } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
+ /*
+ * Create a schema for imports.
+ */
+ IMPBUCKET_CAST(ret)->schema = xmlSchemaNewSchema(pctxt);
+ if (IMPBUCKET_CAST(ret)->schema == NULL) {
+ xmlSchemaBucketFree(ret);
+ return(NULL);
+ }
+ }
+ }
+ if (WXS_IS_IMPMAIN(type)) {
+ int res;
+ /* Imports got into the "schemasImports" slot of the main *schema*. */
+ if (mainSchema->schemasImports == NULL) {
+ mainSchema->schemasImports = xmlHashCreateDict(5, constr->dict);
+ if (mainSchema->schemasImports == NULL) {
+ xmlSchemaBucketFree(ret);
+ return(NULL);
+ }
+ }
+ if (targetNamespace == NULL)
+ res = xmlHashAddEntry(mainSchema->schemasImports,
+ XML_SCHEMAS_NO_NAMESPACE, ret);
+ else
+ res = xmlHashAddEntry(mainSchema->schemasImports,
+ targetNamespace, ret);
+ if (res != 0) {
+ PERROR_INT("xmlSchemaBucketCreate",
+ "failed to add the schema bucket to the hash");
+ xmlSchemaBucketFree(ret);
+ return(NULL);
+ }
+ } else {
+ /* Set the @ownerImport of an include bucket. */
+ if (WXS_IS_IMPMAIN(constr->bucket->type))
+ INCBUCKET_CAST(ret)->ownerImport =
+ IMPBUCKET_CAST(constr->bucket);
+ else
+ INCBUCKET_CAST(ret)->ownerImport =
+ INCBUCKET_CAST(constr->bucket)->ownerImport;
+
+ /* Includes got into the "includes" slot of the *main* schema. */
+ if (mainSchema->includes == NULL) {
+ mainSchema->includes = xmlSchemaItemListCreate();
+ if (mainSchema->includes == NULL) {
+ xmlSchemaBucketFree(ret);
+ return(NULL);
+ }
+ }
+ xmlSchemaItemListAdd(mainSchema->includes, ret);
+ }
+ /*
+ * Add to list of all buckets; this is used for lookup
+ * during schema construction time only.
+ */
+ if (xmlSchemaItemListAdd(constr->buckets, ret) == -1)
+ return(NULL);
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
- * @head: the head of the substitution group
- * @member: the new member of the substitution group
- *
- * Allocate a new annotation structure.
- *
- * Returns the newly allocated structure or NULL in case or error
- */
static int
-xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
- xmlSchemaElementPtr head,
- xmlSchemaElementPtr member)
+xmlSchemaAddItem(xmlSchemaItemListPtr *list, void *item)
{
- xmlSchemaSubstGroupPtr substGroup;
-
- if (pctxt == NULL)
- return (-1);
-
- if (pctxt->substGroups == NULL) {
- pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
- if (pctxt->substGroups == NULL)
- return (-1);
+ if (*list == NULL) {
+ *list = xmlSchemaItemListCreate();
+ if (*list == NULL)
+ return(-1);
}
- substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
- head->targetNamespace);
- if (substGroup == NULL) {
- int res;
-
- substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
- if (substGroup == NULL) {
- xmlSchemaPErrMemory(NULL,
- "xmlSchemaAddElementSubstitution, allocating a substitution "
- "group container",
- NULL);
- return (-1);
- }
- substGroup->members = xmlSchemaItemListCreate();
- if (substGroup->members == NULL) {
- xmlFree(substGroup);
- return (-1);
- }
- substGroup->head = head;
-
- res = xmlHashAddEntry2(pctxt->substGroups,
- head->name, head->targetNamespace, substGroup);
- if (res != 0) {
- xmlFree(substGroup->members);
- xmlFree(substGroup);
- xmlSchemaPErr(pctxt, member->node,
- XML_SCHEMAP_INTERNAL,
- "Internal error: xmlSchemaAddElementSubstitution, "
- "failed to add a new substitution group container for "
- "'%s'.\n", head->name, NULL);
- return (-1);
- }
- }
- if (substGroup->members->items == NULL) {
- substGroup->members->items = (void **) xmlMalloc(
- 5 * sizeof(xmlSchemaElementPtr));
- if (substGroup->members->items == NULL) {
- xmlSchemaPErrMemory(NULL,
- "allocating list of substitution group members", NULL);
- return (-1);
- }
- substGroup->members->sizeItems = 5;
- } else if (substGroup->members->sizeItems <=
- substGroup->members->nbItems) {
- substGroup->members->sizeItems *= 2;
- substGroup->members->items = (void **) xmlRealloc(
- substGroup->members->items,
- substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
- if (substGroup->members->items == NULL) {
- xmlSchemaPErrMemory(NULL,
- "re-allocating list of substitution group members", NULL);
- substGroup->members->sizeItems = 0;
- return (-1);
- }
- }
- ((xmlSchemaElementPtr *) substGroup->members->items)
- [substGroup->members->nbItems++] = (void *) member;
- return (0);
-}
-
-/**
- * xmlSchemaGetElementSubstitutionGroup:
- * @pctxt: a schema parser context
- * @head: the head of the substitution group
- * @member: the new member of the substitution group
- *
- * Allocate a new annotation structure.
- *
- * Returns the newly allocated structure or NULL in case or error
- */
-static xmlSchemaSubstGroupPtr
-xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
- xmlSchemaElementPtr head)
-{
- if (pctxt == NULL)
- return (NULL);
-
- if (pctxt->substGroups == NULL)
- return (NULL);
-
- return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
- head->name, head->targetNamespace));
+ xmlSchemaItemListAdd(*list, item);
+ return(0);
}
/**
@@ -3131,57 +3257,6 @@
}
/**
- * xmlSchemaFreeImport:
- * @import: a schema import structure
- *
- * Deallocate an import structure
- */
-static void
-xmlSchemaFreeImport(xmlSchemaImportPtr import)
-{
- if (import == NULL)
- return;
-
- xmlSchemaFree(import->schema);
- xmlFreeDoc(import->doc);
- xmlFree(import);
-}
-
-/**
- * xmlSchemaFreeInclude:
- * @include: a schema include structure
- *
- * Deallocate an include structure
- */
-static void
-xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
-{
- if (include == NULL)
- return;
-
- xmlFreeDoc(include->doc);
- xmlFree(include);
-}
-
-/**
- * xmlSchemaFreeIncludeList:
- * @includes: a schema include list
- *
- * Deallocate an include structure
- */
-static void
-xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
-{
- xmlSchemaIncludePtr next;
-
- while (includes != NULL) {
- next = includes->next;
- xmlSchemaFreeInclude(includes);
- includes = next;
- }
-}
-
-/**
* xmlSchemaFreeNotation:
* @schema: a schema notation structure
*
@@ -3298,37 +3373,6 @@
}
/**
- * xmlSchemaFreeQNameRef:
- * @item: a QName reference structure
- *
- * Deallocatea a QName reference structure.
- */
-static void
-xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
-{
- if (item == NULL)
- return;
- if (item->members != NULL)
- xmlSchemaItemListFree(item->members);
- xmlFree(item);
-}
-
-static int
-xmlSchemaAddVolatile(xmlSchemaPtr schema,
- xmlSchemaBasicItemPtr item)
-{
- if (schema->volatiles == NULL) {
- schema->volatiles = (void *) xmlSchemaItemListCreate();
- if (schema->volatiles == NULL) {
- xmlSchemaPErrMemory(NULL,
- "allocating list of volatiles", NULL);
- return (-1);
- }
- }
- return(xmlSchemaItemListAdd((xmlSchemaItemListPtr) schema->volatiles, item));
-}
-
-/**
* xmlSchemaFreeTypeLinkList:
* @alink: a type link
*
@@ -3512,76 +3556,6 @@
}
/**
- * xmlSchemaFreeParticle:
- * @type: a schema type structure
- *
- * Deallocate a Schema Type structure.
- */
-static void
-xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
-{
- if (item->annot != NULL)
- xmlSchemaFreeAnnot(item->annot);
- xmlFree(item);
-}
-
-/**
- * xmlSchemaFreeMiscComponents:
- * @item: a schema component
- *
- * Deallocates misc. schema component structures.
- */
-static void
-xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
-{
- if (item == NULL)
- return;
- switch (item->type) {
- case XML_SCHEMA_TYPE_PARTICLE:
- xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
- return;
- case XML_SCHEMA_TYPE_SEQUENCE:
- case XML_SCHEMA_TYPE_CHOICE:
- case XML_SCHEMA_TYPE_ALL:
- xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
- return;
- case XML_SCHEMA_TYPE_ANY:
- case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
- xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
- break;
- default:
- /* TODO: This should never be hit. */
- TODO
- return;
- }
-}
-
-static void
-xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
-{
- if (schema->volatiles == NULL)
- return;
- {
- xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
- xmlSchemaTreeItemPtr item;
- int i;
-
- for (i = 0; i < list->nbItems; i++) {
- if (list->items[i] != NULL) {
- item = (xmlSchemaTreeItemPtr) list->items[i];
- switch (item->type) {
- case XML_SCHEMA_EXTRA_QNAMEREF:
- xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
- break;
- default:
- xmlSchemaFreeMiscComponents(item);
- }
- }
- }
- xmlSchemaItemListFree(list);
- }
-}
-/**
* xmlSchemaFreeTypeList:
* @type: a schema type structure
*
@@ -3599,6 +3573,79 @@
}
}
+static void
+xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
+{
+ if ((list == NULL) || (list->nbItems == 0))
+ return;
+ {
+ xmlSchemaTreeItemPtr item;
+ xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
+ int i;
+
+ for (i = 0; i < list->nbItems; i++) {
+ item = items[i];
+ if (item == NULL)
+ continue;
+ switch (item->type) {
+ case XML_SCHEMA_TYPE_SIMPLE:
+ case XML_SCHEMA_TYPE_COMPLEX:
+ xmlSchemaFreeTypeList((xmlSchemaTypePtr) item);
+ break;
+ case XML_SCHEMA_TYPE_ATTRIBUTE:
+ xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
+ break;
+ case XML_SCHEMA_TYPE_ELEMENT:
+ xmlSchemaFreeElement((xmlSchemaElementPtr) item);
+ break;
+ case XML_SCHEMA_TYPE_PARTICLE:
+ if (item->annot != NULL)
+ xmlSchemaFreeAnnot(item->annot);
+ xmlFree(item);
+ break;
+ case XML_SCHEMA_TYPE_SEQUENCE:
+ case XML_SCHEMA_TYPE_CHOICE:
+ case XML_SCHEMA_TYPE_ALL:
+ xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
+ break;
+ case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
+ xmlSchemaFreeAttributeGroup(
+ (xmlSchemaAttributeGroupPtr) item);
+ break;
+ case XML_SCHEMA_TYPE_GROUP:
+ xmlSchemaFreeModelGroupDef(
+ (xmlSchemaModelGroupDefPtr) item);
+ break;
+ case XML_SCHEMA_TYPE_ANY:
+ case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
+ xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
+ break;
+ case XML_SCHEMA_TYPE_IDC_KEY:
+ case XML_SCHEMA_TYPE_IDC_UNIQUE:
+ case XML_SCHEMA_TYPE_IDC_KEYREF:
+ xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
+ break;
+ case XML_SCHEMA_TYPE_NOTATION:
+ xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
+ break;
+ case XML_SCHEMA_EXTRA_QNAMEREF:
+ xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
+ break;
+ default: {
+ /* TODO: This should never be hit. */
+ xmlSchemaPSimpleInternalErr(NULL,
+ "Internal error: xmlSchemaComponentListFree, "
+ "unexpected component type '%s'\n",
+ (const xmlChar *)
+ xmlSchemaCompTypeToString(item->type));
+ }
+ break;
+ }
+ }
+ list->nbItems = 0;
+ }
+}
+
/**
* xmlSchemaFree:
* @schema: a schema structure
@@ -3610,40 +3657,44 @@
{
if (schema == NULL)
return;
-
+ /* @volatiles is not used anymore :-/ */
if (schema->volatiles != NULL)
- xmlSchemaFreeVolatiles(schema);
+ TODO
+ /*
+ * Note that those slots are not responsible for freeing
+ * schema components anymore; this will now be done by
+ * the schema buckets.
+ */
if (schema->notaDecl != NULL)
- xmlHashFree(schema->notaDecl,
- (xmlHashDeallocator) xmlSchemaFreeNotation);
+ xmlHashFree(schema->notaDecl, NULL);
if (schema->attrDecl != NULL)
- xmlHashFree(schema->attrDecl,
- (xmlHashDeallocator) xmlSchemaFreeAttribute);
+ xmlHashFree(schema->attrDecl, NULL);
if (schema->attrgrpDecl != NULL)
- xmlHashFree(schema->attrgrpDecl,
- (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
+ xmlHashFree(schema->attrgrpDecl, NULL);
if (schema->elemDecl != NULL)
- xmlHashFree(schema->elemDecl,
- (xmlHashDeallocator) xmlSchemaFreeElement);
+ xmlHashFree(schema->elemDecl, NULL);
if (schema->typeDecl != NULL)
- xmlHashFree(schema->typeDecl,
- (xmlHashDeallocator) xmlSchemaFreeTypeList);
+ xmlHashFree(schema->typeDecl, NULL);
if (schema->groupDecl != NULL)
- xmlHashFree(schema->groupDecl,
- (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
+ xmlHashFree(schema->groupDecl, NULL);
if (schema->idcDef != NULL)
- xmlHashFree(schema->idcDef,
- (xmlHashDeallocator) xmlSchemaFreeIDC);
+ xmlHashFree(schema->idcDef, NULL);
+
if (schema->schemasImports != NULL)
xmlHashFree(schema->schemasImports,
- (xmlHashDeallocator) xmlSchemaFreeImport);
+ (xmlHashDeallocator) xmlSchemaBucketFree);
if (schema->includes != NULL) {
- xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
+ xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
+ int i;
+ for (i = 0; i < list->nbItems; i++) {
+ xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
+ }
+ xmlSchemaItemListFree(list);
}
if (schema->annot != NULL)
xmlSchemaFreeAnnot(schema->annot);
- if (schema->doc != NULL && !schema->preserve)
- xmlFreeDoc(schema->doc);
+ /* Never free the doc here, since this will be done by the buckets. */
+
xmlDictFree(schema->dict);
xmlFree(schema);
}
@@ -4070,7 +4121,7 @@
xmlAttrPtr prop;
if ((node == NULL) || (name == NULL))
- return(NULL);
+ return(NULL);
prop = node->properties;
while (prop != NULL) {
if ((prop->ns != NULL) &&
@@ -4113,7 +4164,7 @@
xmlChar *val;
const xmlChar *ret;
- val = xmlGetProp(node, BAD_CAST name);
+ val = xmlGetNoNsProp(node, BAD_CAST name);
if (val == NULL)
return(NULL);
ret = xmlDictLookup(ctxt->dict, val, -1);
@@ -4127,6 +4178,23 @@
* *
************************************************************************/
+#define WXS_FIND_GLOBAL_ITEM(slot) \
+ if (xmlStrEqual(nsName, schema->targetNamespace)) { \
+ ret = xmlHashLookup(schema->slot, name); \
+ if (ret != NULL) goto exit; \
+ } \
+ if (xmlHashSize(schema->schemasImports) > 1) { \
+ xmlSchemaImportPtr import; \
+ if (nsName == NULL) \
+ import = xmlHashLookup(schema->schemasImports, \
+ XML_SCHEMAS_NO_NAMESPACE); \
+ else \
+ import = xmlHashLookup(schema->schemasImports, nsName); \
+ if (import == NULL) \
+ goto exit; \
+ ret = xmlHashLookup(import->schema->slot, name); \
+ }
+
/**
* xmlSchemaGetElem:
* @schema: the schema context
@@ -4141,40 +4209,21 @@
xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
const xmlChar * nsName)
{
- xmlSchemaElementPtr ret;
-
+ xmlSchemaElementPtr ret = NULL;
+
if ((name == NULL) || (schema == NULL))
- return (NULL);
-
- ret = xmlHashLookup2(schema->elemDecl, name, nsName);
- if ((ret != NULL) &&
- (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
- return (ret);
- } else
- ret = NULL;
-
- /*
- * Removed since imported components will be hold by the main schema only.
- *
- if (namespace == NULL)
- import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
- else
- import = xmlHashLookup(schema->schemasImports, namespace);
- if (import != NULL) {
- ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
- if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
- return (ret);
- } else
- ret = NULL;
- }
- */
+ return(NULL);
+ if (schema != NULL) {
+ WXS_FIND_GLOBAL_ITEM(elemDecl)
+ }
+exit:
#ifdef DEBUG
if (ret == NULL) {
- if (namespace == NULL)
+ if (nsName == NULL)
fprintf(stderr, "Unable to lookup element decl. %s", name);
else
fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
- namespace);
+ nsName);
}
#endif
return (ret);
@@ -4182,9 +4231,9 @@
/**
* xmlSchemaGetType:
- * @schema: the schemas context
- * @name: the type name
- * @ns: the type namespace
+ * @schema: the main schema
+ * @name: the type's name
+ * nsName: the type's namespace
*
* Lookup a type in the schemas or the predefined types
*
@@ -4194,40 +4243,30 @@
xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
const xmlChar * nsName)
{
- xmlSchemaTypePtr ret;
+ xmlSchemaTypePtr ret = NULL;
if (name == NULL)
- return (NULL);
+ return (NULL);
+ /* First try the built-in types. */
+ if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
+ ret = xmlSchemaGetPredefinedType(name, nsName);
+ if (ret != NULL)
+ goto exit;
+ /*
+ * Note that we try the parsed schemas as well here
+ * since one might have parsed the S4S, which contain more
+ * than the built-in types.
+ * TODO: Can we optimize this?
+ */
+ }
if (schema != NULL) {
- 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);
- }
+ WXS_FIND_GLOBAL_ITEM(typeDecl)
+ }
+exit:
+ if ((ret != NULL) && (ret->redef != NULL)) {
+ /* Return the last redefinition. */
+ ret = ret->redef;
}
- ret = xmlSchemaGetPredefinedType(name, nsName);
- if (ret != NULL)
- return (ret);
- /*
- * Removed, since the imported components will be grafted on the
- * main schema only.
- if (namespace == NULL)
- import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
- else
- import = xmlHashLookup(schema->schemasImports, namespace);
- if (import != NULL) {
- ret = xmlSchemaGetType(import->schema, name, namespace);
- if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
- return (ret);
- } else
- ret = NULL;
- }
- */
#ifdef DEBUG
if (ret == NULL) {
if (nsName == NULL)
@@ -4237,7 +4276,7 @@
nsName);
}
#endif
- return (NULL);
+ return (ret);
}
/**
@@ -4252,41 +4291,23 @@
*/
static xmlSchemaAttributePtr
xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
- const xmlChar * namespace)
+ const xmlChar * nsName)
{
- xmlSchemaAttributePtr ret;
+ xmlSchemaAttributePtr ret = NULL;
if ((name == NULL) || (schema == NULL))
return (NULL);
-
-
- ret = xmlHashLookup2(schema->attrDecl, name, namespace);
- if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
- return (ret);
- else
- ret = NULL;
- /*
- * Removed, since imported components will be hold by the main schema only.
- *
- if (namespace == NULL)
- import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
- else
- import = xmlHashLookup(schema->schemasImports, namespace);
- if (import != NULL) {
- ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
- if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
- return (ret);
- } else
- ret = NULL;
+ if (schema != NULL) {
+ WXS_FIND_GLOBAL_ITEM(attrDecl)
}
- */
+exit:
#ifdef DEBUG
if (ret == NULL) {
- if (namespace == NULL)
+ if (nsName == NULL)
fprintf(stderr, "Unable to lookup attribute %s", name);
else
fprintf(stderr, "Unable to lookup attribute %s:%s", name,
- namespace);
+ nsName);
}
#endif
return (ret);
@@ -4304,41 +4325,29 @@
*/
static xmlSchemaAttributeGroupPtr
xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
- const xmlChar * namespace)
+ const xmlChar * nsName)
{
- xmlSchemaAttributeGroupPtr ret;
+ xmlSchemaAttributeGroupPtr ret = NULL;
if ((name == NULL) || (schema == NULL))
return (NULL);
-
-
- ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
- if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
- return (ret);
- else
- ret = NULL;
- /*
- * Removed since imported components will be hold by the main schema only.
- *
- if (namespace == NULL)
- import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
- else
- import = xmlHashLookup(schema->schemasImports, namespace);
- if (import != NULL) {
- ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
- if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
- return (ret);
- else
- ret = NULL;
+ if (schema != NULL) {
+ WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
+ }
+exit:
+ /* TODO:
+ if ((ret != NULL) && (ret->redef != NULL)) {
+ * Return the last redefinition. *
+ ret = ret->redef;
}
*/
#ifdef DEBUG
if (ret == NULL) {
- if (namespace == NULL)
+ if (nsName == NULL)
fprintf(stderr, "Unable to lookup attribute group %s", name);
else
fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
- namespace);
+ nsName);
}
#endif
return (ret);
@@ -4354,43 +4363,66 @@
*
* Returns the group definition or NULL if not found.
*/
-static xmlSchemaTypePtr
+static xmlSchemaModelGroupDefPtr
xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
- const xmlChar * namespace)
+ const xmlChar * nsName)
{
- xmlSchemaTypePtr ret;
+ xmlSchemaModelGroupDefPtr ret = NULL;
if ((name == NULL) || (schema == NULL))
return (NULL);
-
- ret = xmlHashLookup2(schema->groupDecl, name, namespace);
- /*
- * Removed since imported components will be hold by the main schema only.
- *
- if (namespace == NULL)
- import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
- else
- import = xmlHashLookup(schema->schemasImports, namespace);
- if (import != NULL) {
- ret = xmlSchemaGetGroup(import->schema, name, namespace);
- if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
- return (ret);
- else
- ret = NULL;
+ if (schema != NULL) {
+ WXS_FIND_GLOBAL_ITEM(groupDecl)
}
- */
+exit:
+ if ((ret != NULL) && (ret->redef != NULL)) {
+ /* Return the last redefinition. */
+ ret = ret->redef;
+ }
#ifdef DEBUG
if (ret == NULL) {
- if (namespace == NULL)
+ if (nsName == NULL)
fprintf(stderr, "Unable to lookup group %s", name);
else
fprintf(stderr, "Unable to lookup group %s:%s", name,
- namespace);
+ nsName);
}
#endif
return (ret);
}
+static xmlSchemaNotationPtr
+xmlSchemaGetNotation(xmlSchemaPtr schema,
+ const xmlChar *name,
+ const xmlChar *nsName)
+{
+ xmlSchemaNotationPtr ret = NULL;
+
+ if ((name == NULL) || (schema == NULL))
+ return (NULL);
+ if (schema != NULL) {
+ WXS_FIND_GLOBAL_ITEM(notaDecl)
+ }
+exit:
+ return (ret);
+}
+
+static xmlSchemaIDCPtr
+xmlSchemaGetIDC(xmlSchemaPtr schema,
+ const xmlChar *name,
+ const xmlChar *nsName)
+{
+ xmlSchemaIDCPtr ret = NULL;
+
+ if ((name == NULL) || (schema == NULL))
+ return (NULL);
+ if (schema != NULL) {
+ WXS_FIND_GLOBAL_ITEM(idcDef)
+ }
+exit:
+ return (ret);
+}
+
/**
* xmlSchemaGetNamedComponent:
* @schema: the schema
@@ -4401,7 +4433,7 @@
*
* Returns the group definition or NULL if not found.
*/
-static xmlSchemaTreeItemPtr
+static xmlSchemaBasicItemPtr
xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
xmlSchemaTypeType itemType,
const xmlChar *name,
@@ -4409,12 +4441,13 @@
{
switch (itemType) {
case XML_SCHEMA_TYPE_GROUP:
- return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
+ return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
name, targetNs));
case XML_SCHEMA_TYPE_ELEMENT:
- return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
+ return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
name, targetNs));
default:
+ TODO
return (NULL);
}
}
@@ -4458,54 +4491,17 @@
return (1);
}
-/**
- * xmlSchemaAddAssembledItem:
- * @ctxt: a schema parser context
- * @schema: the schema being built
- * @item: the item
- *
- * Add a item to the schema's list of current items.
- * This is used if the schema was already constructed and
- * new schemata need to be added to it.
- * *WARNING* this interface is highly subject to change.
- *
- * Returns 0 if suceeds and -1 if an internal error occurs.
- */
-static int
-xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
- xmlSchemaTypePtr item)
-{
- static int growSize = 100;
- xmlSchemaAssemblePtr ass;
+#define WXS_GET_GLOBAL_HASH(c, s, slot) \
+{ \
+ if (WXS_IS_IMPMAIN((c)->type)) \
+ table = &(IMPBUCKET_CAST((c))->schema->slot); \
+ else \
+ table = &(INCBUCKET_CAST((c))->ownerImport->schema->slot); \
+} \
- ass = ctxt->assemble;
- if (ass->sizeItems < 0) {
- /* If disabled. */
- return (0);
- }
- if (ass->sizeItems <= 0) {
- ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
- if (ass->items == NULL) {
- xmlSchemaPErrMemory(ctxt,
- "allocating new item buffer", NULL);
- return (-1);
- }
- ass->sizeItems = growSize;
- } else if (ass->sizeItems <= ass->nbItems) {
- ass->sizeItems *= 2;
- ass->items = (void **) xmlRealloc(ass->items,
- ass->sizeItems * sizeof(xmlSchemaTypePtr));
- if (ass->items == NULL) {
- xmlSchemaPErrMemory(ctxt,
- "growing item buffer", NULL);
- ass->sizeItems = 0;
- return (-1);
- }
- }
- /* ass->items[ass->nbItems++] = (void *) item; */
- ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
- return (0);
-}
+#define WXS_INIT_GLOBAL_HASH(ctx, tbl) \
+if (*(tbl) == NULL) *(tbl) = xmlHashCreateDict(10, (ctx)->dict); \
+if (*(tbl) == NULL) { if (ret != NULL) xmlFree(ret); return (NULL); }
/**
* xmlSchemaAddNotation:
@@ -4523,41 +4519,37 @@
const xmlChar *name)
{
xmlSchemaNotationPtr ret = NULL;
+ xmlHashTablePtr *table = NULL;
int val;
if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
return (NULL);
- if (schema->notaDecl == NULL)
- schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
- if (schema->notaDecl == NULL)
- return (NULL);
+ WXS_GET_GLOBAL_HASH(WXS_SCHEMA_BUCKET(ctxt), schema, notaDecl)
+ WXS_INIT_GLOBAL_HASH(ctxt, table)
ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
if (ret == NULL) {
xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
return (NULL);
}
memset(ret, 0, sizeof(xmlSchemaNotation));
+ ret->type = XML_SCHEMA_TYPE_NOTATION;
ret->name = xmlDictLookup(ctxt->dict, name, -1);
- val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
- ret);
+
+ val = xmlHashAddEntry(*table, ret->name, ret);
if (val != 0) {
- /*
- * TODO: This should never happen, since a unique name will be computed.
- * If it fails, then an other internal error must have occured.
- */
xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
- XML_SCHEMAP_REDEFINED_NOTATION,
- "Annotation declaration '%s' is already declared.\n",
- name, NULL);
+ XML_SCHEMAP_REDEFINED_NOTATION,
+ "A notation declaration with the name '%s' does already exist.\n",
+ name, NULL);
xmlFree(ret);
return (NULL);
}
+ ADD_GLOBAL_ITEM(ctxt, ret);
return (ret);
}
-
/**
* xmlSchemaAddAttribute:
* @ctxt: a schema parser context
@@ -4572,24 +4564,14 @@
*/
static xmlSchemaAttributePtr
xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
- const xmlChar * name, const xmlChar * namespace,
+ const xmlChar * name, const xmlChar * nsName,
xmlNodePtr node, int topLevel)
{
xmlSchemaAttributePtr ret = NULL;
int val;
+ xmlHashTablePtr *table;
- if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
- return (NULL);
-
-#ifdef DEBUG
- fprintf(stderr, "Adding attribute %s\n", name);
- if (namespace != NULL)
- fprintf(stderr, " target namespace %s\n", namespace);
-#endif
-
- if (schema->attrDecl == NULL)
- schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
- if (schema->attrDecl == NULL)
+ if ((ctxt == NULL) || (schema == NULL))
return (NULL);
ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
@@ -4599,11 +4581,13 @@
}
memset(ret, 0, sizeof(xmlSchemaAttribute));
ret->name = xmlDictLookup(ctxt->dict, name, -1);
- ret->targetNamespace = namespace;
- val = xmlHashAddEntry3(schema->attrDecl, name,
- namespace, ctxt->container, ret);
- if (val != 0) {
- if (topLevel) {
+ ret->targetNamespace = nsName;
+
+ if (topLevel) {
+ WXS_GET_GLOBAL_HASH(WXS_SCHEMA_BUCKET(ctxt), schema, attrDecl)
+ WXS_INIT_GLOBAL_HASH(ctxt, table)
+ val = xmlHashAddEntry(*table, name, ret);
+ if (val != 0) {
xmlSchemaPCustomErr(ctxt,
XML_SCHEMAP_REDEFINED_ATTR,
NULL, NULL, node,
@@ -4611,36 +4595,11 @@
"already exist", name);
xmlFree(ret);
return (NULL);
- } else {
- char buf[30];
- /*
- * Using the ctxt->container for xmlHashAddEntry3 is ambigious
- * in the scenario:
- * 1. multiple top-level complex types have different target
- * namespaces but have the SAME NAME; this can happen if
- * schemata are imported
- * 2. those complex types contain attributes with an equal name
- * 3. those attributes are in no namespace
- * We will compute a new context string.
- */
- snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
- val = xmlHashAddEntry3(schema->attrDecl, name,
- namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
-
- if (val != 0) {
- xmlSchemaPCustomErr(ctxt,
- XML_SCHEMAP_INTERNAL,
- NULL, NULL, node,
- "Internal error: xmlSchemaAddAttribute, "
- "a dublicate attribute declaration with the name '%s' "
- "could not be added to the hash.", name);
- xmlFree(ret);
- return (NULL);
- }
}
- }
- if (ctxt->assemble != NULL)
- xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
+ ADD_GLOBAL_ITEM(ctxt, ret);
+ } else
+ ADD_LOCAL_ITEM(ctxt, ret);
+ WXS_ADD_PENDING_ITEM(ctxt, ret);
return (ret);
}
@@ -4656,41 +4615,51 @@
*/
static xmlSchemaAttributeGroupPtr
xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
- xmlSchemaPtr schema, const xmlChar * name,
- xmlNodePtr node)
+ xmlSchemaPtr schema,
+ const xmlChar * name,
+ xmlNodePtr node,
+ int topLevel)
{
xmlSchemaAttributeGroupPtr ret = NULL;
+ xmlHashTablePtr *table = NULL;
int val;
- if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
+ if ((ctxt == NULL) || (schema == NULL))
return (NULL);
- if (schema->attrgrpDecl == NULL)
- schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
- if (schema->attrgrpDecl == NULL)
- return (NULL);
-
- ret =
- (xmlSchemaAttributeGroupPtr)
+ ret = (xmlSchemaAttributeGroupPtr)
xmlMalloc(sizeof(xmlSchemaAttributeGroup));
if (ret == NULL) {
- xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
- return (NULL);
+ xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
+ return (NULL);
}
memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
- ret->name = xmlDictLookup(ctxt->dict, name, -1);
- val = xmlHashAddEntry3(schema->attrgrpDecl, name,
- schema->targetNamespace, ctxt->container, ret);
- if (val != 0) {
- xmlSchemaPCustomErr(ctxt,
- XML_SCHEMAP_REDEFINED_ATTRGROUP,
- NULL, NULL, node,
- "A global attribute group definition with the name '%s' does already exist", name);
- xmlFree(ret);
- return (NULL);
- }
- if (ctxt->assemble != NULL)
- xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
+ ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
+ ret->node = node;
+
+ if (topLevel) {
+ ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
+ ret->name = xmlDictLookup(ctxt->dict, name, -1);
+ ret->targetNamespace = ctxt->targetNamespace;
+
+ WXS_GET_GLOBAL_HASH(WXS_SCHEMA_BUCKET(ctxt), schema, attrgrpDecl)
+ WXS_INIT_GLOBAL_HASH(ctxt, table)
+
+ val = xmlHashAddEntry(*table, name, ret);
+ if (val != 0) {
+ xmlSchemaPCustomErr(ctxt,
+ XML_SCHEMAP_REDEFINED_ATTRGROUP,
+ NULL, NULL, node,
+ "A global attribute group definition with the name '%s' "
+ "does already exist", name);
+ xmlFree(ret);
+ return (NULL);
+ }
+ ADD_GLOBAL_ITEM(ctxt, ret);
+ } else
+ ADD_LOCAL_ITEM(ctxt, ret);
+
+ WXS_ADD_PENDING_ITEM(ctxt, ret);
return (ret);
}
@@ -4708,26 +4677,16 @@
*/
static xmlSchemaElementPtr
xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
- const xmlChar * name, const xmlChar * namespace,
+ const xmlChar * name, const xmlChar * nsName,
xmlNodePtr node, int topLevel)
{
xmlSchemaElementPtr ret = NULL;
+ xmlHashTablePtr *table = NULL;
int val;
if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
return (NULL);
-#ifdef DEBUG
- fprintf(stderr, "Adding element %s\n", name);
- if (namespace != NULL)
- fprintf(stderr, " target namespace %s\n", namespace);
-#endif
-
- if (schema->elemDecl == NULL)
- schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
- if (schema->elemDecl == NULL)
- return (NULL);
-
ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
if (ret == NULL) {
xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
@@ -4735,38 +4694,25 @@
}
memset(ret, 0, sizeof(xmlSchemaElement));
ret->name = xmlDictLookup(ctxt->dict, name, -1);
- val = xmlHashAddEntry3(schema->elemDecl, name,
- namespace, ctxt->container, ret);
- if (val != 0) {
- if (topLevel) {
+ ret->targetNamespace = nsName;
+
+ if (topLevel) {
+ WXS_GET_GLOBAL_HASH(WXS_SCHEMA_BUCKET(ctxt), schema, elemDecl)
+ WXS_INIT_GLOBAL_HASH(ctxt, table)
+ val = xmlHashAddEntry(*table, name, ret);
+ if (val != 0) {
xmlSchemaPCustomErr(ctxt,
XML_SCHEMAP_REDEFINED_ELEMENT,
NULL, NULL, node,
"A global element declaration with the name '%s' does "
"already exist", name);
- xmlFree(ret);
- return (NULL);
- } else {
- char buf[30];
-
- snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
- val = xmlHashAddEntry3(schema->elemDecl, name,
- namespace, (xmlChar *) buf, ret);
- if (val != 0) {
- xmlSchemaPCustomErr(ctxt,
- XML_SCHEMAP_INTERNAL,
- NULL, NULL, node,
- "Internal error: xmlSchemaAddElement, "
- "a dublicate element declaration with the name '%s' "
- "could not be added to the hash.", name);
- xmlFree(ret);
- return (NULL);
- }
+ xmlFree(ret);
+ return (NULL);
}
-
- }
- if (ctxt->assemble != NULL)
- xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
+ ADD_GLOBAL_ITEM(ctxt, ret);
+ } else
+ ADD_LOCAL_ITEM(ctxt, ret);
+ WXS_ADD_PENDING_ITEM(ctxt, ret);
return (ret);
}
@@ -4788,14 +4734,10 @@
xmlNodePtr node, int topLevel)
{
xmlSchemaTypePtr ret = NULL;
+ xmlHashTablePtr *table = NULL;
int val;
- if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
- return (NULL);
-
- if (schema->typeDecl == NULL)
- schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
- if (schema->typeDecl == NULL)
+ if ((ctxt == NULL) || (schema == NULL))
return (NULL);
ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
@@ -4804,58 +4746,58 @@
return (NULL);
}
memset(ret, 0, sizeof(xmlSchemaType));
- ret->name = xmlDictLookup(ctxt->dict, name, -1);
- ret->redef = NULL;
- val = xmlHashAddEntry2(schema->typeDecl, name, nsName, ret);
- if (val != 0) {
- if (! ctxt->isRedefine) {
- xmlChar *str = NULL;
- if (topLevel) {
+ if (name != NULL)
+ ret->name = xmlDictLookup(ctxt->dict, name, -1);
+ ret->targetNamespace = nsName;
+ ret->node = node;
+ /* TODO: Get rid of occurences here. */
+ ret->minOccurs = 1;
+ ret->maxOccurs = 1;
+
+ if (topLevel) {
+ WXS_GET_GLOBAL_HASH(WXS_SCHEMA_BUCKET(ctxt), schema, typeDecl)
+ WXS_INIT_GLOBAL_HASH(ctxt, table)
+ val = xmlHashAddEntry(*table, name, ret);
+ if (val != 0) {
+ if (! ctxt->isRedefine) {
+ xmlChar *str = NULL;
+
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;
-
- /*
- * REDEFINE: Add a redefinition.
- */
- TODO
- prev = xmlHashLookup2(schema->typeDecl, name, nsName);
- if (prev == NULL) {
- PERROR_INT2("xmlSchemaAddType", "hash list didn't return "
- "a type component, but should");
- xmlFree(ret);
+ FREE_AND_NULL(str);
+ xmlFree(ret);
return (NULL);
+ } else {
+ xmlSchemaTypePtr prev;
+
+ /* REDEFINE: Add a redefinition. */
+ TODO
+ prev = xmlHashLookup(*table, name);
+ if (prev == NULL) {
+ PERROR_INT2("xmlSchemaAddType", "hash list did not "
+ "return a redefined type component, but should");
+ xmlFree(ret);
+ return (NULL);
+ }
+ ret->redef = prev->redef;
+ prev->redef = ret;
+ /* TODO: Add to locals; dunno if this will make trouble. */
+ ADD_LOCAL_ITEM(ctxt, ret);
}
- ret->redef = prev->redef;
- prev->redef = ret;
- }
- }
- ret->node = node;
- ret->minOccurs = 1;
- ret->maxOccurs = 1;
- ret->attributeUses = NULL;
- ret->attributeWildcard = NULL;
- if (ctxt->assemble != NULL)
- xmlSchemaAddAssembledItem(ctxt,ret);
+ } else
+ ADD_GLOBAL_ITEM(ctxt, ret);
+ } else
+ ADD_LOCAL_ITEM(ctxt, ret);
+ WXS_ADD_PENDING_ITEM(ctxt, ret);
return (ret);
}
static xmlSchemaQNameRefPtr
-xmlSchemaNewQNameRef(xmlSchemaPtr schema,
+xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
xmlSchemaTypeType refType,
const xmlChar *refName,
const xmlChar *refNs)
@@ -4865,8 +4807,8 @@
ret = (xmlSchemaQNameRefPtr)
xmlMalloc(sizeof(xmlSchemaQNameRef));
if (ret == NULL) {
- xmlSchemaPErrMemory(NULL, "allocating QName reference item",
- NULL);
+ xmlSchemaPErrMemory(pctxt,
+ "allocating QName reference item", NULL);
return (NULL);
}
ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
@@ -4877,7 +4819,7 @@
/*
* Store the reference item in the schema.
*/
- xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
+ ADD_LOCAL_ITEM(pctxt, ret);
return (ret);
}
@@ -4886,7 +4828,6 @@
* @ctxt: a schema parser context
* @schema: the schema being built
* @type: the "compositor" type of the model group
- * @container: the internal component name
* @node: the node in the schema doc
*
* Adds a schema model group
@@ -4895,19 +4836,16 @@
* Returns the new struture or NULL in case of error
*/
static xmlSchemaModelGroupPtr
-xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
- xmlSchemaTypeType type, const xmlChar **container,
- xmlNodePtr node)
+xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
+ xmlSchemaPtr schema,
+ xmlSchemaTypeType type,
+ xmlNodePtr node)
{
xmlSchemaModelGroupPtr ret = NULL;
- xmlChar buf[30];
if ((ctxt == NULL) || (schema == NULL))
return (NULL);
-#ifdef DEBUG
- fprintf(stderr, "Adding model group component\n");
-#endif
ret = (xmlSchemaModelGroupPtr)
xmlMalloc(sizeof(xmlSchemaModelGroup));
if (ret == NULL) {
@@ -4915,31 +4853,10 @@
NULL);
return (NULL);
}
+ memset(ret, 0, sizeof(xmlSchemaModelGroup));
ret->type = type;
- ret->annot = NULL;
ret->node = node;
- ret->children = NULL;
- ret->next = NULL;
- if (type == XML_SCHEMA_TYPE_SEQUENCE) {
- if (container != NULL)
- snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
- } else if (type == XML_SCHEMA_TYPE_CHOICE) {
- if (container != NULL)
- snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
- } else {
- if (container != NULL)
- snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
- }
- if (container != NULL)
- *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
- /*
- * Add to volatile items.
- * TODO: this should be changed someday.
- */
- if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
- xmlFree(ret);
- return (NULL);
- }
+ ADD_LOCAL_ITEM(ctxt, ret);
return (ret);
}
@@ -4983,15 +4900,18 @@
ret->next = NULL;
ret->children = NULL;
- if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
- xmlFree(ret);
- return (NULL);
- }
+ ADD_LOCAL_ITEM(ctxt, ret);
+ /*
+ * Note that addition to pending components will be done locally
+ * to the specific parsing function, since the most particles
+ * need not to be fixed up (i.e. the reference to be resolved).
+ * REMOVED: WXS_ADD_PENDING_ITEM(ctxt, ret);
+ */
return (ret);
}
/**
- * xmlSchemaAddGroup:
+ * xmlSchemaAddModelGroupDefinition:
* @ctxt: a schema validation context
* @schema: the schema being built
* @name: the group name
@@ -5001,22 +4921,24 @@
* Returns the new struture or NULL in case of error
*/
static xmlSchemaModelGroupDefPtr
-xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
- const xmlChar *name, const xmlChar *namespaceName,
- xmlNodePtr node)
+xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
+ xmlSchemaPtr schema,
+ const xmlChar *name,
+ const xmlChar *nsName,
+ xmlNodePtr node)
{
xmlSchemaModelGroupDefPtr ret = NULL;
+ xmlHashTablePtr *table = NULL;
int val;
if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
return (NULL);
- if (schema->groupDecl == NULL)
- schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
- if (schema->groupDecl == NULL)
- return (NULL);
+ WXS_GET_GLOBAL_HASH(WXS_SCHEMA_BUCKET(ctxt), schema, groupDecl)
+ WXS_INIT_GLOBAL_HASH(ctxt, table)
- ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
+ ret = (xmlSchemaModelGroupDefPtr)
+ xmlMalloc(sizeof(xmlSchemaModelGroupDef));
if (ret == NULL) {
xmlSchemaPErrMemory(ctxt, "adding group", NULL);
return (NULL);
@@ -5025,19 +4947,20 @@
ret->name = xmlDictLookup(ctxt->dict, name, -1);
ret->type = XML_SCHEMA_TYPE_GROUP;
ret->node = node;
- ret->targetNamespace = namespaceName;
- val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
+ ret->targetNamespace = nsName;
+
+ val = xmlHashAddEntry(*table, ret->name, ret);
if (val != 0) {
xmlSchemaPCustomErr(ctxt,
XML_SCHEMAP_REDEFINED_GROUP,
NULL, NULL, node,
- "A global model group definition with the name '%s' does already "
- "exist", name);
+ "A global model group definition with the name '%s' does "
+ "already exist", name);
xmlFree(ret);
return (NULL);
}
- if (ctxt->assemble != NULL)
- xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
+ ADD_GLOBAL_ITEM(ctxt, ret);
+ WXS_ADD_PENDING_ITEM(ctxt, ret);
return (ret);
}
@@ -5065,6 +4988,56 @@
return (ret);
}
+static xmlSchemaIDCPtr
+xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+ const xmlChar *name, const xmlChar *nsName,
+ int category, xmlNodePtr node)
+{
+ xmlSchemaIDCPtr ret = NULL;
+ xmlHashTablePtr *table = NULL;
+ int val;
+
+ if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
+ return (NULL);
+
+ WXS_GET_GLOBAL_HASH(WXS_SCHEMA_BUCKET(ctxt), schema, idcDef)
+ WXS_INIT_GLOBAL_HASH(ctxt, table)
+
+ ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
+ if (ret == NULL) {
+ xmlSchemaPErrMemory(ctxt,
+ "allocating an identity-constraint definition", NULL);
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(xmlSchemaIDC));
+ /* The target namespace of the parent element declaration. */
+ ret->targetNamespace = nsName;
+ ret->name = name;
+ ret->type = category;
+ ret->node = node;
+
+ val = xmlHashAddEntry(*table, ret->name, ret);
+ if (val != 0) {
+ xmlSchemaPCustomErrExt(ctxt,
+ /* TODO: Error code! */
+ XML_SCHEMAP_REDEFINED_TYPE,
+ NULL, NULL, node,
+ "An identity-constraint definition with the name '%s' "
+ "and targetNamespace '%s' does already exist",
+ ret->name, ret->targetNamespace, NULL);
+
+ xmlFree(ret);
+ return (NULL);
+ }
+ ADD_GLOBAL_ITEM(ctxt, ret);
+ /*
+ * Only keyrefs need to be fixup up.
+ */
+ if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
+ WXS_ADD_PENDING_ITEM(ctxt, ret);
+ return (ret);
+}
+
/**
* xmlSchemaAddWildcard:
* @ctxt: a schema validation context
@@ -5084,10 +5057,6 @@
if ((ctxt == NULL) || (schema == NULL))
return (NULL);
-#ifdef DEBUG
- fprintf(stderr, "Adding wildcard component\n");
-#endif
-
ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
if (ret == NULL) {
xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
@@ -5095,84 +5064,109 @@
}
memset(ret, 0, sizeof(xmlSchemaWildcard));
ret->type = type;
+ ret->node = node;
ret->minOccurs = 1;
- ret->maxOccurs = 1;
-
- if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
- xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
- "Failed to add a wildcard component to the list", NULL);
- xmlFree(ret);
- return (NULL);
- }
+ ret->maxOccurs = 1;
+
+ ADD_LOCAL_ITEM(ctxt, ret);
return (ret);
}
+static void
+xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
+{
+ if (group == NULL)
+ return;
+ if (group->members != NULL)
+ xmlSchemaItemListFree(group->members);
+ xmlFree(group);
+}
+
+static xmlSchemaSubstGroupPtr
+xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
+ xmlSchemaElementPtr head)
+{
+ xmlSchemaSubstGroupPtr ret;
+
+ /* Init subst group hash. */
+ if (WXS_SUBST_GROUPS(pctxt) == NULL) {
+ WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
+ if (WXS_SUBST_GROUPS(pctxt) == NULL)
+ return(NULL);
+ }
+ /* Create a new substitution group. */
+ ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
+ if (ret == NULL) {
+ xmlSchemaPErrMemory(NULL,
+ "allocating a substitution group container", NULL);
+ return(NULL);
+ }
+ memset(ret, 0, sizeof(xmlSchemaSubstGroup));
+ ret->head = head;
+ /* Create list of members. */
+ ret->members = xmlSchemaItemListCreate();
+ if (ret->members == NULL) {
+ xmlSchemaSubstGroupFree(ret);
+ return(NULL);
+ }
+ /* Add subst group to hash. */
+ if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
+ head->name, head->targetNamespace, ret) != 0) {
+ PERROR_INT("xmlSchemaSubstGroupAdd",
+ "failed to add a new substitution container");
+ xmlSchemaSubstGroupFree(ret);
+ return(NULL);
+ }
+ return(ret);
+}
+
+static xmlSchemaSubstGroupPtr
+xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
+ xmlSchemaElementPtr head)
+{
+ if (WXS_SUBST_GROUPS(pctxt) == NULL)
+ return(NULL);
+ return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
+ head->name, head->targetNamespace));
+
+}
+
+/**
+ * xmlSchemaAddElementSubstitutionMember:
+ * @pctxt: a schema parser context
+ * @head: the head of the substitution group
+ * @member: the new member of the substitution group
+ *
+ * Allocate a new annotation structure.
+ *
+ * Returns the newly allocated structure or NULL in case or error
+ */
+static int
+xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
+ xmlSchemaElementPtr head,
+ xmlSchemaElementPtr member)
+{
+ xmlSchemaSubstGroupPtr substGroup = NULL;
+
+ if ((pctxt == NULL) || (head == NULL) || (member == NULL))
+ return (-1);
+
+ substGroup = xmlSchemaSubstGroupGet(pctxt, head);
+ if (substGroup == NULL)
+ substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
+ if (substGroup == NULL)
+ return(-1);
+ if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
+ return(-1);
+ return(0);
+}
+
/************************************************************************
* *
* Utilities for parsing *
* *
************************************************************************/
-#if 0
-/**
- * xmlGetQNameProp:
- * @ctxt: a schema validation context
- * @node: a subtree containing XML Schema informations
- * @name: the attribute name
- * @namespace: the result namespace if any
- *
- * Extract a QName Attribute value
- *
- * Returns the NCName or NULL if not found, and also update @namespace
- * with the namespace URI
- */
-static const xmlChar *
-xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
- const char *name, const xmlChar ** namespace)
-{
- const xmlChar *val;
- xmlNsPtr ns;
- const xmlChar *ret, *prefix;
- int len;
- xmlAttrPtr attr;
-
- *namespace = NULL;
- attr = xmlSchemaGetPropNode(node, name);
- if (attr == NULL)
- return (NULL);
- val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
-
- if (val == NULL)
- return (NULL);
-
- if (!strchr((char *) val, ':')) {
- ns = xmlSearchNs(node->doc, node, 0);
- if (ns) {
- *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
- return (val);
- }
- }
- ret = xmlSplitQName3(val, &len);
- if (ret == NULL) {
- return (val);
- }
- ret = xmlDictLookup(ctxt->dict, ret, -1);
- prefix = xmlDictLookup(ctxt->dict, val, len);
-
- ns = xmlSearchNs(node->doc, node, prefix);
- if (ns == NULL) {
- xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
- NULL, NULL, (xmlNodePtr) attr,
- xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
- "The QName value '%s' has no corresponding namespace "
- "declaration in scope", val, NULL);
- } else {
- *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
- }
- return (ret);
-}
-#endif
-
/**
* xmlSchemaPValAttrNodeQNameValue:
* @ctxt: a schema parser context
@@ -5223,11 +5217,13 @@
if (ns)
*uri = xmlDictLookup(ctxt->dict, ns->href, -1);
else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
+ /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
+ * parser context. */
/*
* This one takes care of included schemas with no
* target namespace.
*/
- *uri = schema->targetNamespace;
+ *uri = ctxt->targetNamespace;
}
*local = xmlDictLookup(ctxt->dict, value, -1);
return (0);
@@ -5817,21 +5813,33 @@
static int
xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
- xmlSchemaPtr schema,
+ xmlSchemaPtr schema ATTRIBUTE_UNUSED,
xmlNodePtr node,
xmlSchemaBasicItemPtr item,
const xmlChar *namespaceName)
{
- if (xmlStrEqual(schema->targetNamespace, namespaceName))
+ /* TODO: Pointer comparison instead? */
+ if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
return (1);
if (xmlStrEqual(xmlSchemaNs, namespaceName))
return (1);
- if (pctxt->localImports != NULL) {
- int i;
- for (i = 0; i < pctxt->nbLocalImports; i++)
- if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
+ /*
+ * Check if the referenced namespace was <import>ed.
+ */
+ if (WXS_SCHEMA_BUCKET(pctxt)->relations != NULL) {
+ xmlSchemaSchemaRelationPtr rel;
+
+ rel = WXS_SCHEMA_BUCKET(pctxt)->relations;
+ do {
+ if (WXS_IS_IMPMAIN(rel->type) &&
+ xmlStrEqual(namespaceName, rel->importNamespace))
return (1);
+ rel = rel->next;
+ } while (rel != NULL);
}
+ /*
+ * No matching <import>ed namespace found.
+ */
if (namespaceName == NULL)
xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
NULL, (xmlSchemaTypePtr) item, node,
@@ -6119,7 +6127,7 @@
*/
static int
xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
- xmlSchemaPtr schema,
+ xmlSchemaPtr schema ATTRIBUTE_UNUSED,
xmlSchemaWildcardPtr wildc,
xmlNodePtr node)
{
@@ -6158,7 +6166,7 @@
if (wildc->negNsSet == NULL) {
return (-1);
}
- wildc->negNsSet->value = schema->targetNamespace;
+ wildc->negNsSet->value = ctxt->targetNamespace;
} else {
const xmlChar *end, *cur;
@@ -6184,7 +6192,7 @@
ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
} else {
if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
- dictnsItem = schema->targetNamespace;
+ dictnsItem = ctxt->targetNamespace;
} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
dictnsItem = NULL;
} else {
@@ -6400,7 +6408,7 @@
if (ret == NULL) {
return (NULL);
}
- ret->targetNamespace = schema->targetNamespace;
+ ret->targetNamespace = ctxt->targetNamespace;
xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
node, BAD_CAST "id");
@@ -6552,7 +6560,9 @@
isRef = 1;
if (isRef) {
+#ifdef ENABLE_NAMED_LOCALS
char buf[50];
+#endif
const xmlChar *refNs = NULL, *ref = NULL;
/*
@@ -6563,9 +6573,14 @@
&ref) != 0) {
return (NULL);
}
+#ifdef ENABLE_NAMED_LOCALS
snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
name = (const xmlChar *) buf;
ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
+#else
+ ret = xmlSchemaAddAttribute(ctxt, schema, NULL, NULL, node, 0);
+#endif
+
if (ret == NULL) {
if (repName != NULL)
xmlFree(repName);
@@ -6650,13 +6665,13 @@
* Evaluate the target namespace
*/
if (topLevel) {
- ns = schema->targetNamespace;
+ ns = ctxt->targetNamespace;
} else {
attr = xmlSchemaGetPropNode(node, "form");
if (attr != NULL) {
attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
- ns = schema->targetNamespace;
+ ns = ctxt->targetNamespace;
} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
@@ -6665,7 +6680,8 @@
attrValue, NULL, NULL, NULL);
}
} else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
- ns = schema->targetNamespace;
+ /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
+ ns = ctxt->targetNamespace;
}
ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
if (ret == NULL) {
@@ -6847,7 +6863,6 @@
const xmlChar *name;
xmlSchemaAttributeGroupPtr ret;
xmlNodePtr child = NULL;
- const xmlChar *oldcontainer;
xmlAttrPtr attr, nameAttr;
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
@@ -6877,15 +6892,13 @@
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
return (NULL);
}
- ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
+ ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node, 1);
if (ret == NULL)
- return (NULL);
- ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
- ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
- ret->node = node;
- ret->targetNamespace = schema->targetNamespace;
+ return (NULL);
} else {
+#ifdef ENABLE_NAMED_LOCALS
char buf[50];
+#endif
const xmlChar *refNs = NULL, *ref = NULL;
/*
@@ -6898,7 +6911,7 @@
}
xmlSchemaPValAttrNodeQName(ctxt, schema,
NULL, NULL, attr, &refNs,&ref);
-
+#ifdef ENABLE_NAMED_LOCALS
snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
name = (const xmlChar *) buf;
if (name == NULL) {
@@ -6906,13 +6919,14 @@
"attribute group definition reference", node);
return (NULL);
}
- ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
+ ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node, 0);
+#else
+ ret = xmlSchemaAddAttributeGroup(ctxt, schema, NULL, node, 0);
+#endif
if (ret == NULL)
return (NULL);
- ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
ret->ref = ref;
ret->refNs = refNs;
- ret->node = node;
xmlSchemaCheckReference(ctxt, schema, node,
(xmlSchemaBasicItemPtr) ret, refNs);
}
@@ -6922,7 +6936,8 @@
attr = node->properties;
while (attr != NULL) {
if (attr->ns == NULL) {
- if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
+ if ((((topLevel == 0) &&
+ (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
(topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
(!xmlStrEqual(attr->name, BAD_CAST "id")))
{
@@ -6937,21 +6952,23 @@
}
attr = attr->next;
}
- /* TODO: Validate "id" ? */
+ /* Attribute ID */
+ xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
+ node, BAD_CAST "id");
/*
* And now for the children...
*/
- oldcontainer = ctxt->container;
- ctxt->container = name;
child = node->children;
if (IS_SCHEMA(child, "annotation")) {
ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
child = child->next;
}
if (topLevel) {
- child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
+ child = xmlSchemaParseAttrDecls(ctxt, schema, child,
+ (xmlSchemaTypePtr) ret);
if (IS_SCHEMA(child, "anyAttribute")) {
- ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
+ ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt,
+ schema, child);
child = child->next;
}
}
@@ -6961,7 +6978,6 @@
NULL, NULL, node, child, NULL,
"(annotation?)");
}
- ctxt->container = oldcontainer;
return (ret);
}
@@ -7419,7 +7435,6 @@
xmlAttrPtr attr;
const xmlChar *name = NULL;
xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
- int resAdd;
/*
* Check for illegal attributes.
@@ -7457,44 +7472,12 @@
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
return (NULL);
}
- /*
- * Create the component.
- */
- if (schema->idcDef == NULL)
- schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
- if (schema->idcDef == NULL)
- return (NULL);
+ /* Create the component. */
+ item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
+ idcCategory, node);
+ if (item == NULL)
+ return(NULL);
- item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
- if (item == NULL) {
- xmlSchemaPErrMemory(ctxt,
- "allocating an identity-constraint definition", NULL);
- return (NULL);
- }
- /*
- * Add the IDC to the list of IDCs on the schema component.
- */
- resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
- if (resAdd != 0) {
- xmlSchemaPCustomErrExt(ctxt,
- XML_SCHEMAP_REDEFINED_TYPE,
- NULL, NULL, node,
- "An identity-constraint definition with the name '%s' "
- "and targetNamespace '%s' does already exist",
- name, targetNamespace, NULL);
- xmlFree(item);
- return (NULL);
- }
- memset(item, 0, sizeof(xmlSchemaIDC));
- item->name = name;
- item->type = idcCategory;
- item->node = node;
- if (ctxt->assemble != NULL)
- xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
- /*
- * The target namespace of the parent element declaration.
- */
- item->targetNamespace = targetNamespace;
xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
node, BAD_CAST "id");
if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
@@ -7511,7 +7494,7 @@
/*
* Create a reference item.
*/
- item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
+ item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
NULL, NULL);
if (item->ref == NULL)
return (NULL);
@@ -7710,18 +7693,17 @@
/*
* Create the reference item.
*/
- refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
+ refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
ref, refNs);
if (refer == NULL)
goto return_null;
particle->children = (xmlSchemaTreeItemPtr) refer;
particle->annot = annot;
/*
- * Add to assembled items; the reference need to be resolved.
+ * Add the particle to pending components, since the reference
+ * need to be resolved.
*/
- if (ctxt->assemble != NULL)
- xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
-
+ WXS_ADD_PENDING_ITEM(ctxt, particle);
return ((xmlSchemaBasicItemPtr) particle);
}
/*
@@ -7729,7 +7711,7 @@
*/
declaration_part:
{
- const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
+ const xmlChar *ns = NULL, *fixed, *name, *attrValue;
xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
@@ -7739,13 +7721,13 @@
* Evaluate the target namespace.
*/
if (topLevel) {
- ns = schema->targetNamespace;
+ ns = ctxt->targetNamespace;
} else {
attr = xmlSchemaGetPropNode(node, "form");
if (attr != NULL) {
attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
- ns = schema->targetNamespace;
+ ns = ctxt->targetNamespace;
} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
@@ -7754,7 +7736,7 @@
attrValue, NULL, NULL, NULL);
}
} else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
- ns = schema->targetNamespace;
+ ns = ctxt->targetNamespace;
}
decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
if (decl == NULL) {
@@ -7903,8 +7885,6 @@
/*
* And now for the children...
*/
- oldcontainer = ctxt->container;
- ctxt->container = decl->name;
if (IS_SCHEMA(child, "complexType")) {
/*
* 3.3.3 : 3
@@ -7962,7 +7942,6 @@
NULL, "(annotation?, ((simpleType | complexType)?, "
"(unique | key | keyref)*))");
}
- ctxt->container = oldcontainer;
decl->annot = annot;
}
/*
@@ -8088,7 +8067,7 @@
/*
* Create a reference item.
*/
- ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
+ ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
localName, nsName);
if (ref == NULL) {
FREE_AND_NULL(tmp)
@@ -8332,19 +8311,29 @@
}
}
}
-
+ /*
+ * TargetNamespace:
+ * SPEC "The ·actual value· of the targetNamespace [attribute]
+ * of the <schema> ancestor element information item if present,
+ * otherwise ·absent·.
+ */
if (topLevel == 0) {
+#ifdef ENABLE_NAMED_LOCALS
char buf[40];
-
+#endif
/*
* Parse as local simple type definition.
*/
+#ifdef ENABLE_NAMED_LOCALS
snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
- type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL,
- node, 0);
+ type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf,
+ ctxt->targetNamespace, node, 0);
+#else
+ type = xmlSchemaAddType(ctxt, schema, NULL,
+ ctxt->targetNamespace, node, 0);
+#endif
if (type == NULL)
return (NULL);
- type->node = node;
type->type = XML_SCHEMA_TYPE_SIMPLE;
type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
/*
@@ -8372,10 +8361,9 @@
* Note that attrValue is the value of the attribute "name" here.
*/
type = xmlSchemaAddType(ctxt, schema, attrValue,
- schema->targetNamespace, node, 1);
+ ctxt->targetNamespace, node, 1);
if (type == NULL)
return (NULL);
- type->node = node;
type->type = XML_SCHEMA_TYPE_SIMPLE;
type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
@@ -8425,7 +8413,7 @@
}
}
}
- type->targetNamespace = schema->targetNamespace;
+ type->targetNamespace = ctxt->targetNamespace;
xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
/*
* And now for the children...
@@ -8543,12 +8531,14 @@
item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
if (item == NULL)
return (NULL);
+ /* Add to pending components; the reference needs to be resolved. */
+ WXS_ADD_PENDING_ITEM(ctxt, item);
/*
* Create a reference item as the term; it will be substituted for
* the model group after the reference has been resolved.
*/
item->children = (xmlSchemaTreeItemPtr)
- xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
+ xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
/*
@@ -8574,8 +8564,7 @@
*/
if ((min == 0) && (max == 0))
return (NULL);
- if (ctxt->assemble != NULL)
- xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
+
return ((xmlSchemaTreeItemPtr) item);
}
@@ -8616,7 +8605,8 @@
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
return (NULL);
}
- item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
+ item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
+ ctxt->targetNamespace, node);
if (item == NULL)
return (NULL);
/*
@@ -8772,55 +8762,82 @@
schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
}
-static void
-xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
+static int
+xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaPtr schema,
xmlNodePtr node)
{
xmlAttrPtr attr;
const xmlChar *val;
+ int res = 0, oldErrs = ctxt->nberrors;
- xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
- if (schema->version == NULL)
- xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
- xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
- else
- xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
- xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
+ /*
+ * Those flags should be moved to the parser context flags,
+ * since they are not visible at the component level. I.e.
+ * they are used if processing schema *documents* only.
+ */
+ res = xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
+ HFAILURE;
+ /*
+ * Since the version is of type xs:token, we won't bother to
+ * check it.
+ */
+ /* REMOVED:
+ attr = xmlSchemaGetPropNode(node, "version");
+ if (attr != NULL) {
+ res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
+ xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
+ HFAILURE;
+ }
+ */
+ attr = xmlSchemaGetPropNode(node, "targetNamespace");
+ if (attr != NULL) {
+ res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
+ xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
+ HFAILURE;
+ if (res != 0) {
+ ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
+ goto exit;
+ }
+ }
attr = xmlSchemaGetPropNode(node, "elementFormDefault");
if (attr != NULL) {
val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
- if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
- XML_SCHEMAS_QUALIF_ELEM) != 0) {
+ res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
+ XML_SCHEMAS_QUALIF_ELEM);
+ HFAILURE;
+ if (res != 0) {
xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
NULL, (xmlNodePtr) attr, NULL,
"(qualified | unqualified)", val, NULL, NULL, NULL);
}
}
-
attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
if (attr != NULL) {
val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
- if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
- XML_SCHEMAS_QUALIF_ATTR) != 0) {
+ res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
+ XML_SCHEMAS_QUALIF_ATTR);
+ HFAILURE;
+ if (res != 0) {
xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
NULL, (xmlNodePtr) attr, NULL,
"(qualified | unqualified)", val, NULL, NULL, NULL);
}
}
-
attr = xmlSchemaGetPropNode(node, "finalDefault");
if (attr != NULL) {
val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
- if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
+ res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
-1,
XML_SCHEMAS_FINAL_DEFAULT_LIST,
- XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
+ XML_SCHEMAS_FINAL_DEFAULT_UNION);
+ HFAILURE;
+ if (res != 0) {
xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
NULL, (xmlNodePtr) attr, NULL,
@@ -8828,21 +8845,29 @@
val, NULL, NULL, NULL);
}
}
-
attr = xmlSchemaGetPropNode(node, "blockDefault");
if (attr != NULL) {
- val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
- if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
+ val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
+ res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
- XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
- xmlSchemaPSimpleTypeErr(ctxt,
+ XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
+ HFAILURE;
+ if (res != 0) {
+ xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
NULL, (xmlNodePtr) attr, NULL,
"(#all | List of (extension | restriction | substitution))",
val, NULL, NULL, NULL);
}
}
+
+exit:
+ if (oldErrs != ctxt->nberrors)
+ res = ctxt->err;
+ return(res);
+exit_failure:
+ return(-1);
}
/**
@@ -8854,16 +8879,18 @@
* Returns the internal XML Schema structure built from the resource or
* NULL in case of error
*/
-static void
+static int
xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaPtr schema, xmlNodePtr nodes)
{
xmlNodePtr child;
xmlSchemaAnnotPtr annot;
+ int res = 0, oldErrs, tmpOldErrs;
if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
- return;
+ return(-1);
+ oldErrs = ctxt->nberrors;
child = nodes;
while ((IS_SCHEMA(child, "include")) ||
(IS_SCHEMA(child, "import")) ||
@@ -8876,20 +8903,33 @@
else
xmlSchemaFreeAnnot(annot);
} else if (IS_SCHEMA(child, "import")) {
- xmlSchemaParseImport(ctxt, schema, child);
+ tmpOldErrs = ctxt->nberrors;
+ res = xmlSchemaParseImport(ctxt, schema, child);
+ HFAILURE;
+ HSTOP(ctxt);
+ if (tmpOldErrs != ctxt->nberrors)
+ goto exit;
} else if (IS_SCHEMA(child, "include")) {
- ctxt->includes++;
- xmlSchemaParseInclude(ctxt, schema, child);
- ctxt->includes--;
+ tmpOldErrs = ctxt->nberrors;
+ res = xmlSchemaParseInclude(ctxt, schema, child);
+ HFAILURE;
+ HSTOP(ctxt);
+ if (tmpOldErrs != ctxt->nberrors)
+ goto exit;
} else if (IS_SCHEMA(child, "redefine")) {
-#ifdef ENABLE_REDEFINE
- xmlSchemaParseRedefine(ctxt, schema, child);
-#else
- TODO
-#endif
+ tmpOldErrs = ctxt->nberrors;
+ res = xmlSchemaParseRedefine(ctxt, schema, child);
+ HFAILURE;
+ HSTOP(ctxt);
+ if (tmpOldErrs != ctxt->nberrors)
+ goto exit;
}
child = child->next;
}
+ /*
+ * URGENT TODO: Change the functions to return int results.
+ * We need especially to catch internal errors.
+ */
while (child != NULL) {
if (IS_SCHEMA(child, "complexType")) {
xmlSchemaParseComplexType(ctxt, schema, child, 1);
@@ -8913,10 +8953,12 @@
xmlSchemaParseNotation(ctxt, schema, child);
child = child->next;
} else {
- xmlSchemaPErr2(ctxt, NULL, child,
- XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
- "Unexpected element \"%s\" as child of <schema>.\n",
- child->name, NULL);
+ xmlSchemaPContentErr(ctxt,
+ XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
+ NULL, NULL, child->parent, child,
+ NULL, "((include | import | redefine | annotation)*, "
+ "(((simpleType | complexType | group | attributeGroup) "
+ "| element | attribute | notation), annotation*)*)");
child = child->next;
}
while (IS_SCHEMA(child, "annotation")) {
@@ -8928,63 +8970,93 @@
child = child->next;
}
}
+exit:
ctxt->parentItem = NULL;
ctxt->ctxtType = NULL;
+ if (oldErrs != ctxt->nberrors)
+ res = ctxt->err;
+ return(res);
+exit_failure:
+ return(-1);
}
-static xmlSchemaImportPtr
-xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
- xmlHashTablePtr *imports,
- const xmlChar *nsName)
+static xmlSchemaSchemaRelationPtr
+xmlSchemaSchemaRelationCreate(void)
{
- xmlSchemaImportPtr ret;
+ xmlSchemaSchemaRelationPtr ret;
- if (*imports == NULL) {
- *imports = xmlHashCreateDict(10, ctxt->dict);
- if (*imports == NULL) {
- xmlSchemaPCustomErr(ctxt,
- XML_SCHEMAP_FAILED_BUILD_IMPORT,
- NULL, NULL, (xmlNodePtr) ctxt->doc,
- "Internal error: failed to build the import table",
- NULL);
- return (NULL);
- }
- }
- ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
+ ret = (xmlSchemaSchemaRelationPtr)
+ xmlMalloc(sizeof(xmlSchemaSchemaRelation));
if (ret == NULL) {
- xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
- return (NULL);
- }
- memset(ret, 0, sizeof(xmlSchemaImport));
- if (nsName == NULL)
- nsName = XML_SCHEMAS_NO_NAMESPACE;
- xmlHashAddEntry(*imports, nsName, ret);
-
- 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);
+ xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
return(NULL);
}
- memset(ret, 0, sizeof(xmlSchemaSchemaRef));
+ memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
return(ret);
}
+#if 0
static void
-xmlSchemaSchemaRefFree(xmlSchemaSchemaRefPtr ref)
+xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
{
- xmlFree(ref);
+ xmlFree(rel);
}
#endif
+static void
+xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
+{
+ /*
+ * After the construction context has been freed, there will be
+ * no schema graph available any more. Only the schema buckets
+ * will stay alive, which are put into the "schemasImports" and
+ * "includes" slots of the xmlSchema.
+ */
+ if (con->buckets != NULL)
+ xmlSchemaItemListFree(con->buckets);
+ if (con->pending != NULL)
+ xmlSchemaItemListFree(con->pending);
+ if (con->substGroups != NULL)
+ xmlHashFree(con->substGroups,
+ (xmlHashDeallocator) xmlSchemaSubstGroupFree);
+ if (con->dict != NULL)
+ xmlDictFree(con->dict);
+ xmlFree(con);
+}
+
+static xmlSchemaConstructionCtxtPtr
+xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
+{
+ xmlSchemaConstructionCtxtPtr ret;
+
+ ret = (xmlSchemaConstructionCtxtPtr)
+ xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
+ if (ret == NULL) {
+ xmlSchemaPErrMemory(NULL,
+ "allocating schema construction context", NULL);
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
+
+ ret->buckets = xmlSchemaItemListCreate();
+ if (ret->buckets == NULL) {
+ xmlSchemaPErrMemory(NULL,
+ "allocating list of schema buckets", NULL);
+ xmlFree(ret);
+ return (NULL);
+ }
+ ret->pending = xmlSchemaItemListCreate();
+ if (ret->pending == NULL) {
+ xmlSchemaPErrMemory(NULL,
+ "allocating list of pending global components", NULL);
+ xmlSchemaConstructionCtxtFree(ret);
+ return (NULL);
+ }
+ ret->dict = dict;
+ xmlDictReference(dict);
+ return(ret);
+}
+
static xmlSchemaParserCtxtPtr
xmlSchemaParserCtxtCreate(void)
{
@@ -8998,11 +9070,6 @@
}
memset(ret, 0, sizeof(xmlSchemaParserCtxt));
ret->type = XML_SCHEMA_CTXT_PARSER;
- ret->compContainer = xmlSchemaContainerCreate();
- if (ret->compContainer == NULL) {
- xmlSchemaFreeParserCtxt(ret);
- return(NULL);
- }
return(ret);
}
@@ -9028,7 +9095,6 @@
xmlDictReference(dict);
if (URL != NULL)
ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
- ret->includes = 0;
return (ret);
}
@@ -9037,7 +9103,8 @@
{
if (vctxt->pctxt == NULL) {
if (vctxt->schema != NULL)
- vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
+ vctxt->pctxt =
+ xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
else
vctxt->pctxt = xmlSchemaNewParserCtxt("*");
if (vctxt->pctxt == NULL) {
@@ -9046,293 +9113,677 @@
return (-1);
}
/* TODO: Pass user data. */
- xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
+ xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
+ vctxt->warning, vctxt->userData);
}
return (0);
}
+/**
+ * xmlSchemaGetSchemaBucket:
+ * @pctxt: the schema parser context
+ * @schemaLocation: the URI of the schema document
+ *
+ * Returns a schema bucket if it was already parsed.
+ *
+ * Returns a schema bucket if it was already parsed from
+ * @schemaLocation, NULL otherwise.
+ */
+static xmlSchemaBucketPtr
+xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
+ const xmlChar *schemaLocation)
+{
+ xmlSchemaBucketPtr cur;
+ xmlSchemaItemListPtr list;
+
+ list = pctxt->constructor->buckets;
+ if (list->nbItems == 0)
+ return(NULL);
+ else {
+ int i;
+ for (i = 0; i < list->nbItems; i++) {
+ cur = (xmlSchemaBucketPtr) list->items[i];
+ /* Pointer comparison! */
+ if (cur->schemaLocation == schemaLocation)
+ return(cur);
+ }
+ }
+ return(NULL);
+}
+
+static xmlSchemaBucketPtr
+xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
+ const xmlChar *schemaLocation,
+ const xmlChar *targetNamespace)
+{
+ xmlSchemaBucketPtr cur;
+ xmlSchemaItemListPtr list;
+
+ list = pctxt->constructor->buckets;
+ if (list->nbItems == 0)
+ return(NULL);
+ else {
+ int i;
+ for (i = 0; i < list->nbItems; i++) {
+ cur = (xmlSchemaBucketPtr) list->items[i];
+ /* Pointer comparison! */
+ if ((cur->origTargetNamespace == NULL) &&
+ (cur->schemaLocation == schemaLocation) &&
+ (cur->targetNamespace == targetNamespace))
+ return(cur);
+ }
+ }
+ return(NULL);
+}
+
+
+#define IS_BAD_SCHEMA_DOC(b) \
+ (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
+
+static xmlSchemaBucketPtr
+xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
+ const xmlChar *targetNamespace,
+ int imported)
+{
+ xmlSchemaBucketPtr cur;
+ xmlSchemaItemListPtr list;
+
+ list = pctxt->constructor->buckets;
+ if (list->nbItems == 0)
+ return(NULL);
+ else {
+ int i;
+ for (i = 0; i < list->nbItems; i++) {
+ cur = (xmlSchemaBucketPtr) list->items[i];
+ if ((! IS_BAD_SCHEMA_DOC(cur)) &&
+ (cur->origTargetNamespace == targetNamespace) &&
+ ((imported && cur->imported) ||
+ ((!imported) && (!cur->imported))))
+ return(cur);
+ }
+ }
+ return(NULL);
+}
+
static int
-xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
- xmlSchemaPtr schema,
- xmlNodePtr node,
- const xmlChar *nsName,
- const xmlChar *location,
- xmlDocPtr *doc,
- const xmlChar **targetNamespace,
- int absolute)
+xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
+ xmlSchemaPtr schema,
+ xmlSchemaBucketPtr bucket)
{
- xmlSchemaParserCtxtPtr pctxt;
- xmlParserCtxtPtr parserCtxt;
- xmlSchemaImportPtr import;
- const xmlChar *ns;
- xmlNodePtr root;
+ int oldFlags;
+ xmlDocPtr oldDoc;
+ xmlNodePtr node;
+ int ret, oldErrs;
+ xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
+
+ /*
+ * Save old values; reset the *main* schema.
+ * URGENT TODO: This is not good; move the per-document information
+ * to the parser.
+ */
+ oldFlags = schema->flags;
+ oldDoc = schema->doc;
+ if (schema->flags != 0)
+ xmlSchemaClearSchemaDefaults(schema);
+ schema->doc = bucket->doc;
+ /* !! REMOVED: schema->targetNamespace = bucket->targetNamespace; */
+ pctxt->schema = schema;
+ /*
+ * Keep the current target namespace on the parser *not* on the
+ * main schema.
+ */
+ pctxt->targetNamespace = bucket->targetNamespace;
+ WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
- /*
- * NOTE: This will be used for <import>, <xsi:schemaLocation> and
- * <xsi:noNamespaceSchemaLocation>.
- */
- *doc = NULL;
- /*
- * Given that the schemaLocation [attribute] is only a hint, it is open
- * to applications to ignore all but the first <import> for a given
- * namespace, regardless of the ·actual value· of schemaLocation, but
- * such a strategy risks missing useful information when new
- * schemaLocations are offered.
- *
- * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
- * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
- * valid or not.
- * We will follow XSV here.
- */
- if (location == NULL) {
+ if ((bucket->targetNamespace != NULL) &&
+ xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
/*
- * Schema Document Location Strategy:
- *
- * 3 Based on the namespace name, identify an existing schema document,
- * either as a resource which is an XML document or a <schema> element
- * information item, in some local schema repository;
- *
- * 5 Attempt to resolve the namespace name to locate such a resource.
- *
- * NOTE: Those stategies are not supported, so we will skip.
+ * We are parsing the schema for schemas!
*/
- return (0);
- }
- if (nsName == NULL)
- ns = XML_SCHEMAS_NO_NAMESPACE;
- else
- ns = nsName;
-
- import = xmlHashLookup(schema->schemasImports, ns);
- if (import != NULL) {
- /*
- * There was a valid resource for the specified namespace already
- * defined, so skip.
- * TODO: This might be changed someday to allow import of
- * components from multiple documents for a single target namespace.
- */
- return (0);
- }
- if (actxt->type == XML_SCHEMA_CTXT_PARSER)
- pctxt = (xmlSchemaParserCtxtPtr) actxt;
- else {
- xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
- pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
- }
+ pctxt->isS4S = 1;
+ }
+ /* Mark it as parsed, even if parsing fails. */
+ bucket->parsed++;
+ /* Compile the schema doc. */
+ node = xmlDocGetRootElement(bucket->doc);
+ ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
+ if (ret != 0)
+ goto exit;
+ /* An empty schema; just get out. */
+ if (node->children == NULL)
+ goto exit;
+ oldErrs = pctxt->nberrors;
+ ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
+ if (ret != 0)
+ goto exit;
/*
- * Schema Document Location Strategy:
- *
- * 2 Based on the location URI, identify an existing schema document,
- * either as a resource which is an XML document or a <schema> element
- * information item, in some local schema repository;
- *
- * 4 Attempt to resolve the location URI, to locate a resource on the
- * web which is or contains or references a <schema> element;
- * TODO: Hmm, I don't know if the reference stuff in 4. will work.
- *
+ * TODO: Not nice, but I'm not 100% sure we will get always an error
+ * as a result of the obove functions; so better rely on pctxt->err
+ * as well.
*/
- if ((absolute == 0) && (node != NULL)) {
- xmlChar *base, *URI;
-
- base = xmlNodeGetBase(node->doc, node);
- if (base == NULL) {
- URI = xmlBuildURI(location, node->doc->URL);
- } else {
- URI = xmlBuildURI(location, base);
- xmlFree(base);
- }
- if (URI != NULL) {
- location = xmlDictLookup(pctxt->dict, URI, -1);
- xmlFree(URI);
- }
+ if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
+ ret = pctxt->err;
+ goto exit;
}
- parserCtxt = xmlNewParserCtxt();
- if (parserCtxt == NULL) {
- xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
- "allocating a parser context", NULL);
+
+exit:
+ WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
+ /* Restore schema values. */
+ schema->doc = oldDoc;
+ schema->flags = oldFlags;
+ return(ret);
+}
+
+static int
+xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
+ xmlSchemaPtr schema,
+ xmlSchemaBucketPtr bucket)
+{
+ xmlSchemaParserCtxtPtr newpctxt;
+ int res = 0;
+
+ if (bucket == NULL)
+ return(0);
+ if (bucket->parsed) {
+ PERROR_INT("xmlSchemaParseNewDoc",
+ "reparsing a schema doc");
return(-1);
}
- if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
- xmlDictFree(parserCtxt->dict);
- parserCtxt->dict = pctxt->dict;
- xmlDictReference(parserCtxt->dict);
+ if (bucket->doc == NULL) {
+ PERROR_INT("xmlSchemaParseNewDoc",
+ "parsing a schema doc, but there's no doc");
+ return(-1);
}
- *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
- NULL, SCHEMAS_PARSE_OPTIONS);
+ if (pctxt->constructor == NULL) {
+ PERROR_INT("xmlSchemaParseNewDoc",
+ "no constructor");
+ return(-1);
+ }
+ /* Create and init the temporary parser context. */
+ newpctxt = xmlSchemaNewParserCtxtUseDict(
+ (const char *) bucket->schemaLocation, pctxt->dict);
+ if (newpctxt == NULL)
+ return(-1);
+ newpctxt->constructor = pctxt->constructor;
/*
- * 2.1 The referent is (a fragment of) a resource which is an
- * XML document (see clause 1.1), which in turn corresponds to
- * a <schema> element information item in a well-formed information
- * set, which in turn corresponds to a valid schema.
- * TODO: What to do with the "fragment" stuff?
- *
- * 2.2 The referent is a <schema> element information item in
- * a well-formed information set, which in turn corresponds
- * to a valid schema.
- * NOTE: 2.2 won't apply, since only XML documents will be processed
- * here.
+ * TODO: Can we avoid that the parser knows about the main schema?
+ * It would be better if he knows about the current schema bucket
+ * only.
*/
- if (*doc == NULL) {
- xmlErrorPtr lerr;
- /*
- * It is *not* an error for the application schema reference
- * strategy to fail.
- *
- * If the doc is NULL and the parser error is an IO error we
- * will assume that the resource could not be located or accessed.
- *
- * TODO: Try to find specific error codes to react only on
- * localisation failures.
- *
- * TODO, FIXME: Check the spec: is a namespace added to the imported
- * namespaces, even if the schemaLocation did not provide
- * a resource? I guess so, since omitting the "schemaLocation"
- * attribute, imports a namespace as well.
- */
- lerr = xmlGetLastError();
- if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
- xmlFreeParserCtxt(parserCtxt);
- return(0);
- }
- xmlSchemaCustomErr(actxt,
- XML_SCHEMAP_SRC_IMPORT_2_1,
- node, NULL,
- "Failed to parse the resource '%s' for import",
- location, NULL);
- xmlFreeParserCtxt(parserCtxt);
- return(XML_SCHEMAP_SRC_IMPORT_2_1);
- }
- xmlFreeParserCtxt(parserCtxt);
+ newpctxt->schema = schema;
+ xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
+ pctxt->userData);
+ newpctxt->counter = pctxt->counter;
+
- root = xmlDocGetRootElement(*doc);
- if (root == NULL) {
- xmlSchemaCustomErr(actxt,
- XML_SCHEMAP_SRC_IMPORT_2_1,
- node, NULL,
- "The XML document '%s' to be imported has no document "
- "element", location, NULL);
- xmlFreeDoc(*doc);
- *doc = NULL;
- return (XML_SCHEMAP_SRC_IMPORT_2_1);
- }
-
- xmlSchemaCleanupDoc(pctxt, root);
-
- if (!IS_SCHEMA(root, "schema")) {
- xmlSchemaCustomErr(actxt,
- XML_SCHEMAP_SRC_IMPORT_2_1,
- node, NULL,
- "The XML document '%s' to be imported is not a XML schema document",
- location, NULL);
- xmlFreeDoc(*doc);
- *doc = NULL;
- return (XML_SCHEMAP_SRC_IMPORT_2_1);
- }
- *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
- /*
- * Schema Representation Constraint: Import Constraints and Semantics
- */
- if (nsName == NULL) {
- if (*targetNamespace != NULL) {
- xmlSchemaCustomErr(actxt,
- XML_SCHEMAP_SRC_IMPORT_3_2,
- node, NULL,
- "The XML schema to be imported is not expected "
- "to have a target namespace; this differs from "
- "its target namespace of '%s'", *targetNamespace, NULL);
- xmlFreeDoc(*doc);
- *doc = NULL;
- return (XML_SCHEMAP_SRC_IMPORT_3_2);
- }
- } else {
- if (*targetNamespace == NULL) {
- xmlSchemaCustomErr(actxt,
- XML_SCHEMAP_SRC_IMPORT_3_1,
- node, NULL,
- "The XML schema to be imported is expected to have a target "
- "namespace of '%s'", nsName, NULL);
- xmlFreeDoc(*doc);
- *doc = NULL;
- return (XML_SCHEMAP_SRC_IMPORT_3_1);
- } else if (!xmlStrEqual(*targetNamespace, nsName)) {
- xmlSchemaCustomErr(actxt,
- XML_SCHEMAP_SRC_IMPORT_3_1,
- node, NULL,
- "The XML schema to be imported is expected to have a "
- "target namespace of '%s'; this differs from "
- "its target namespace of '%s'",
- nsName, *targetNamespace);
- xmlFreeDoc(*doc);
- *doc = NULL;
- return (XML_SCHEMAP_SRC_IMPORT_3_1);
- }
- }
- import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
- if (import == NULL) {
- AERROR_INT("xmlSchemaAcquireSchemaDoc",
- "failed to build import table");
- xmlFreeDoc(*doc);
- *doc = NULL;
- return (-1);
- }
- import->schemaLocation = location;
- import->doc = *doc;
- return (0);
+ res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
+
+ /* Channel back errors and cleanup the temporary parser context. */
+ if (res != 0)
+ pctxt->err = res;
+ pctxt->nberrors += newpctxt->nberrors;
+ pctxt->counter = newpctxt->counter;
+ newpctxt->constructor = NULL;
+ /* Free the parser context. */
+ xmlSchemaFreeParserCtxt(newpctxt);
+ return(res);
}
static void
-xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
- xmlSchemaPtr schema,
- const xmlChar *targetNamespace,
- xmlNodePtr node)
+xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
+ xmlSchemaSchemaRelationPtr rel)
{
- const xmlChar *oldURL, **oldLocImps, *oldTNS;
- int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
+ xmlSchemaSchemaRelationPtr cur = bucket->relations;
+ if (cur == NULL) {
+ bucket->relations = rel;
+ return;
+ }
+ while (cur->next != NULL)
+ cur = cur->next;
+ cur->next = rel;
+}
+
+
+static const xmlChar *
+xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
+ xmlNodePtr ctxtNode)
+{
/*
- * Save and reset the context & schema.
+ * Build an absolue location URI.
*/
- oldURL = pctxt->URL;
- /* TODO: Is using the doc->URL here correct? */
- pctxt->URL = node->doc->URL;
+ if (location != NULL) {
+ if (ctxtNode == NULL)
+ return(location);
+ else {
+ xmlChar *base, *URI;
+ const xmlChar *ret = NULL;
- oldLocImps = pctxt->localImports;
- pctxt->localImports = NULL;
- oldNumLocImps = pctxt->nbLocalImports;
- pctxt->nbLocalImports = 0;
- oldSizeLocImps = pctxt->sizeLocalImports;
- pctxt->sizeLocalImports = 0;
+ base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
+ if (base == NULL) {
+ URI = xmlBuildURI(location, ctxtNode->doc->URL);
+ } else {
+ URI = xmlBuildURI(location, base);
+ xmlFree(base);
+ }
+ if (URI != NULL) {
+ ret = xmlDictLookup(dict, URI, -1);
+ xmlFree(URI);
+ return(ret);
+ }
+ }
+ }
+ return(NULL);
+}
+
- oldFlags = schema->flags;
- oldIsS4S = pctxt->isS4S;
- xmlSchemaClearSchemaDefaults(schema);
- oldTNS = schema->targetNamespace;
- schema->targetNamespace = targetNamespace;
- if ((targetNamespace != NULL) &&
- xmlStrEqual(targetNamespace, xmlSchemaNs)) {
- /*
- * We are parsing the schema for schema!
- */
- pctxt->isS4S = 1;
+/**
+ * xmlSchemaAddSchemaDoc:
+ * @pctxt: a schema validation context
+ * @schema: the schema being built
+ * @node: a subtree containing XML Schema informations
+ *
+ * Parse an included (and to-be-redefined) XML schema document.
+ *
+ * Returns 0 on success, a positive error code on errors and
+ * -1 in case of an internal or API error.
+ */
+
+static int
+xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
+ int type, /* import or include or redefine */
+ const xmlChar *schemaLocation,
+ xmlDocPtr schemaDoc,
+ const char *schemaBuffer,
+ int schemaBufferLen,
+ xmlNodePtr invokingNode,
+ const xmlChar *sourceTargetNamespace,
+ const xmlChar *importNamespace,
+ xmlSchemaBucketPtr *bucket)
+{
+ const xmlChar *targetNamespace = NULL;
+ xmlSchemaSchemaRelationPtr relation = NULL;
+ xmlDocPtr doc = NULL;
+ int res = 0, err = 0, located = 0, preserveDoc = 0;
+ xmlSchemaBucketPtr bkt = NULL;
+
+ if (bucket != NULL)
+ *bucket = NULL;
+
+ switch (type) {
+ case XML_SCHEMA_SCHEMA_IMPORT:
+ case XML_SCHEMA_SCHEMA_MAIN:
+ err = XML_SCHEMAP_SRC_IMPORT;
+ break;
+ case XML_SCHEMA_SCHEMA_INCLUDE:
+ err = XML_SCHEMAP_SRC_INCLUDE;
+ break;
+ case XML_SCHEMA_SCHEMA_REDEFINE:
+ err = XML_SCHEMAP_SRC_REDEFINE;
+ break;
+ }
+
+
+ /* Special handling for the main schema:
+ * skip the location and relation logic and just parse the doc.
+ * We need just a bucket to be returned in this case.
+ */
+ if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
+ goto doc_load;
+
+ /* Note that we expect the location to be an absulute URI. */
+ if (schemaLocation != NULL) {
+ bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
+ if ((bkt != NULL) &&
+ (pctxt->constructor->bucket == bkt)) {
+ /* Report self-imports/inclusions/redefinitions. */
+
+ xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
+ invokingNode, NULL,
+ "The schema must not import/include/redefine itself",
+ NULL, NULL);
+ goto exit;
+ }
}
/*
- * Parse the schema.
+ * Create a relation for the graph of schemas.
*/
- xmlSchemaParseSchemaDefaults(pctxt, schema, node);
- xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
+ relation = xmlSchemaSchemaRelationCreate();
+ if (relation == NULL)
+ return(-1);
+ xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
+ relation);
+ relation->type = type;
+
/*
- * Restore the context & schema.
+ * Save the namespace import information.
*/
- schema->flags = oldFlags;
- schema->targetNamespace = oldTNS;
- if (pctxt->localImports != NULL)
- xmlFree((xmlChar *) pctxt->localImports);
- pctxt->localImports = oldLocImps;
- pctxt->nbLocalImports = oldNumLocImps;
- pctxt->sizeLocalImports = oldSizeLocImps;
- pctxt->URL = oldURL;
- pctxt->isS4S = oldIsS4S;
+ if (WXS_IS_IMPMAIN(type)) {
+ relation->importNamespace = importNamespace;
+ if (schemaLocation == NULL) {
+ /*
+ * No location; this is just an import of the namespace.
+ * Note that we don't assign a bucket to the relation
+ * in this case.
+ */
+ goto exit;
+ }
+ targetNamespace = importNamespace;
+ }
+
+ /* Did we already fetch the doc? */
+ if (bkt != NULL) {
+ /* TODO: The following nasty cases will produce an error. */
+ if ((WXS_IS_IMPMAIN(type)) && (! bkt->imported)) {
+ /* We included/redefined and then try to import a schema. */
+ xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
+ invokingNode, NULL,
+ "The schema document '%s' cannot be imported, since "
+ "it was already included or redefined",
+ schemaLocation, NULL);
+ goto exit;
+ } else if ((! WXS_IS_IMPMAIN(type)) && (bkt->imported)) {
+ /* We imported and then try to include/redefine a schema. */
+ xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
+ invokingNode, NULL,
+ "The schema document '%s' cannot be included or "
+ "redefined, since it was already imported",
+ schemaLocation, NULL);
+ goto exit;
+ }
+ }
+
+ if (WXS_IS_IMPMAIN(type)) {
+ /*
+ * Given that the schemaLocation [attribute] is only a hint, it is open
+ * to applications to ignore all but the first <import> for a given
+ * namespace, regardless of the ·actual value· of schemaLocation, but
+ * such a strategy risks missing useful information when new
+ * schemaLocations are offered.
+ *
+ * We will use the first <import> that comes with a location.
+ * Further <import>s *with* a location, will result in an error.
+ * TODO: Better would be to just report a warning here, but
+ * we'll try it this way until someone complains.
+ *
+ * Schema Document Location Strategy:
+ * 3 Based on the namespace name, identify an existing schema document,
+ * either as a resource which is an XML document or a <schema> element
+ * information item, in some local schema repository;
+ * 5 Attempt to resolve the namespace name to locate such a resource.
+ *
+ * NOTE: (3) and (5) are not supported.
+ */
+ if (bkt != NULL) {
+ relation->bucket = bkt;
+ goto exit;
+ }
+ bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
+ importNamespace, 1);
+
+ if (bkt != NULL) {
+ relation->bucket = bkt;
+ if (bkt->schemaLocation == NULL) {
+ /* First given location of the schema; load the doc. */
+ bkt->schemaLocation = schemaLocation;
+ } else {
+ if (!xmlStrEqual(schemaLocation,
+ bkt->schemaLocation)) {
+ /*
+ * Additional location given; just skip it.
+ * URGENT TODO: We should report a warning here.
+ * res = XML_SCHEMAP_SRC_IMPORT;
+ */
+ xmlSchemaCustomWarning(ACTXT_CAST pctxt,
+ XML_SCHEMAP_WARN_SKIP_SCHEMA,
+ invokingNode, NULL,
+ "Skipping import of schema located at '%s' for the "
+ "namespace '%s', since this namespace was already "
+ "imported with the schema located at '%s'",
+ schemaLocation, importNamespace, bkt->schemaLocation);
+ }
+ goto exit;
+ }
+ }
+ /*
+ * No bucket + first location: load the doc and create a
+ * bucket.
+ */
+ } else {
+ /* <include> and <redefine> */
+ if (bkt != NULL) {
+
+ if ((bkt->origTargetNamespace == NULL) &&
+ (bkt->targetNamespace != sourceTargetNamespace)) {
+ xmlSchemaBucketPtr chamel;
+
+ /*
+ * Chameleon include/redefine: skip loading only if it was
+ * aleady build for the targetNamespace of the including
+ * schema.
+ */
+ /*
+ * URGENT TODO: If the schema is a chameleon-include then copy
+ * the components into the including schema and modify the
+ * targetNamespace of those components, do nothing otherwise.
+ * NOTE: This is currently worked-around by compiling the
+ * chameleon for every destinct including targetNamespace; thus
+ * not performant at the moment.
+ * TODO: Check when the namespace in wildcards for chameleons
+ * needs to be converted: before we built wildcard intersections
+ * or after.
+ * Answer: after!
+ */
+ chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
+ schemaLocation, sourceTargetNamespace);
+ if (chamel != NULL) {
+ /* A fitting chameleon was already parsed; NOP. */
+ relation->bucket = chamel;
+ goto exit;
+ }
+ /*
+ * We need to parse the chameleon again for a different
+ * targetNamespace.
+ * CHAMELEON TODO: Optimize this by only parsing the
+ * chameleon once, and then copying the components to
+ * the new targetNamespace.
+ */
+ bkt = NULL;
+ } else {
+ relation->bucket = bkt;
+ goto exit;
+ }
+ }
+ }
+ if ((bkt != NULL) && (bkt->doc != NULL)) {
+ PERROR_INT("xmlSchemaAddSchemaDoc",
+ "trying to load a schema doc, but a doc is already "
+ "assigned to the schema bucket");
+ goto exit_failure;
+ }
+
+doc_load:
+ /*
+ * Load the document.
+ */
+ if (schemaDoc != NULL) {
+ doc = schemaDoc;
+ /* Don' free this one, since it was provided by the caller. */
+ preserveDoc = 1;
+ /* TODO: Does the context or the doc hold the location? */
+ if (schemaDoc->URL != NULL)
+ schemaLocation = xmlDictLookup(pctxt->dict,
+ schemaDoc->URL, -1);
+
+ } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
+ xmlParserCtxtPtr parserCtxt;
+
+ parserCtxt = xmlNewParserCtxt();
+ if (parserCtxt == NULL) {
+ xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
+ "allocating a parser context", NULL);
+ goto exit_failure;
+ }
+ if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
+ /*
+ * TODO: Do we have to burden the schema parser dict with all
+ * the content of the schema doc?
+ */
+ xmlDictFree(parserCtxt->dict);
+ parserCtxt->dict = pctxt->dict;
+ xmlDictReference(parserCtxt->dict);
+ }
+ if (schemaLocation != NULL) {
+ /* Parse from file. */
+ doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
+ NULL, SCHEMAS_PARSE_OPTIONS);
+ } else if (schemaBuffer != NULL) {
+ /* Parse from memory buffer. */
+ doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
+ NULL, NULL, SCHEMAS_PARSE_OPTIONS);
+ schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer");
+ if (doc != NULL)
+ doc->URL = schemaLocation;
+ }
+ /*
+ * For <import>:
+ * 2.1 The referent is (a fragment of) a resource which is an
+ * XML document (see clause 1.1), which in turn corresponds to
+ * a <schema> element information item in a well-formed information
+ * set, which in turn corresponds to a valid schema.
+ * TODO: (2.1) fragments of XML documents are not supported.
+ *
+ * 2.2 The referent is a <schema> element information item in
+ * a well-formed information set, which in turn corresponds
+ * to a valid schema.
+ * TODO: (2.2) is not supported.
+ */
+ if (doc == NULL) {
+ xmlErrorPtr lerr;
+ lerr = xmlGetLastError();
+ /*
+ * Check if this a parser error, or if the document could
+ * just not be located.
+ * TODO: Try to find specific error codes to react only on
+ * localisation failures.
+ */
+ if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
+ /*
+ * We assume a parser error here.
+ */
+ located = 1;
+ /* TODO: Error code ?? */
+ res = XML_SCHEMAP_SRC_IMPORT_2_1;
+ xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
+ invokingNode, NULL,
+ "Failed to parse the XML resource '%s'",
+ schemaLocation, NULL);
+ }
+ }
+ xmlFreeParserCtxt(parserCtxt);
+ if ((doc == NULL) && located)
+ goto exit_error;
+ } else {
+ xmlSchemaPErr(pctxt, NULL,
+ XML_SCHEMAP_NOTHING_TO_PARSE,
+ "No information for parsing was provided with the "
+ "given schema parser context.\n",
+ NULL, NULL);
+ goto exit_failure;
+ }
+ /*
+ * Preprocess the document.
+ */
+ if (doc != NULL) {
+ xmlNodePtr docElem = NULL;
+
+ located = 1;
+ docElem = xmlDocGetRootElement(doc);
+ if (docElem == NULL) {
+ xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
+ invokingNode, NULL,
+ "The document '%s' has no document element",
+ schemaLocation, NULL);
+ xmlFreeDoc(doc);
+ doc = NULL;
+ goto exit_error;
+ }
+ /*
+ * Remove all the blank text nodes.
+ */
+ xmlSchemaCleanupDoc(pctxt, docElem);
+ /*
+ * Check the schema's top level element.
+ */
+ if (!IS_SCHEMA(docElem, "schema")) {
+ xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
+ invokingNode, NULL,
+ "The XML document '%s' is not a schema document",
+ schemaLocation, NULL);
+ xmlFreeDoc(doc);
+ doc = NULL;
+ goto exit_error;
+ }
+ /*
+ * Note that we don't apply a type check for the
+ * targetNamespace value here.
+ */
+ targetNamespace = xmlSchemaGetProp(pctxt, docElem,
+ "targetNamespace");
+ }
+
+/* after_doc_loading: */
+ if ((bkt == NULL) && located) {
+ /* Only create a bucket if the schema was located. */
+ bkt = xmlSchemaBucketCreate(pctxt, type,
+ targetNamespace);
+ if (bkt == NULL)
+ goto exit_failure;
+ }
+ if (bkt != NULL) {
+ bkt->schemaLocation = schemaLocation;
+ bkt->located = located;
+ if (doc != NULL) {
+ bkt->doc = doc;
+ bkt->targetNamespace = targetNamespace;
+ bkt->origTargetNamespace = targetNamespace;
+ if (preserveDoc)
+ bkt->preserveDoc = 1;
+ }
+ if (WXS_IS_IMPMAIN(type))
+ bkt->imported++;
+ /*
+ * Add it to the graph of schemas.
+ */
+ if (relation != NULL)
+ relation->bucket = bkt;
+ }
+
+exit:
+ /*
+ * Return the bucket explicitely; this is needed for the
+ * main schema.
+ */
+ if (bucket != NULL)
+ *bucket = bkt;
+ return (0);
+
+exit_error:
+ if ((doc != NULL) && (! preserveDoc)) {
+ xmlFreeDoc(doc);
+ if (bkt != NULL)
+ bkt->doc = NULL;
+ }
+ return(pctxt->err);
+
+exit_failure:
+ if ((doc != NULL) && (! preserveDoc)) {
+ xmlFreeDoc(doc);
+ if (bkt != NULL)
+ bkt->doc = NULL;
+ }
+ return (-1);
}
/**
@@ -9354,10 +9805,9 @@
xmlNodePtr child;
const xmlChar *namespaceName = NULL;
const xmlChar *schemaLocation = NULL;
- const xmlChar *targetNamespace;
xmlAttrPtr attr;
- xmlDocPtr doc;
int ret = 0;
+ xmlSchemaBucketPtr bucket = NULL;
if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
return (-1);
@@ -9432,13 +9882,13 @@
* must not match the ·actual value· of the enclosing <schema>'s
* targetNamespace [attribute].
*/
- if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
+ if (xmlStrEqual(pctxt->targetNamespace, namespaceName)) {
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);
+ pctxt->targetNamespace);
return (pctxt->err);
}
} else {
@@ -9446,7 +9896,7 @@
* 1.2 If the namespace [attribute] is not present, then the enclosing
* <schema> must have a targetNamespace [attribute].
*/
- if (schema->targetNamespace == NULL) {
+ if (pctxt->targetNamespace == NULL) {
xmlSchemaPCustomErr(pctxt,
XML_SCHEMAP_SRC_IMPORT_1_2,
NULL, NULL, node,
@@ -9457,266 +9907,46 @@
}
}
/*
- * 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 (pctxt->localImports == NULL) {
- pctxt->localImports = (const xmlChar **) xmlMalloc(10 *
- 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*));
- }
- pctxt->localImports[pctxt->nbLocalImports++] = namespaceName;
- /*
* Locate and aquire the schema document.
*/
- ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) pctxt,
- schema, node, namespaceName,
- schemaLocation, &doc, &targetNamespace, 0);
- if (ret != 0) {
- if (doc != NULL)
- xmlFreeDoc(doc);
- return (ret);
- } else if (doc != NULL) {
- xmlSchemaParseForImpInc(pctxt, schema, targetNamespace,
- xmlDocGetRootElement(doc));
- }
+ if (schemaLocation != NULL)
+ schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
+ schemaLocation, node);
+ ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
+ schemaLocation, NULL, NULL, 0, node, pctxt->targetNamespace,
+ namespaceName, &bucket);
- return (0);
+ if (ret != 0)
+ return(ret);
+
+ /*
+ * For <import>: "It is *not* an error for the application
+ * schema reference strategy to fail."
+ * So just don't parse if no schema document was found.
+ * Note that we will get no bucket if the schema could not be
+ * located or if there was no schemaLocation.
+ */
+ if ((bucket == NULL) && (schemaLocation != NULL)) {
+ xmlSchemaCustomWarning(ACTXT_CAST pctxt,
+ XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
+ node, NULL,
+ "Failed to locate a schema at location '%s'. "
+ "Skipping the import", schemaLocation, NULL, NULL);
+ }
+
+ if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
+ ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
+ }
+
+ return (ret);
}
-/**
- * xmlSchemaParseIncludedDoc:
- * @pctxt: a schema validation context
- * @schema: the schema being built
- * @node: a subtree containing XML Schema informations
- *
- * Parse an included (and to-be-redefined) XML schema document.
- *
- * Returns 0 on success, a positive error code on errors and
- * -1 in case of an internal or API error.
- */
-static int
-xmlSchemaParseIncludedDoc(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
- xmlNodePtr node, const xmlChar *schemaLocation,
- int *located)
-{
- const xmlChar *targetNamespace;
- xmlDocPtr doc = NULL;
- xmlNodePtr root = NULL;
- xmlSchemaIncludePtr include = NULL;
- int wasConvertingNs = 0;
- xmlParserCtxtPtr parserCtxt;
-
- if (located == NULL)
- return(-1);
- (*located) = 0;
- /*
- * Check if this one was already processed to avoid incorrect
- * duplicate component errors and infinite circular inclusion.
- */
- include = schema->includes;
- while (include != NULL) {
- if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
- (*located) = 1;
- targetNamespace = include->origTargetNamespace;
- if (targetNamespace == NULL) {
- /*
- * Chameleon include: skip only if it was build for
- * the targetNamespace of the including schema.
- */
- if (xmlStrEqual(schema->targetNamespace,
- include->targetNamespace)) {
- goto check_targetNamespace;
- }
- } else {
- goto check_targetNamespace;
- }
- }
- include = include->next;
- }
- /*
- * First step is to parse the input document into an DOM/Infoset
- * TODO: Use xmlCtxtReadFile to share the dictionary?
- */
- parserCtxt = xmlNewParserCtxt();
- if (parserCtxt == NULL) {
- xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
- "allocating a parser context", NULL);
- goto exit_failure;
- }
-
- if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
- xmlDictFree(parserCtxt->dict);
- parserCtxt->dict = pctxt->dict;
- xmlDictReference(parserCtxt->dict);
- }
-
- doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
- NULL, SCHEMAS_PARSE_OPTIONS);
- xmlFreeParserCtxt(parserCtxt);
- if (doc == NULL) {
- goto exit_not_located;
- }
- (*located) = 1;
- /*
- * Then extract the root of the schema
- */
- root = xmlDocGetRootElement(doc);
- if (root == NULL) {
- xmlSchemaPCustomErr(pctxt,
- XML_SCHEMAP_NOROOT,
- NULL, NULL, node,
- "The included document '%s' has no document "
- "element", schemaLocation);
- goto exit_error;
- }
-
- /*
- * Remove all the blank text nodes
- */
- xmlSchemaCleanupDoc(pctxt, root);
-
- /*
- * Check the schemas top level element
- */
- if (!IS_SCHEMA(root, "schema")) {
- xmlSchemaPCustomErr(pctxt,
- XML_SCHEMAP_NOT_SCHEMA,
- NULL, NULL, node,
- "The document '%s' to be included is not a schema document",
- schemaLocation);
- goto exit_error;
- }
-
- 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
- * [attribute] of SIIÂ’ (which must have such an [attribute]).
- */
-check_targetNamespace:
- if (targetNamespace != NULL) {
- if (schema->targetNamespace == NULL) {
- 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_error;
- } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
- 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_error;
- }
- } else if (schema->targetNamespace != NULL) {
- if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
- schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
- } else
- wasConvertingNs = 1;
- }
-
- if (include != NULL)
- goto exit;
-
- /*
- * URGENT TODO: If the schema is a chameleon-include then copy the
- * components into the including schema and modify the targetNamespace
- * of those components, do nothing otherwise.
- * NOTE: This is currently worked-around by compiling the chameleon
- * for every destinct including targetNamespace; thus not performant at
- * 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(pctxt, "allocating include entry", NULL);
- goto exit_failure;
- }
- memset(include, 0, sizeof(xmlSchemaInclude));
- include->next = schema->includes;
- schema->includes = include;
- /*
- * TODO: Use the resolved URI for the this location, since it might
- * differ if using filenames/URIs simultaneosly.
- */
- include->schemaLocation = schemaLocation;
- include->doc = doc;
- /*
- * In case of chameleons, the original target namespace will differ
- * from the resulting namespace.
- */
- include->origTargetNamespace = targetNamespace;
- include->targetNamespace = schema->targetNamespace;
-#ifdef DEBUG_INCLUDES
- if (targetNamespace != schema->targetNamespace)
- xmlGenericError(xmlGenericErrorContext,
- "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
- " into TNS '%s'\n", schemaLocation,
- targetNamespace, schema->targetNamespace);
- else
- xmlGenericError(xmlGenericErrorContext,
- "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
- targetNamespace);
-#endif
- /*
- * Compile the included schema.
- */
- xmlSchemaParseForImpInc(pctxt, schema, schema->targetNamespace, root);
-
-exit:
- /*
- * Remove the converting flag.
- */
- if ((wasConvertingNs == 0) &&
- (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
- schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
- return (0);
-
-exit_error:
- if (doc != NULL) {
- if (include != NULL)
- include->doc = NULL;
- xmlFreeDoc(doc);
- }
- return (pctxt->err);
-
-exit_not_located:
- return(0);
-
-exit_failure:
- if (doc != NULL) {
- if (include != NULL)
- include->doc = NULL;
- xmlFreeDoc(doc);
- }
- return (-1);
-}
-
-
static int
xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
xmlSchemaPtr schema,
xmlNodePtr node,
xmlChar **schemaLocation,
- int isRedefine)
+ int type)
{
xmlAttrPtr attr;
@@ -9786,7 +10016,7 @@
* Report self-inclusion and self-redefinition.
*/
if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
- if (isRedefine) {
+ if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
xmlSchemaPCustomErr(pctxt,
XML_SCHEMAP_SRC_REDEFINE,
NULL, NULL, node,
@@ -9813,11 +10043,13 @@
xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
xmlSchemaPtr schema,
xmlNodePtr node,
- int isRedefine)
+ int type)
{
xmlNodePtr child = NULL;
const xmlChar *schemaLocation = NULL;
- int res = 0, located = 0, hasRedefinitions = 0;
+ int res = 0, /* docRes = 0, located = 0, */ hasRedefinitions = 0;
+ int isChameleon = 0, wasChameleon = 0;
+ xmlSchemaBucketPtr bucket = NULL;
if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
return (-1);
@@ -9827,27 +10059,141 @@
* be already converted to an absolute URI.
*/
res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
- node, (xmlChar **) (&schemaLocation), isRedefine);
+ node, (xmlChar **) (&schemaLocation), type);
if (res != 0)
- return(res);
-
+ return(res);
/*
- * Include the schema.
+ * Load and add the schema document.
*/
- res = xmlSchemaParseIncludedDoc(pctxt, schema, node,
- schemaLocation, &located);
+ res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
+ NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
if (res != 0)
- return(res);
-
+ return(res);
+ /*
+ if (bucket == NULL) {
+ PERROR_INT("xmlSchemaParseIncludeOrRedefine",
+ "no schema bucket aquired");
+ return(-1);
+ }
+ */
+ if ((bucket == NULL) || (bucket->doc == NULL)) {
+ if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
+ /*
+ * 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;
+ xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
+ node, NULL,
+ "Failed to load the document '%s' for inclusion",
+ schemaLocation, NULL);
+ } else {
+ /*
+ * NOTE: This was changed to raise an error even if no redefinitions
+ * are specified.
+ *
+ * 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 always to resolve
+ * here as well!
+ */
+ res = XML_SCHEMAP_SRC_REDEFINE;
+ xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
+ node, NULL,
+ "Failed to load the document '%s' for redefinition",
+ schemaLocation, NULL);
+ }
+ } else {
+ /*
+ * Check targetNamespace sanity before parsing the new schema.
+ * TODO: Note that we won't check further content if the
+ * targetNamespace was bad.
+ */
+ if (bucket->origTargetNamespace != NULL) {
+ /*
+ * SPEC src-include (2.1)
+ * "SII has a targetNamespace [attribute], and its ·actual
+ * value· is identical to the ·actual value· of the targetNamespace
+ * [attribute] of SIIÂ’ (which must have such an [attribute])."
+ */
+ if (pctxt->targetNamespace == NULL) {
+ xmlSchemaCustomErr(ACTXT_CAST pctxt,
+ XML_SCHEMAP_SRC_INCLUDE,
+ node, NULL,
+ "The target namespace of the included/redefined schema "
+ "'%s' has to be absent, since the including/redefining "
+ "schema has no target namespace",
+ schemaLocation, NULL);
+ goto exit_error;
+ } else if (!xmlStrEqual(bucket->origTargetNamespace,
+ pctxt->targetNamespace)) {
+ /* TODO: Change error function. */
+ xmlSchemaPCustomErrExt(pctxt,
+ XML_SCHEMAP_SRC_INCLUDE,
+ NULL, NULL, node,
+ "The target namespace '%s' of the included/redefined "
+ "schema '%s' differs from '%s' of the "
+ "including/redefining schema",
+ bucket->origTargetNamespace, schemaLocation,
+ pctxt->targetNamespace);
+ goto exit_error;
+ }
+ } else if (pctxt->targetNamespace != NULL) {
+ /*
+ * Chameleons: the original target namespace will
+ * differ from the resulting namespace.
+ */
+ isChameleon = 1;
+ if (bucket->parsed &&
+ (bucket->targetNamespace != pctxt->targetNamespace)) {
+ /*
+ * This is a sanity check, I dunno yet if this can happen.
+ */
+ PERROR_INT("xmlSchemaParseIncludeOrRedefine",
+ "trying to use an already parsed schema for a "
+ "different targetNamespace");
+ return(-1);
+ }
+ bucket->targetNamespace = pctxt->targetNamespace;
+ }
+ }
+ /*
+ * Parse the schema.
+ */
+ if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
+ if (isChameleon) {
+ /* TODO: Get rid of this flag on the schema itself. */
+ if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
+ schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
+ } else
+ wasChameleon = 1;
+ }
+ xmlSchemaParseNewDoc(pctxt, schema, bucket);
+ /* Restore chameleon flag. */
+ if (isChameleon && (!wasChameleon))
+ schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
+ }
/*
* And now for the children...
*/
- child = node->children;
-
- if (isRedefine) {
+ child = node->children;
+ if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
+
/*
* Parse (simpleType | complexType | group | attributeGroup))*
*/
+ /*
+ * How to proceed if the redefined schema was not located?
+ */
pctxt->isRedefine = 1;
while (IS_SCHEMA(child, "annotation") ||
IS_SCHEMA(child, "simpleType") ||
@@ -9858,19 +10204,27 @@
/*
* 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); */
+ } else if (bucket && bucket->parsed) {
+ /*
+ * TODO: Not nice: we won't parse the stuff if the redefined
+ * document was not parsed or not located.
+ */
+ 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;
}
@@ -9885,71 +10239,37 @@
}
if (child != NULL) {
res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
- if (isRedefine) {
- xmlSchemaPContentErr(pctxt,
- res,
+ if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
+ xmlSchemaPContentErr(pctxt, res,
NULL, NULL, node, child, NULL,
"(annotation | (simpleType | complexType | group | attributeGroup))*");
} else {
- xmlSchemaPContentErr(pctxt,
- res,
+ 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);
+
+exit_error:
+ return(pctxt->err);
}
-#ifdef ENABLE_REDEFINE
static int
xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
xmlNodePtr node)
{
int res;
-
- res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, 1);
+#ifndef ENABLE_REDEFINE
+ TODO
+ return(0);
+#endif
+ res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
+ XML_SCHEMA_SCHEMA_REDEFINE);
if (res != 0)
return(res);
return(0);
}
-#endif
static int
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
@@ -9957,7 +10277,8 @@
{
int res;
- res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, 0);
+ res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
+ XML_SCHEMA_SCHEMA_INCLUDE);
if (res != 0)
return(res);
return(0);
@@ -9986,7 +10307,6 @@
xmlSchemaParticlePtr particle = NULL;
xmlNodePtr child = NULL;
xmlAttrPtr attr;
- const xmlChar *oldcontainer, *container;
int min = 0, max = 0;
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
@@ -9994,7 +10314,7 @@
/*
* Create a model group with the given compositor.
*/
- item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
+ item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
if (item == NULL)
return (NULL);
@@ -10070,8 +10390,6 @@
item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
child = child->next;
}
- oldcontainer = ctxt->container;
- ctxt->container = container;
if (type == XML_SCHEMA_TYPE_ALL) {
xmlSchemaParticlePtr part, last = NULL;
@@ -10144,7 +10462,6 @@
"(annotation?, (element | group | choice | sequence | any)*)");
}
}
- ctxt->container = oldcontainer;
if (withParticle) {
if ((min == 0) && (max == 0))
return (NULL);
@@ -10171,8 +10488,6 @@
{
xmlSchemaTypePtr type;
xmlNodePtr child = NULL;
- char buf[30];
- const xmlChar *oldcontainer, *container;
xmlAttrPtr attr;
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
@@ -10182,12 +10497,6 @@
type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
/*
- * TODO: Is the container needed at all? the anonymous
- * items inside should generate unique names already.
- */
- snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
- container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
- /*
* Check for illegal attributes.
*/
attr = node->properties;
@@ -10272,8 +10581,6 @@
xmlSchemaParseAnnotation(ctxt, schema, child));
child = child->next;
}
- oldcontainer = ctxt->container;
- ctxt->container = container;
if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
/*
* Corresponds to <simpleType><restriction><simpleType>.
@@ -10457,7 +10764,6 @@
"pattern)*))");
}
}
- ctxt->container = oldcontainer;
return (NULL);
}
@@ -10479,8 +10785,6 @@
{
xmlSchemaTypePtr type;
xmlNodePtr child = NULL;
- char buf[30];
- const xmlChar *oldcontainer, *container;
xmlAttrPtr attr;
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
@@ -10489,8 +10793,6 @@
type = ctxt->ctxtType;
type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
- snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
- container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
/*
* Check for illegal attributes.
*/
@@ -10535,8 +10837,6 @@
xmlSchemaParseAnnotation(ctxt, schema, child));
child = child->next;
}
- oldcontainer = ctxt->container;
- ctxt->container = container;
if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
/*
* Corresponds to <complexType><complexContent><extension>... and:
@@ -10595,7 +10895,6 @@
"anyAttribute?))");
}
}
- ctxt->container = oldcontainer;
return (NULL);
}
@@ -10805,10 +11104,12 @@
{
xmlSchemaTypePtr type, ctxtType;
xmlNodePtr child = NULL;
- const xmlChar *oldcontainer, *name = NULL;
+ const xmlChar *name = NULL;
xmlAttrPtr attr;
const xmlChar *attrValue;
+#ifdef ENABLE_NAMED_LOCALS
char buf[40];
+#endif
int final = 0, block = 0, hasRestrictionOrExtension = 0;
@@ -10834,9 +11135,14 @@
/*
* Parse as local complex type definition.
*/
+#ifdef ENABLE_NAMED_LOCALS
snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
- type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL,
- node, 0);
+ type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf,
+ ctxt->targetNamespace, node, 0);
+#else
+ type = xmlSchemaAddType(ctxt, schema, NULL,
+ ctxt->targetNamespace, node, 0);
+#endif
if (type == NULL)
return (NULL);
name = type->name;
@@ -10849,7 +11155,7 @@
/*
* Parse as global complex type definition.
*/
- type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace,
+ type = xmlSchemaAddType(ctxt, schema, name, ctxt->targetNamespace,
node, 1);
if (type == NULL)
return (NULL);
@@ -10857,7 +11163,7 @@
type->type = XML_SCHEMA_TYPE_COMPLEX;
type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
}
- type->targetNamespace = schema->targetNamespace;
+ type->targetNamespace = ctxt->targetNamespace;
/*
* Handle attributes.
*/
@@ -10966,8 +11272,6 @@
/*
* And now for the children...
*/
- oldcontainer = ctxt->container;
- ctxt->container = name;
child = node->children;
if (IS_SCHEMA(child, "annotation")) {
type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
@@ -11058,134 +11362,10 @@
"<complexType> must have a <restriction> or <extension> "
"grand-child", NULL);
}
- ctxt->container = oldcontainer;
ctxt->ctxtType = ctxtType;
return (type);
}
-/**
- * xmlSchemaParseSchema:
- * @ctxt: a schema validation context
- * @node: a subtree containing XML Schema informations
- *
- * parse a XML schema definition from a node set
- * *WARNING* this interface is highly subject to change
- *
- * Returns the internal XML Schema structure built from the resource or
- * NULL in case of error
- */
-static xmlSchemaPtr
-xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
-{
- xmlSchemaPtr schema = NULL;
- const xmlChar *val;
- int nberrors;
- xmlAttrPtr attr;
-
- /*
- * This one is called by xmlSchemaParse only and is used if
- * the schema to be parsed was specified via the API; i.e. not
- * automatically by the validated instance document.
- */
- if ((ctxt == NULL) || (node == NULL))
- return (NULL);
- nberrors = ctxt->nberrors;
- ctxt->nberrors = 0;
- ctxt->isS4S = 0;
- if (IS_SCHEMA(node, "schema")) {
- xmlSchemaImportPtr import;
-#ifdef ENABLE_REDEFINE
- xmlSchemaSchemaRefPtr ref;
-#endif
-
- schema = xmlSchemaNewSchema(ctxt);
- if (schema == NULL)
- return (NULL);
- attr = xmlSchemaGetPropNode(node, "targetNamespace");
- if (attr != NULL) {
- xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
- xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
- /*
- * TODO: Should we proceed with an invalid target namespace?
- */
- schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
- if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
- /*
- * We are parsing the schema for schema!
- */
- ctxt->isS4S = 1;
- }
- } else {
- schema->targetNamespace = NULL;
- }
- /*
- * Add the current ns name and location to the import table;
- * this is needed to have a consistent mechanism, regardless
- * 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) {
- xmlSchemaPInternalErr(ctxt, "xmlSchemaParseSchema",
- "failed to add an import entry", NULL, NULL);
- xmlSchemaFree(schema);
- schema = NULL;
- return (NULL);
- }
- import->schemaLocation = ctxt->URL;
- /*
- * NOTE: We won't set the doc here, otherwise it will be freed
- * if the import struct is freed.
- * import->doc = ctxt->doc;
- */
- xmlSchemaParseSchemaDefaults(ctxt, schema, node);
- xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
- } else {
- xmlDocPtr doc;
-
- doc = node->doc;
-
- if ((doc != NULL) && (doc->URL != NULL)) {
- xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
- XML_SCHEMAP_NOT_SCHEMA,
- "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
- } else {
- xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
- XML_SCHEMAP_NOT_SCHEMA,
- "The file is not a XML schema.\n", NULL, NULL);
- }
- return(NULL);
- }
- if (ctxt->nberrors != 0) {
- if (schema != NULL) {
- xmlSchemaFree(schema);
- schema = NULL;
- }
- }
- if (schema != NULL)
- schema->counter = ctxt->counter;
- ctxt->nberrors = nberrors;
-#ifdef DEBUG
- if (schema == NULL)
- xmlGenericError(xmlGenericErrorContext,
- "xmlSchemaParse() failed\n");
-#endif
- return (schema);
-}
-
/************************************************************************
* *
* Validating using Schemas *
@@ -11270,7 +11450,6 @@
return(NULL);
ret->dict = xmlDictCreate();
ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
- ret->includes = 0;
return (ret);
}
@@ -11339,20 +11518,15 @@
if (ctxt == NULL)
return;
if (ctxt->doc != NULL && !ctxt->preserve)
- xmlFreeDoc(ctxt->doc);
- if (ctxt->assemble != NULL) {
- xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
- xmlFree(ctxt->assemble);
- }
+ xmlFreeDoc(ctxt->doc);
if (ctxt->vctxt != NULL) {
xmlSchemaFreeValidCtxt(ctxt->vctxt);
}
- if (ctxt->localImports != NULL)
- xmlFree((xmlChar *) ctxt->localImports);
- if (ctxt->substGroups != NULL)
- xmlHashFree(ctxt->substGroups,
- (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
- xmlSchemaContainerFree(ctxt->compContainer);
+ if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
+ xmlSchemaConstructionCtxtFree(ctxt->constructor);
+ ctxt->constructor = NULL;
+ ctxt->ownsConstructor = 0;
+ }
xmlDictFree(ctxt->dict);
xmlFree(ctxt);
}
@@ -11379,7 +11553,7 @@
start = pctxt->state;
if (end == NULL)
end = xmlAutomataNewState(pctxt->am);
- substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
+ substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
if (substGroup == NULL) {
xmlSchemaPErr(pctxt, GET_NODE(particle),
XML_SCHEMAP_INTERNAL,
@@ -11390,7 +11564,10 @@
}
if (counter >= 0) {
/*
- * NOTE that we put the declaration in, even if it's abstract,
+ * NOTE that we put the declaration in, even if it's abstract.
+ * However, an error will be raised during *validation* if an element
+ * information item shall be validated against an abstract element
+ * declaration.
*/
tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
xmlAutomataNewTransition2(pctxt->am, tmp, end,
@@ -11515,8 +11692,7 @@
*/
static void
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
- xmlSchemaParticlePtr particle,
- const xmlChar * name)
+ xmlSchemaParticlePtr particle)
{
if (particle == NULL) {
PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
@@ -11629,7 +11805,7 @@
sub = particle->children->children;
while (sub != NULL) {
xmlSchemaBuildAContentModel(pctxt,
- (xmlSchemaParticlePtr) sub, name);
+ (xmlSchemaParticlePtr) sub);
sub = sub->next;
}
} else {
@@ -11650,7 +11826,7 @@
sub = particle->children->children;
while (sub != NULL) {
xmlSchemaBuildAContentModel(pctxt,
- (xmlSchemaParticlePtr) sub, name);
+ (xmlSchemaParticlePtr) sub);
sub = sub->next;
}
tmp = pctxt->state;
@@ -11668,7 +11844,7 @@
sub = particle->children->children;
while (sub != NULL) {
xmlSchemaBuildAContentModel(pctxt,
- (xmlSchemaParticlePtr) sub, name);
+ (xmlSchemaParticlePtr) sub);
sub = sub->next;
}
xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
@@ -11701,7 +11877,7 @@
sub = particle->children->children;
while (sub != NULL) {
xmlSchemaBuildAContentModel(pctxt,
- (xmlSchemaParticlePtr) sub, name);
+ (xmlSchemaParticlePtr) sub);
sub = sub->next;
}
tmp = pctxt->state;
@@ -11718,7 +11894,7 @@
sub = particle->children->children;
while (sub != NULL) {
xmlSchemaBuildAContentModel(pctxt,
- (xmlSchemaParticlePtr) sub, name);
+ (xmlSchemaParticlePtr) sub);
sub = sub->next;
}
if (particle->minOccurs == 0) {
@@ -11745,7 +11921,7 @@
while (sub != NULL) {
pctxt->state = start;
xmlSchemaBuildAContentModel(pctxt,
- (xmlSchemaParticlePtr) sub, name);
+ (xmlSchemaParticlePtr) sub);
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
sub = sub->next;
}
@@ -11770,7 +11946,7 @@
while (sub != NULL) {
pctxt->state = base;
xmlSchemaBuildAContentModel(pctxt,
- (xmlSchemaParticlePtr) sub, name);
+ (xmlSchemaParticlePtr) sub);
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
sub = sub->next;
}
@@ -11853,15 +12029,15 @@
* 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.
+ * TODO: But the group should be substituted and not occur at
+ * all in the content model at this point. Fix this.
*/
break;
default:
- 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);
+ xmlSchemaInternalErr2(ACTXT_CAST pctxt,
+ "xmlSchemaBuildAContentModel",
+ "found unexpected term of type '%s' in content model",
+ xmlSchemaCompTypeToString(particle->children->type), NULL);
return;
}
}
@@ -11876,8 +12052,7 @@
*/
static void
xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
- xmlSchemaParserCtxtPtr ctxt,
- const xmlChar * name)
+ xmlSchemaParserCtxtPtr ctxt)
{
xmlAutomataStatePtr start;
@@ -11895,11 +12070,11 @@
ctxt->am = xmlNewAutomata();
if (ctxt->am == NULL) {
xmlGenericError(xmlGenericErrorContext,
- "Cannot create automata for complex type %s\n", name);
+ "Cannot create automata for complex type %s\n", type->name);
return;
}
start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
- xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
+ xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes);
xmlAutomataSetFinalState(ctxt->am, ctxt->state);
type->contModel = xmlAutomataCompile(ctxt->am);
if (type->contModel == NULL) {
@@ -11926,7 +12101,7 @@
}
/**
- * xmlSchemaElementFixup:
+ * xmlSchemaResolveElementReferences:
* @elem: the schema element context
* @ctxt: the schema parser context
*
@@ -11935,11 +12110,8 @@
* term.
*/
static void
-xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
- xmlSchemaParserCtxtPtr ctxt,
- const xmlChar * name ATTRIBUTE_UNUSED,
- const xmlChar * context ATTRIBUTE_UNUSED,
- const xmlChar * namespace ATTRIBUTE_UNUSED)
+xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
+ xmlSchemaParserCtxtPtr ctxt)
{
if ((ctxt == NULL) || (elemDecl == NULL) ||
((elemDecl != NULL) &&
@@ -11980,22 +12152,28 @@
"substitutionGroup", elemDecl->substGroup,
elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
} else {
- xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
+ xmlSchemaResolveElementReferences(substHead, ctxt);
/*
* Set the "substitution group affiliation".
* NOTE that now we use the "refDecl" field for this.
*/
- elemDecl->refDecl = substHead;
+ SUBST_GROUP_AFF(elemDecl) = substHead;
/*
- * (type definition)...otherwise the {type definition} of the
- * element declaration ·resolved· to by the ·actual value· of
- * the substitutionGroup [attribute], if present
+ * The type definitions is set to:
+ * SPEC "...the {type definition} of the element
+ * declaration ·resolved· to by the ·actual value·
+ * of the substitutionGroup [attribute], if present"
*/
if (elemDecl->subtypes == NULL)
elemDecl->subtypes = substHead->subtypes;
}
}
- if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
+ /*
+ * SPEC "The definition of anyType serves as the default type definition
+ * for element declarations whose XML representation does not specify one."
+ */
+ if ((elemDecl->subtypes == NULL) &&
+ (elemDecl->namedType == NULL) &&
(elemDecl->substGroup == NULL))
elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
}
@@ -12215,9 +12393,11 @@
*/
static int
xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
+ int isRestriction,
xmlSchemaAttributePtr cur,
xmlSchemaAttributeLinkPtr *uses,
- xmlSchemaAttributeLinkPtr *lastUse)
+ xmlSchemaAttributeLinkPtr *lastUse,
+ int *hasProhibitions)
{
xmlSchemaAttributeLinkPtr tmp;
while (cur != NULL) {
@@ -12227,11 +12407,21 @@
* to by the ·actual value·s of the ref [attribute] of the
* <attributeGroup> [children], if any."
*/
- if (xmlSchemaBuildAttributeUsesOwned(ctxt,
+ if (xmlSchemaBuildAttributeUsesOwned(ctxt, isRestriction,
((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
- lastUse) == -1) {
+ lastUse, hasProhibitions) == -1) {
return (-1);
}
+ } else if ((! isRestriction) &&
+ (cur->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
+ /*
+ * Warn about pointless prohibitions when extending.
+ */
+ xmlSchemaCustomWarning(ACTXT_CAST ctxt,
+ XML_SCHEMAP_WARN_ATTR_REDECL_PROH,
+ cur->node, NULL,
+ "Attribute use prohibitions are pointless when "
+ "extending a type", NULL, NULL, NULL);
} else {
/* W3C: "1 The set of attribute uses corresponding to the
* <attribute> [children], if any."
@@ -12249,6 +12439,8 @@
else
(*lastUse)->next = tmp;
*lastUse = tmp;
+ if (cur->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
+ (*hasProhibitions)++;
}
cur = cur->next;
}
@@ -12969,11 +13161,11 @@
{
xmlSchemaTypePtr baseType = NULL;
xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
- prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
+ prev = NULL, localUses = NULL, lastUse = NULL, lastBaseUse = NULL;
xmlSchemaAttributePtr attrs;
xmlSchemaTypePtr anyType;
xmlChar *str = NULL;
- int err = 0;
+ int err = 0, hasProhibitions = 0;
anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
/*
@@ -12995,49 +13187,254 @@
}
baseType = type->baseType;
/*
- * Inherit the attribute uses of the base type.
- */
- /*
- * NOTE: It is allowed to "extend" the anyType complex type.
- */
- if (! IS_ANYTYPE(baseType)) {
- if (baseType != NULL) {
- for (cur = baseType->attributeUses; cur != NULL;
- cur = cur->next) {
- tmp = (xmlSchemaAttributeLinkPtr)
- xmlMalloc(sizeof(xmlSchemaAttributeLink));
- if (tmp == NULL) {
- xmlSchemaPErrMemory(pctxt,
- "building attribute uses of complexType", NULL);
- return (-1);
- }
- tmp->attr = cur->attr;
- tmp->next = NULL;
- if (type->attributeUses == NULL) {
- type->attributeUses = tmp;
- } else
- lastBaseUse->next = tmp;
- lastBaseUse = tmp;
- }
+ * Gather attribute uses defined by this type.
+ */
+ attrs = type->attributes;
+ if (attrs != NULL) {
+ if (xmlSchemaBuildAttributeUsesOwned(pctxt,
+ WXS_IS_RESTRICTION(type) ? 1 : 0,
+ attrs,
+ &localUses, &lastUse, &hasProhibitions) == -1) {
+ return (-1);
+ }
+ /*
+ * Handle attribute wildcards.
+ */
+ err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
+ attrs, &type->attributeWildcard);
+ /*
+ * NOTE: During the parse time, the wildcard is created
+ * on the complexType directly, if encountered in a
+ * <restriction> or <extension> element.
+ */
+ if (err == -1) {
+ PERROR_INT("xmlSchemaBuildAttributeValidation",
+ "failed to build an intersected attribute wildcard");
+ return (-1);
}
}
- attrs = type->attributes;
- /*
- * Handle attribute wildcards.
- */
- err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
- attrs, &type->attributeWildcard);
- /*
- * NOTE: During the parse time, the wildcard is created on the complexType
- * directly, if encountered in a <restriction> or <extension> element.
- */
- if (err == -1) {
- PERROR_INT("xmlSchemaBuildAttributeValidation",
- "failed to build an intersected attribute wildcard");
- return (-1);
+
+ if (hasProhibitions) {
+ xmlSchemaAttributeLinkPtr tmpPrev = NULL;
+ /*
+ * Handle annoying pointless prohibitions.
+ * Note that this will be done for restrictions only, since
+ * prohibitions are not gathered for extensions.
+ */
+ cur = localUses;
+
+pointless_prohib_next:
+ while (cur != NULL) {
+ tmp = cur->next;
+ tmpPrev = cur;
+ while (tmp != NULL) {
+ if ( ((cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
+ (tmp->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED)) ||
+ (xmlSchemaGetAttrName(cur->attr) !=
+ xmlSchemaGetAttrName(tmp->attr)) ||
+ (xmlSchemaGetAttrTargetNsURI(cur->attr) !=
+ xmlSchemaGetAttrTargetNsURI(tmp->attr)))
+ {
+ tmpPrev = tmp;
+ tmp = tmp->next;
+ continue;
+ }
+ if (cur->attr->occurs == tmp->attr->occurs) {
+ xmlSchemaAttributeLinkPtr tmpFree;
+ /*
+ * Warn about duplicate prohibitions.
+ */
+ xmlSchemaCustomWarning(ACTXT_CAST pctxt,
+ XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
+ tmp->attr->node, NULL,
+ "Skipping duplicate prohibition "
+ "of attribute use '%s'",
+ xmlSchemaFormatQName(&str,
+ xmlSchemaGetAttrTargetNsURI(tmp->attr),
+ xmlSchemaGetAttrName(tmp->attr)),
+ NULL, NULL);
+ FREE_AND_NULL(str)
+ /*
+ * Remove the duplicate prohibition.
+ */
+ tmpFree = tmp;
+ tmpPrev->next = tmp->next;
+ tmp = tmp->next;
+ xmlFree(tmpFree);
+ hasProhibitions--;
+ continue;
+ } else {
+ xmlSchemaAttributeLinkPtr tmpFree;
+ xmlSchemaAttributePtr reattr;
+ /*
+ * Annoying case:
+ * This is the case when we prohibited
+ * the base attribute decl in the previous
+ * step; i.e. when we prohibit and declare the
+ * same attribute in the same <complexType>.
+ */
+ if (cur->attr->occurs ==
+ XML_SCHEMAS_ATTR_USE_PROHIBITED)
+ reattr = cur->attr;
+ else
+ reattr = tmp->attr;
+ xmlSchemaCustomWarning(ACTXT_CAST pctxt,
+ XML_SCHEMAP_WARN_ATTR_REDECL_PROH,
+ reattr->node, NULL,
+ "Skipping pointless prohibition of "
+ "attribute use '%s', since a corresponding "
+ "attribute was explicitely declared as well",
+ xmlSchemaFormatQName(&str,
+ xmlSchemaGetAttrTargetNsURI(reattr),
+ xmlSchemaGetAttrName(reattr)),
+ NULL, NULL);
+ FREE_AND_NULL(str);
+ /*
+ * Remove the prohibition.
+ */
+ if (reattr == cur->attr) {
+ tmpFree = cur;
+ if (prev != NULL)
+ prev->next = cur->next;
+ else
+ localUses = cur->next;
+ cur = cur->next;
+ xmlFree(tmpFree);
+ hasProhibitions--;
+ goto pointless_prohib_next;
+ } else {
+ tmpFree = tmp;
+ tmpPrev->next = tmp->next;
+ tmp = tmp->next;
+ xmlFree(tmpFree);
+ hasProhibitions--;
+ continue;
+ }
+ }
+ tmpPrev = tmp;
+ tmp = tmp->next;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
}
- if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
+ /* 3.4.6 -> Complex Type Definition Properties Correct 4.
+ * "Two distinct attribute declarations in the {attribute uses} must
+ * not have identical {name}s and {target namespace}s."
+ *
+ * This is done here for <restriction>s. We will compare only the
+ * attr uses of the current type.
+ * For <extension>s this is done further down.
+ */
+ if ((localUses != NULL) && (localUses->next != NULL) &&
+ (WXS_IS_RESTRICTION(type))) {
+ cur = localUses;
+ while (cur != NULL) {
+ if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
+ cur = cur->next;
+ continue;
+ }
+ tmp = cur->next;
+ while (tmp != NULL) {
+ if (tmp->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
+ tmp = tmp->next;
+ continue;
+ }
+ if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
+ xmlSchemaGetAttrName(tmp->attr))) &&
+ (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
+ xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
+ /*
+ * Duplicate attr uses.
+ */
+ xmlSchemaPAttrUseErr(pctxt,
+ XML_SCHEMAP_CT_PROPS_CORRECT_4,
+ type, cur->attr,
+ "Duplicate attribute use '%s' specified",
+ xmlSchemaFormatQName(&str,
+ xmlSchemaGetAttrTargetNsURI(tmp->attr),
+ xmlSchemaGetAttrName(tmp->attr)));
+ FREE_AND_NULL(str)
+ break;
+ }
+ tmp = tmp->next;
+ }
+ cur = cur->next;
+ }
+ }
+
+ /*
+ * Inherit the attribute uses of the base type, but leave out
+ * prohibited ones.
+ * NOTE: It is allowed to "extend" the anyType complex type.
+ */
+ if (baseType->attributeUses != NULL) {
+ base = baseType->attributeUses;
+inherit_start:
+ while (base != NULL) {
+ /*
+ * Check if prohibited.
+ */
+ if (hasProhibitions) {
+ cur = localUses;
+ while (cur != NULL) {
+ if ((cur->attr->occurs ==
+ XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
+ xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
+ xmlSchemaGetAttrName(base->attr)) &&
+ xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
+ xmlSchemaGetAttrTargetNsURI(base->attr)))
+ {
+ /*
+ * Don't inherit prohibited attr uses.
+ */
+ if (base->attr->occurs ==
+ XML_SCHEMAS_ATTR_USE_REQUIRED) {
+ /*
+ * derivation-ok-restriction 3
+ * There won't be an attr use left if
+ * prohibiting the inherited one, so this
+ * will automatically violate required
+ * attr uses.
+ */
+ xmlSchemaPCustomErr(pctxt,
+ XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
+ NULL, type, NULL,
+ "A matching attribute use for the "
+ "'required' attribute use '%s' of the "
+ "base type is missing",
+ xmlSchemaFormatQName(&str,
+ xmlSchemaGetAttrTargetNsURI(base->attr),
+ xmlSchemaGetAttrName(base->attr)));
+ FREE_AND_NULL(str)
+ }
+ base = base->next;
+ goto inherit_start;
+ }
+ cur = cur->next;
+ }
+ }
+ tmp = (xmlSchemaAttributeLinkPtr)
+ xmlMalloc(sizeof(xmlSchemaAttributeLink));
+ if (tmp == NULL) {
+ xmlSchemaPErrMemory(pctxt,
+ "allocating attribute uses", NULL);
+ return (-1);
+ }
+ tmp->attr = base->attr;
+ tmp->next = NULL;
+ if (type->attributeUses == NULL) {
+ type->attributeUses = tmp;
+ } else
+ lastBaseUse->next = tmp;
+ lastBaseUse = tmp;
+ /* next */
+ base = base->next;
+ }
+ }
+
+ if ((WXS_IS_EXTENSION(type)) &&
((IS_ANYTYPE(baseType)) ||
((baseType != NULL) &&
(baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
@@ -13061,7 +13458,7 @@
}
}
- if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
+ if (WXS_IS_RESTRICTION(type)) {
if (type->attributeWildcard != NULL) {
/*
* Derivation Valid (Restriction, Complex)
@@ -13108,7 +13505,7 @@
return (1);
}
}
- } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
+ } else if (WXS_IS_EXTENSION(type)) {
/*
* Derivation Valid (Extension)
* At this point the type and the base have both, either
@@ -13130,80 +13527,40 @@
}
}
}
-
- /*
- * Gather attribute uses defined by this type.
- */
- if (attrs != NULL) {
- if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
- &uses, &lastUse) == -1) {
- return (-1);
- }
- }
- /* 3.4.6 -> Complex Type Definition Properties Correct 4.
- * "Two distinct attribute declarations in the {attribute uses} must
- * not have identical {name}s and {target namespace}s."
- *
- * For "extension" this is done further down.
- */
- if ((uses != NULL) && ((type->flags &
- XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
- cur = uses;
- while (cur != NULL) {
- tmp = cur->next;
- while (tmp != NULL) {
- if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
- xmlSchemaGetAttrName(tmp->attr))) &&
- (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
- xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
-
- xmlSchemaPAttrUseErr(pctxt,
- XML_SCHEMAP_CT_PROPS_CORRECT_4,
- type, cur->attr,
- "Duplicate attribute use %s specified",
- xmlSchemaFormatQName(&str,
- xmlSchemaGetAttrTargetNsURI(tmp->attr),
- xmlSchemaGetAttrName(tmp->attr)));
- FREE_AND_NULL(str)
- break;
- }
- tmp = tmp->next;
- }
- cur = cur->next;
- }
- }
- if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
+
+ if (localUses == NULL) {
+ /* PASS */
+ } else if (WXS_IS_RESTRICTION(type)) {
/*
- * Derive by restriction.
+ * Derive by restriction. At this point prohibited uses are already
+ * filtered out.
*/
if (IS_ANYTYPE(baseType)) {
- type->attributeUses = uses;
+ type->attributeUses = localUses;
} else {
int found, valid;
const xmlChar *bEffValue;
int effFixed;
- cur = uses;
+ cur = localUses;
while (cur != NULL) {
+ if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
+ prev = cur;
+ cur = cur->next;
+ continue;
+ }
found = 0;
valid = 1;
base = type->attributeUses;
while (base != NULL) {
if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
- xmlSchemaGetAttrName(base->attr)) &&
+ xmlSchemaGetAttrName(base->attr)) &&
xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
- xmlSchemaGetAttrTargetNsURI(base->attr))) {
+ xmlSchemaGetAttrTargetNsURI(base->attr))) {
found = 1;
if ((cur->attr->occurs ==
- XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
- (base->attr->occurs ==
- XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
- /*
- * NOOP.
- */
- } else if ((cur->attr->occurs ==
XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
(base->attr->occurs ==
XML_SCHEMAS_ATTR_USE_REQUIRED)) {
@@ -13216,23 +13573,6 @@
"The 'optional' use is inconsistent with a "
"matching 'required' use of the base type",
NULL);
- } else if ((cur->attr->occurs ==
- XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
- (base->attr->occurs ==
- XML_SCHEMAS_ATTR_USE_REQUIRED)) {
- /*
- * derivation-ok-restriction 3
- */
- xmlSchemaPCustomErr(pctxt,
- XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
- NULL, type, NULL,
- "A matching attribute use for the 'required' "
- "attribute use '%s' of the base type is "
- "missing",
- xmlSchemaFormatQName(&str,
- xmlSchemaGetAttrTargetNsURI(base->attr),
- xmlSchemaGetAttrName(base->attr)));
- FREE_AND_NULL(str)
} else if (xmlSchemaCheckCOSSTDerivedOK(
cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
@@ -13299,8 +13639,7 @@
base = base->next;
}
- if ((!found) && (cur->attr->occurs !=
- XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
+ if (!found) {
/*
* derivation-ok-restriction 2.2
*/
@@ -13326,7 +13665,7 @@
if (prev != NULL)
prev->next = cur->next;
else
- uses = cur->next;
+ localUses = cur->next;
cur = cur->next;
tmp->next = NULL;
if (type->attributeUses == NULL) {
@@ -13341,20 +13680,20 @@
prev = cur;
cur = cur->next;
}
- if (uses != NULL)
- xmlSchemaFreeAttributeUseList(uses);
+ if (localUses != NULL)
+ xmlSchemaFreeAttributeUseList(localUses);
}
- } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
+ } else if (WXS_IS_EXTENSION(type)) {
/*
* The spec allows only appending, and not other kinds of extensions.
*
* This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
*/
- if (uses != NULL) {
+ if (localUses != NULL) {
if (type->attributeUses == NULL) {
- type->attributeUses = uses;
+ type->attributeUses = localUses;
} else
- lastBaseUse->next = uses;
+ lastBaseUse->next = localUses;
}
} else {
PERROR_INT("xmlSchemaBuildAttributeValidation",
@@ -13368,6 +13707,22 @@
cur = type->attributeUses;
prev = NULL;
while (cur != NULL) {
+ if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
+ /*
+ * Remove "prohibited" attribute uses. The reason this is
+ * done at this late stage is to be able to catch
+ * dublicate attribute uses. So we had to keep prohibited
+ * uses in the list as well.
+ */
+ tmp = cur;
+ if (prev == NULL)
+ type->attributeUses = cur->next;
+ else
+ prev->next = cur->next;
+ cur = cur->next;
+ xmlFree(tmp);
+ continue;
+ }
/*
* 4. Two distinct attribute declarations in the {attribute uses} must
* not have identical {name}s and {target namespace}s.
@@ -13375,7 +13730,7 @@
* Note that this was already done for "restriction" and types derived from
* the ur-type.
*/
- if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
+ if (WXS_IS_EXTENSION(type)) {
tmp = cur->next;
while (tmp != NULL) {
if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
@@ -13391,42 +13746,29 @@
}
tmp = tmp->next;
}
- }
+ }
+
/*
- * 5. Two distinct attribute declarations in the {attribute uses} must
- * not have {type definition}s which are or are derived from ID.
+ * 5. Two distinct attribute declarations in the
+ * {attribute uses} must not have {type definition}s which
+ * are or are derived from ID.
*/
if ((cur->attr->subtypes != NULL) &&
(xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
- XML_SCHEMAS_ID))) {
+ XML_SCHEMAS_ID))) {
if (id != NULL) {
xmlSchemaPAttrUseErr(pctxt,
XML_SCHEMAP_CT_PROPS_CORRECT_5,
type, cur->attr,
- "There must not exist more than one attribute use, "
- "declared of type 'ID' or derived from it",
+ "There must not exist more than one attribute "
+ "use, declared of type 'ID' or derived from it",
NULL);
FREE_AND_NULL(str)
}
id = cur;
- }
- /*
- * Remove "prohibited" attribute uses. The reason this is done at this late
- * stage is to be able to catch dublicate attribute uses. So we had to keep
- * prohibited uses in the list as well.
- */
- if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
- tmp = cur;
- if (prev == NULL)
- type->attributeUses = cur->next;
- else
- prev->next = cur->next;
- cur = cur->next;
- xmlFree(tmp);
- } else {
- prev = cur;
- cur = cur->next;
- }
+ }
+ prev = cur;
+ cur = cur->next;
}
}
/*
@@ -13760,8 +14102,7 @@
*/
static void
xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
- xmlSchemaParserCtxtPtr ctxt,
- const xmlChar * name ATTRIBUTE_UNUSED)
+ xmlSchemaParserCtxtPtr ctxt)
{
if ((item == NULL) ||
((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
@@ -13777,16 +14118,78 @@
xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
}
+/*
+* Simple Type Definition Representation OK (src-simple-type) 4
+*
+* "4 Circular union type definition is disallowed. That is, if the
+* <union> alternative is chosen, there must not be any entries in the
+* memberTypes [attribute] at any depth which resolve to the component
+* corresponding to the <simpleType>."
+*
+* Note that this should work on the *representation* of a component,
+* thus assumes any union types in the member types not being yet
+* substituted. At this stage we need the variety of the types
+* to be already computed.
+*/
+static int
+xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
+ xmlSchemaTypePtr ctxType,
+ xmlSchemaTypeLinkPtr members)
+{
+ xmlSchemaTypeLinkPtr member;
+ xmlSchemaTypePtr memberType;
+
+ member = members;
+ while (member != NULL) {
+ memberType = member->type;
+ while ((memberType != NULL) &&
+ (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
+ if (memberType == ctxType) {
+ xmlSchemaPCustomErr(pctxt,
+ XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
+ NULL, ctxType, NULL,
+ "The union type definition is circular", NULL);
+ return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
+ }
+ if ((VARIETY_UNION(memberType)) &&
+ ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
+ {
+ int res;
+ memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
+ res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
+ ctxType,
+ xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
+ memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
+ if (res != 0)
+ return(res);
+ }
+ memberType = memberType->baseType;
+ }
+ member = member->next;
+ }
+ return(0);
+}
+
+static int
+xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
+ xmlSchemaTypePtr type)
+{
+ if (! VARIETY_UNION(type))
+ return(0);
+ return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
+ type->memberTypes));
+}
+
/**
- * xmlSchemaResolveTypeDefs:
+ * xmlSchemaResolveTypeReferences:
* @item: the complex/simple type definition
* @ctxt: the parser context
* @name: the name
*
- * Checks for circular type definitions.
+ * Resolvese type definition references
*/
static void
-xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
+xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
xmlSchemaParserCtxtPtr ctxt,
const xmlChar * name ATTRIBUTE_UNUSED)
{
@@ -13854,8 +14257,7 @@
xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaTypePtr type)
{
- xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
- anyType;
+ xmlSchemaTypePtr baseType = type->baseType;
xmlChar *str = NULL;
/* STATE: error funcs converted. */
@@ -13865,8 +14267,6 @@
* NOTE: This is somehow redundant, since we actually built a simple type
* to have all the needed information; this acts as an self test.
*/
- anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
- anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
/* Base type: If the datatype has been ·derived· by ·restriction·
* then the Simple Type Definition component from which it is ·derived·,
* otherwise the Simple Type Definition for anySimpleType (§4.1.6).
@@ -13893,7 +14293,7 @@
return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
}
if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
- ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
+ (WXS_IS_RESTRICTION(type) == 0) &&
(! IS_ANY_SIMPLE_TYPE(baseType))) {
xmlSchemaPCustomErr(ctxt,
XML_SCHEMAP_ST_PROPS_CORRECT_1,
@@ -14046,7 +14446,7 @@
return (-1);
}
if (IS_NOT_TYPEFIXED(itemType))
- xmlSchemaTypeFixup(itemType, pctxt, NULL);
+ xmlSchemaTypeFixup(itemType, pctxt);
/*
* 2.1 The {item type definition} must have a {variety} of atomic or
* union (in which case all the {member type definitions}
@@ -14245,7 +14645,7 @@
member = type->memberTypes;
while (member != NULL) {
if (IS_NOT_TYPEFIXED(member->type))
- xmlSchemaTypeFixup(member->type, pctxt, NULL);
+ xmlSchemaTypeFixup(member->type, pctxt);
if ((! VARIETY_ATOMIC(member->type)) &&
(! VARIETY_LIST(member->type))) {
@@ -14416,12 +14816,13 @@
* @ctxt: the schema parser context
* @type: the simple type definition
*
- * Checks crc-simple-type constraints.
+ * Checks crc-simple-type constraints.
*
* Returns 0 if the constraints are satisfied,
* if not a positive error code and -1 on internal
* errors.
*/
+#if 0
static int
xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaTypePtr type)
@@ -14430,82 +14831,32 @@
* src-simple-type.1 The corresponding simple type definition, if any,
* must satisfy the conditions set out in Constraints on Simple Type
* Definition Schema Components (§3.14.6).
- */
- if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
- (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
+ */
+ if (WXS_IS_RESTRICTION(type)) {
/*
- * TODO: Removed this, since it got annoying to get an
- * extra error report, if anything failed until now.
- * Enable this if needed.
- */
- /*
- xmlSchemaPErr(ctxt, type->node,
- XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
- "Simple type '%s' does not satisfy the constraints "
- "on simple type definitions.\n",
- type->name, NULL);
- */
- return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
- }
-
- if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
- /*
- * src-simple-type.2 If the <restriction> alternative is chosen,
+ * src-simple-type.2 "If the <restriction> alternative is chosen,
* either it must have a base [attribute] or a <simpleType> among its
- * [children], but not both.
- */
- /*
- * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
+ * [children], but not both."
* NOTE: This is checked in the parse function of <restriction>.
*/
+ /*
+ *
+ */
} else if (VARIETY_LIST(type)) {
- /* src-simple-type.3 If the <list> alternative is chosen, either it must have
+ /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
* an itemType [attribute] or a <simpleType> among its [children],
- * but not both.
+ * but not both."
*
- * REMOVED: This is checked in the parse function of <list>.
+ * NOTE: This is checked in the parse function of <list>.
*/
- } else if (VARIETY_UNION(type)) {
- xmlSchemaTypeLinkPtr member;
- xmlSchemaTypePtr ancestor, anySimpleType;
-
- anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
-
- /* src-simple-type.4 Circular union type definition is disallowed. That is, if
- * the <union> alternative is chosen, there must not be any entries
- * in the memberTypes [attribute] at any depth which resolve to the
- * component corresponding to the <simpleType>.
+ } else if (VARIETY_UNION(type)) {
+ /*
+ * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
*/
- member = type->memberTypes;
- while (member != NULL) {
- ancestor = member->type;
- while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
- if (ancestor == type) {
- xmlSchemaPCustomErr(ctxt,
- XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
- NULL, type, NULL,
- "The definition is circular", NULL);
- return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
- }
- if (IS_NOT_TYPEFIXED(ancestor))
- xmlSchemaTypeFixup(ancestor, ctxt, NULL);
- if (VARIETY_LIST(ancestor)) {
- /*
- * TODO, FIXME: Although a list simple type must not have a union ST
- * type as item type, which in turn has a list ST as member
- * type, we will assume this here as well, since this check
- * was not yet performed.
- */
- }
-
- ancestor = ancestor->baseType;
- }
- member = member->next;
- }
}
-
return (0);
}
+#endif
static int
xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
@@ -14521,7 +14872,8 @@
return (-1);
}
/* TODO: Pass user data. */
- xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
+ xmlSchemaSetValidErrors(ctxt->vctxt,
+ ctxt->error, ctxt->warning, ctxt->userData);
}
return (0);
}
@@ -14601,10 +14953,10 @@
* as defined by String Valid (§3.14.4).
*/
if (IS_SIMPLE_TYPE(type))
- ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
+ ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
type, value, val, 1, 1, 0);
else if (HAS_SIMPLE_CONTENT(type))
- ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
+ ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
type->contentTypeDef, value, val, 1, 1, 0);
else
return (ret);
@@ -14644,7 +14996,7 @@
*/
if ((type->baseType != NULL) &&
(IS_SIMPLE_TYPE(type->baseType)) &&
- ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
+ (WXS_IS_EXTENSION(type) == 0)) {
/*
* SPEC (2) "If the {base type definition} is a simple type definition,
* the {derivation method} must be extension."
@@ -14719,10 +15071,8 @@
* SPEC (1) "If B and D are not the same type definition, then the
* {derivation method} of D must not be in the subset."
*/
- if (((set & SUBSET_EXTENSION) &&
- (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
- ((set & SUBSET_RESTRICTION) &&
- (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
+ if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
+ ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
return (1);
} else {
/*
@@ -15132,7 +15482,7 @@
ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
if (ret != 0)
return (ret);
- if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
+ if (WXS_IS_EXTENSION(type))
ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
else
ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
@@ -15190,8 +15540,7 @@
* base [attribute] must be one of the following:
*/
if (IS_SIMPLE_TYPE(base)) {
- if ((type->flags &
- XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
+ if (WXS_IS_EXTENSION(type) == 0) {
xmlChar *str = NULL;
/*
* 2.1.3 only if the <extension> alternative is also
@@ -15227,8 +15576,7 @@
return (-1);
}
} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
- (type->flags &
- XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
+ (WXS_IS_RESTRICTION(type))) {
/*
* 2.1.2 only if the <restriction> alternative is also
@@ -15268,7 +15616,7 @@
}
if (ret > 0) {
xmlChar *str = NULL;
- if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
+ if (WXS_IS_RESTRICTION(type)) {
xmlSchemaPCustomErr(ctxt,
XML_SCHEMAP_SRC_CT_1,
NULL, type, NULL,
@@ -15758,6 +16106,12 @@
xmlFree(msg);
}
+/*
+* xmlSchemaDeriveAndValidateFacets:
+*
+* Schema Component Constraint: Simple Type Restriction (Facets)
+* (st-restrict-facets)
+*/
static int
xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
xmlSchemaTypePtr type)
@@ -15774,14 +16128,29 @@
bfmininc = NULL, bfmaxinc = NULL,
bfminexc = NULL, bfmaxexc = NULL;
int res, err = 0, fixedErr;
+
/*
- * 3 The {facets} of R are the union of S and the {facets}
+ * SPEC st-restrict-facets 1:
+ * "The {variety} of R is the same as that of B."
+ */
+ /*
+ * SPEC st-restrict-facets 2:
+ * "If {variety} is atomic, the {primitive type definition}
+ * of R is the same as that of B."
+ *
+ * NOTE: we leave 1 & 2 out for now, since this will be
+ * satisfied by the derivation process.
+ * CONSTRUCTION TODO: Maybe needed if using a construction API.
+ */
+ /*
+ * SPEC st-restrict-facets 3:
+ * "The {facets} of R are the union of S and the {facets}
* of B, eliminating duplicates. To eliminate duplicates,
* when a facet of the same kind occurs in both S and the
* {facets} of B, the one in the {facets} of B is not
* included, with the exception of enumeration and pattern
* facets, for which multiple occurrences with distinct values
- * are allowed.
+ * are allowed."
*/
if ((type->facetSet == NULL) && (base->facetSet == NULL))
@@ -16278,10 +16647,8 @@
return (0);
internal_error:
- xmlSchemaPCustomErr(pctxt,
- XML_SCHEMAP_INVALID_FACET_VALUE,
- NULL, type, NULL,
- "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
+ PERROR_INT("xmlSchemaDeriveAndValidateFacets",
+ "an error occured");
return (-1);
}
@@ -16299,7 +16666,7 @@
while (link != NULL) {
if (IS_NOT_TYPEFIXED(link->type))
- xmlSchemaTypeFixup(link->type, pctxt, NULL);
+ xmlSchemaTypeFixup(link->type, pctxt);
if (VARIETY_UNION(link->type)) {
subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
@@ -16451,451 +16818,81 @@
return (0);
}
-/**
- * xmlSchemaTypeFixup:
- * @typeDecl: the schema type definition
- * @ctxt: the schema parser context
- *
- * Fixes the content model of the type.
- */
-static void
-xmlSchemaTypeFixup(xmlSchemaTypePtr type,
- xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
+static int
+xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
+ xmlSchemaTypePtr type)
{
- if (type == NULL)
- return;
- if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
- (type->type != XML_SCHEMA_TYPE_SIMPLE))
- return;
- if (! IS_NOT_TYPEFIXED(type))
- return;
- type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
- if (name == NULL)
- name = type->name;
+ if (type->type != XML_SCHEMA_TYPE_SIMPLE)
+ return(0);
+ if (! TYPE_IS_NOT_FIXEDUP_1(type))
+ return(0);
+ type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
- if (type->baseType == NULL) {
- xmlSchemaPCustomErr(pctxt,
- XML_SCHEMAP_INTERNAL,
- NULL, type, NULL,
- "Internal error: xmlSchemaTypeFixup, "
- "baseType is missing on '%s'", type->name);
- return;
- }
-
- if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
- xmlSchemaTypePtr baseType = type->baseType;
-
+ if (VARIETY_LIST(type)) {
/*
- * Type-fix the base type.
+ * Corresponds to <simpleType><list>...
*/
- if (IS_NOT_TYPEFIXED(baseType))
- xmlSchemaTypeFixup(baseType, pctxt, NULL);
- if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
+ if (type->subtypes == NULL) {
/*
- * Skip fixup if the base type is invalid.
- * TODO: Generate a warning!
+ * This one is really needed, so get out.
*/
- return;
- }
- /*
- * This basically checks if the base type can be derived.
- */
- if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
- type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
- return;
- }
- /*
- * Fixup the content type.
- */
- if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
- /*
- * Corresponds to <complexType><simpleContent>...
- */
- if ((IS_COMPLEX_TYPE(baseType)) &&
- (baseType->contentTypeDef != NULL) &&
- (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
- xmlSchemaTypePtr contentBase, content;
- char buf[30];
- const xmlChar *tmpname;
- /*
- * SPEC (1) If <restriction> + base type is <complexType>,
- * "whose own {content type} is a simple type..."
- */
- if (type->contentTypeDef != NULL) {
- /*
- * SPEC (1.1) "the simple type definition corresponding to the
- * <simpleType> among the [children] of <restriction> if there
- * is one;"
- * Note that this "<simpleType> among the [children]" was put
- * into ->contentTypeDef during parsing.
- */
- contentBase = type->contentTypeDef;
- type->contentTypeDef = NULL;
- } else {
- /*
- * (1.2) "...otherwise (<restriction> has no <simpleType>
- * among its [children]), the simple type definition which
- * is the {content type} of the ... base type."
- */
- contentBase = baseType->contentTypeDef;
- }
- /*
- * SPEC
- * "... a simple type definition which restricts the simple
- * type definition identified in clause 1.1 or clause 1.2
- * with a set of facet components"
- *
- * Create the anonymous simple type, which will be the content
- * type of the complex 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, 0);
- if (content == NULL)
- return;
- /*
- * We will use the same node as for the <complexType>
- * to have it somehow anchored in the schema doc.
- */
- content->node = type->node;
- content->type = XML_SCHEMA_TYPE_SIMPLE;
- content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
- content->baseType = contentBase;
- /*
- * Move the facets, previously anchored on the complexType.
- */
- content->facets = type->facets;
- type->facets = NULL;
- content->facetSet = type->facetSet;
- type->facetSet = NULL;
-
- type->contentTypeDef = content;
- if (IS_NOT_TYPEFIXED(contentBase))
- xmlSchemaTypeFixup(contentBase, pctxt, NULL);
- xmlSchemaTypeFixup(content, pctxt, NULL);
-
- } else if ((IS_COMPLEX_TYPE(baseType)) &&
- (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
- (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
- /*
- * SPEC (2) If <restriction> + base is a mixed <complexType> with
- * an emptiable particle, then a simple type definition which
- * restricts the <restriction>'s <simpleType> child.
- */
- if ((type->contentTypeDef == NULL) ||
- (type->contentTypeDef->baseType == NULL)) {
- /*
- * TODO: Check if this ever happens.
- */
- xmlSchemaPCustomErr(pctxt,
- XML_SCHEMAP_INTERNAL,
- NULL, type, NULL,
- "Internal error: xmlSchemaTypeFixup, "
- "complex type '%s': the <simpleContent><restriction> "
- "is missing a <simpleType> child, but was not catched "
- "by xmlSchemaCheckSRCCT()", type->name);
- }
- } else if ((IS_COMPLEX_TYPE(baseType)) &&
- (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
- /*
- * SPEC (3) If <extension> + base is <complexType> with
- * <simpleType> content, "...then the {content type} of that
- * complex type definition"
- */
- if (baseType->contentTypeDef == NULL) {
- /*
- * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
- * should have catched this already.
- */
- xmlSchemaPCustomErr(pctxt,
- XML_SCHEMAP_INTERNAL,
- NULL, type, NULL,
- "Internal error: xmlSchemaTypeFixup, "
- "complex type '%s': the <extension>ed base type is "
- "a complex type with no simple content type",
- type->name);
- }
- type->contentTypeDef = baseType->contentTypeDef;
- } else if ((IS_SIMPLE_TYPE(baseType)) &&
- (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
- /*
- * SPEC (4) <extension> + base is <simpleType>
- * "... then that simple type definition"
- */
- type->contentTypeDef = baseType;
- } else {
- /*
- * TODO: Check if this ever happens.
- */
- xmlSchemaPCustomErr(pctxt,
- XML_SCHEMAP_INTERNAL,
- NULL, type, NULL,
- "Internal error: xmlSchemaTypeFixup, "
- "complex type '%s' with <simpleContent>: unhandled "
- "derivation case", type->name);
- }
- } else {
- int dummySequence = 0;
- xmlSchemaParticlePtr particle =
- (xmlSchemaParticlePtr) type->subtypes;
- /*
- * Corresponds to <complexType><complexContent>...
- *
- * NOTE that the effective mixed was already set during parsing of
- * <complexType> and <complexContent>; its flag value is
- * XML_SCHEMAS_TYPE_MIXED.
- *
- * Compute the "effective content":
- * (2.1.1) + (2.1.2) + (2.1.3)
- */
- if ((particle == NULL) ||
- ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
- ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
- (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
- ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
- (particle->minOccurs == 0))) &&
- ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
- if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
- /*
- * SPEC (2.1.4) "If the ·effective mixed· is true, then
- * a particle whose properties are as follows:..."
- *
- * Empty sequence model group with
- * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
- * NOTE that we sill assign it the <complexType> node to
- * somehow anchor it in the doc.
- */
- if ((particle == NULL) ||
- (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
- /*
- * Create the particle.
- */
- particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
- type->node, 1, 1);
- if (particle == NULL)
- return;
- /*
- * Create the model group.
- */
- particle->children = (xmlSchemaTreeItemPtr)
- xmlSchemaAddModelGroup(pctxt, pctxt->schema,
- XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
- if (particle->children == NULL)
- return;
-
- type->subtypes = (xmlSchemaTypePtr) particle;
- }
- dummySequence = 1;
- type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
- } else {
- /*
- * SPEC (2.1.5) "otherwise empty"
- */
- type->contentType = XML_SCHEMA_CONTENT_EMPTY;
- }
- } else {
- /*
- * SPEC (2.2) "otherwise the particle corresponding to the
- * <all>, <choice>, <group> or <sequence> among the
- * [children]."
- */
- type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
- }
- /*
- * Compute the "content type".
- */
- if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
- /*
- * SPEC (3.1) "If <restriction>..."
- * (3.1.1) + (3.1.2) */
- if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
- if (type->flags & XML_SCHEMAS_TYPE_MIXED)
- type->contentType = XML_SCHEMA_CONTENT_MIXED;
- }
- } else {
- /*
- * SPEC (3.2) "If <extension>..."
- */
- if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
- /*
- * SPEC (3.2.1)
- */
- type->contentType = baseType->contentType;
- type->subtypes = baseType->subtypes;
- /*
- * NOTE that the effective mixed is ignored here.
- */
- } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
- /*
- * SPEC (3.2.2)
- */
- if (type->flags & XML_SCHEMAS_TYPE_MIXED)
- type->contentType = XML_SCHEMA_CONTENT_MIXED;
- } else {
- /*
- * SPEC (3.2.3)
- */
- if (type->flags & XML_SCHEMAS_TYPE_MIXED)
- type->contentType = XML_SCHEMA_CONTENT_MIXED;
- /*
- * "A model group whose {compositor} is sequence and whose
- * {particles} are..."
- */
- if (! dummySequence) {
- xmlSchemaTreeItemPtr effectiveContent =
- (xmlSchemaTreeItemPtr) type->subtypes;
- /*
- * Create the particle.
- */
- particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
- type->node, 1, 1);
- if (particle == NULL)
- return;
- /*
- * Create the "sequence" model group.
- */
- particle->children = (xmlSchemaTreeItemPtr)
- xmlSchemaAddModelGroup(pctxt, pctxt->schema,
- XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
- if (particle->children == NULL)
- return;
- type->subtypes = (xmlSchemaTypePtr) particle;
- /*
- * SPEC "the particle of the {content type} of
- * the ... base ..."
- * Create a duplicate of the base type's particle
- * and assign its "term" to it.
- */
- particle->children->children =
- (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
- pctxt->schema, type->node,
- ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
- ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
- if (particle->children->children == NULL)
- return;
- particle = (xmlSchemaParticlePtr)
- particle->children->children;
- particle->children =
- ((xmlSchemaParticlePtr) baseType->subtypes)->children;
- /*
- * SPEC "followed by the ·effective content·."
- */
- particle->next = effectiveContent;
- } else {
- /*
- * This is the case when there is already an empty
- * <sequence> with minOccurs==maxOccurs==1.
- * Just add the base types's content type.
- * NOTE that, although we miss to add an intermediate
- * <sequence>, this should produce no difference to
- * neither the regex compilation of the content model,
- * nor to the complex type contraints.
- */
- particle->children->children =
- (xmlSchemaTreeItemPtr) baseType->subtypes;
- }
- }
- }
- }
- /*
- * Apply the complex type component constraints; this will not
- * check attributes, since this is done in
- * xmlSchemaBuildAttributeValidation().
- */
- if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
- return;
- /*
- * Inherit & check constraints for attributes.
- */
- xmlSchemaBuildAttributeValidation(pctxt, type);
- } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
- /*
- * Simple Type Definition Schema Component
- */
- type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
- if (VARIETY_LIST(type)) {
- /*
- * Corresponds to <simpleType><list>...
- */
- if (type->subtypes == NULL) {
- /*
- * This one is really needed, so get out.
- */
- PERROR_INT("xmlSchemaTypeFixup",
+ PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
"list type has no item-type assigned");
- return;
- }
- if (IS_NOT_TYPEFIXED(type->subtypes))
- xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
- } else if (VARIETY_UNION(type)) {
- /*
- * Corresponds to <simpleType><union>...
- */
- if (type->memberTypes == NULL) {
- /*
- * This one is really needed, so get out.
- */
- return;
- }
- if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
- return;
- } else {
- xmlSchemaTypePtr baseType = type->baseType;
- /*
- * Corresponds to <simpleType><restriction>...
- */
- if (IS_NOT_TYPEFIXED(baseType))
- xmlSchemaTypeFixup(baseType, pctxt, NULL);
- /*
- * Variety
- * If the <restriction> alternative is chosen, then the
- * {variety} of the {base type definition}.
- */
- if (VARIETY_ATOMIC(baseType))
- type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
- else if (VARIETY_LIST(baseType)) {
- type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
- /*
- * Inherit the itemType.
- */
- type->subtypes = baseType->subtypes;
- } else if (VARIETY_UNION(baseType)) {
- type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
- /*
- * NOTE that we won't assign the memberTypes of the base,
- * since this will make trouble when freeing them; we will
- * use a lookup function to access them instead.
- */
- }
+ return(-1);
}
+ } else if (VARIETY_UNION(type)) {
/*
- * Check constraints.
- *
- * TODO: Split this somehow, we need to know first if we can derive
- * from the base type at all!
+ * Corresponds to <simpleType><union>...
+ */
+ if (type->memberTypes == NULL) {
+ /*
+ * This one is really needed, so get out.
+ */
+ PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
+ "union type has no member-types assigned");
+ return(-1);
+ }
+ } else {
+ /*
+ * Corresponds to <simpleType><restriction>...
*/
- if (type->baseType != NULL) {
+ if (type->baseType == NULL) {
+ PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
+ "type has no base-type assigned");
+ return(-1);
+ }
+ if (TYPE_IS_NOT_FIXEDUP_1(type->baseType))
+ if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
+ return(-1);
+ /*
+ * Variety
+ * If the <restriction> alternative is chosen, then the
+ * {variety} of the {base type definition}.
+ */
+ if (VARIETY_ATOMIC(type->baseType))
+ type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
+ else if (VARIETY_LIST(type->baseType)) {
+ type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
/*
- * Schema Component Constraint: Simple Type Restriction
- * (Facets)
- * NOTE: Satisfaction of 1 and 2 arise from the fixup
- * applied beforehand.
+ * Inherit the itemType.
*/
- xmlSchemaCheckSRCSimpleType(pctxt, type);
- xmlSchemaCheckFacetValues(type, pctxt);
- if ((type->facetSet != NULL) ||
- (type->baseType->facetSet != NULL))
- xmlSchemaDeriveAndValidateFacets(pctxt, type);
+ type->subtypes = type->baseType->subtypes;
+ } else if (VARIETY_UNION(type->baseType)) {
+ type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
/*
- * Whitespace value.
+ * NOTE that we won't assign the memberTypes of the base,
+ * since this will make trouble when freeing them; we will
+ * use a lookup function to access them instead.
*/
- xmlSchemaTypeFixupWhitespace(type);
- xmlSchemaTypeFixupOptimFacets(type);
}
}
+ return(0);
+}
#ifdef DEBUG_TYPE
+xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
+ xmlSchemaTypePtr type)
+{
if (type->node != NULL) {
xmlGenericError(xmlGenericErrorContext,
"Type of %s : %s:%d :", name,
@@ -16941,7 +16938,503 @@
break;
}
}
+}
#endif
+
+/*
+* 3.14.6 Constraints on Simple Type Definition Schema Components
+*/
+static int
+xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
+ xmlSchemaTypePtr type)
+{
+ int res, olderrs = pctxt->nberrors;
+
+ if (type->type != XML_SCHEMA_TYPE_SIMPLE)
+ return(-1);
+
+ if (! IS_NOT_TYPEFIXED(type))
+ return(0);
+
+ type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
+ type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
+
+ if (type->baseType == NULL) {
+ PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
+ "missing baseType");
+ goto exit_failure;
+ }
+ if (IS_NOT_TYPEFIXED(type->baseType))
+ xmlSchemaTypeFixup(type->baseType, pctxt);
+ /*
+ * If a member type of a union is a union itself, we need to substitute
+ * that member type for its member types.
+ */
+ if ((type->memberTypes != NULL) &&
+ (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
+ return(-1);
+ /*
+ * SPEC src-simple-type 1
+ * "The corresponding simple type definition, if any, must satisfy
+ * the conditions set out in Constraints on Simple Type Definition
+ * Schema Components (§3.14.6)."
+ */
+ /*
+ * Schema Component Constraint: Simple Type Definition Properties Correct
+ * (st-props-correct)
+ */
+ res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
+ HFAILURE HERROR
+ /*
+ * Schema Component Constraint: Derivation Valid (Restriction, Simple)
+ * (cos-st-restricts)
+ */
+ res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
+ HFAILURE HERROR
+ /*
+ * TODO: Removed the error report, since it got annoying to get an
+ * extra error report, if anything failed until now.
+ * Enable this if needed.
+ *
+ * xmlSchemaPErr(ctxt, type->node,
+ * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
+ * "Simple type '%s' does not satisfy the constraints "
+ * "on simple type definitions.\n",
+ * type->name, NULL);
+ */
+ /*
+ * Schema Component Constraint: Simple Type Restriction (Facets)
+ * (st-restrict-facets)
+ */
+ res = xmlSchemaCheckFacetValues(type, pctxt);
+ HFAILURE HERROR
+ if ((type->facetSet != NULL) ||
+ (type->baseType->facetSet != NULL)) {
+ res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
+ HFAILURE HERROR
+ }
+ /*
+ * Whitespace value.
+ */
+ res = xmlSchemaTypeFixupWhitespace(type);
+ HFAILURE HERROR
+ xmlSchemaTypeFixupOptimFacets(type);
+
+exit_error:
+#ifdef DEBUG_TYPE
+ xmlSchemaDebugFixedType(pctxt, type);
+#endif
+ if (olderrs != pctxt->nberrors)
+ return(pctxt->err);
+ return(0);
+
+exit_failure:
+#ifdef DEBUG_TYPE
+ xmlSchemaDebugFixedType(pctxt, type);
+#endif
+ return(-1);
+}
+
+static int
+xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
+ xmlSchemaTypePtr type)
+{
+ int res = 0, olderrs = pctxt->nberrors;
+ xmlSchemaTypePtr baseType = type->baseType;
+
+ if (! IS_NOT_TYPEFIXED(type))
+ return(0);
+ type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
+ if (baseType == NULL) {
+ PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
+ "missing baseType");
+ goto exit_failure;
+ }
+ /*
+ * Fixup the base type.
+ */
+ if (IS_NOT_TYPEFIXED(baseType))
+ xmlSchemaTypeFixup(baseType, pctxt);
+ if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
+ /*
+ * Skip fixup if the base type is invalid.
+ * TODO: Generate a warning!
+ */
+ return(0);
+ }
+ /*
+ * This basically checks if the base type can be derived.
+ */
+ res = xmlSchemaCheckSRCCT(pctxt, type);
+ HFAILURE HERROR
+ /*
+ * Fixup the content type.
+ */
+ if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
+ /*
+ * Corresponds to <complexType><simpleContent>...
+ */
+ if ((IS_COMPLEX_TYPE(baseType)) &&
+ (baseType->contentTypeDef != NULL) &&
+ (WXS_IS_RESTRICTION(type))) {
+ xmlSchemaTypePtr contentBase, content;
+#ifdef ENABLE_NAMED_LOCALS
+ char buf[30];
+ const xmlChar *tmpname;
+#endif
+ /*
+ * SPEC (1) If <restriction> + base type is <complexType>,
+ * "whose own {content type} is a simple type..."
+ */
+ if (type->contentTypeDef != NULL) {
+ /*
+ * SPEC (1.1) "the simple type definition corresponding to the
+ * <simpleType> among the [children] of <restriction> if there
+ * is one;"
+ * Note that this "<simpleType> among the [children]" was put
+ * into ->contentTypeDef during parsing.
+ */
+ contentBase = type->contentTypeDef;
+ type->contentTypeDef = NULL;
+ } else {
+ /*
+ * (1.2) "...otherwise (<restriction> has no <simpleType>
+ * among its [children]), the simple type definition which
+ * is the {content type} of the ... base type."
+ */
+ contentBase = baseType->contentTypeDef;
+ }
+ /*
+ * SPEC
+ * "... a simple type definition which restricts the simple
+ * type definition identified in clause 1.1 or clause 1.2
+ * with a set of facet components"
+ *
+ * Create the anonymous simple type, which will be the content
+ * type of the complex type.
+ */
+#ifdef ENABLE_NAMED_LOCALS
+ snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
+ tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
+ content = xmlSchemaAddType(pctxt,
+ pctxt->schema, tmpname, type->targetNamespace,
+ type->node, 0);
+#else
+ content = xmlSchemaAddType(pctxt,
+ pctxt->schema, NULL, type->targetNamespace,
+ type->node, 0);
+#endif
+ if (content == NULL)
+ goto exit_failure;
+ /*
+ * We will use the same node as for the <complexType>
+ * to have it somehow anchored in the schema doc.
+ */
+ content->type = XML_SCHEMA_TYPE_SIMPLE;
+ content->baseType = contentBase;
+ /*
+ * Move the facets, previously anchored on the
+ * complexType during parsing.
+ */
+ content->facets = type->facets;
+ type->facets = NULL;
+ content->facetSet = type->facetSet;
+ type->facetSet = NULL;
+
+ type->contentTypeDef = content;
+ if (IS_NOT_TYPEFIXED(contentBase))
+ xmlSchemaTypeFixup(contentBase, pctxt);
+ /*
+ * Fixup the newly created type. We don't need to check
+ * for circularity here.
+ */
+ res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
+ HFAILURE HERROR
+ res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
+ HFAILURE HERROR
+
+ } else if ((IS_COMPLEX_TYPE(baseType)) &&
+ (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
+ (WXS_IS_RESTRICTION(type))) {
+ /*
+ * SPEC (2) If <restriction> + base is a mixed <complexType> with
+ * an emptiable particle, then a simple type definition which
+ * restricts the <restriction>'s <simpleType> child.
+ */
+ if ((type->contentTypeDef == NULL) ||
+ (type->contentTypeDef->baseType == NULL)) {
+ /*
+ * TODO: Check if this ever happens.
+ */
+ xmlSchemaPCustomErr(pctxt,
+ XML_SCHEMAP_INTERNAL,
+ NULL, type, NULL,
+ "Internal error: xmlSchemaTypeFixup, "
+ "complex type '%s': the <simpleContent><restriction> "
+ "is missing a <simpleType> child, but was not catched "
+ "by xmlSchemaCheckSRCCT()", type->name);
+ goto exit_failure;
+ }
+ } else if ((IS_COMPLEX_TYPE(baseType)) && WXS_IS_EXTENSION(type)) {
+ /*
+ * SPEC (3) If <extension> + base is <complexType> with
+ * <simpleType> content, "...then the {content type} of that
+ * complex type definition"
+ */
+ if (baseType->contentTypeDef == NULL) {
+ /*
+ * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
+ * should have catched this already.
+ */
+ xmlSchemaPCustomErr(pctxt,
+ XML_SCHEMAP_INTERNAL,
+ NULL, type, NULL,
+ "Internal error: xmlSchemaTypeFixup, "
+ "complex type '%s': the <extension>ed base type is "
+ "a complex type with no simple content type",
+ type->name);
+ goto exit_failure;
+ }
+ type->contentTypeDef = baseType->contentTypeDef;
+ } else if ((IS_SIMPLE_TYPE(baseType)) && WXS_IS_EXTENSION(type)) {
+ /*
+ * SPEC (4) <extension> + base is <simpleType>
+ * "... then that simple type definition"
+ */
+ type->contentTypeDef = baseType;
+ } else {
+ /*
+ * TODO: Check if this ever happens.
+ */
+ xmlSchemaPCustomErr(pctxt,
+ XML_SCHEMAP_INTERNAL,
+ NULL, type, NULL,
+ "Internal error: xmlSchemaTypeFixup, "
+ "complex type '%s' with <simpleContent>: unhandled "
+ "derivation case", type->name);
+ goto exit_failure;
+ }
+ } else {
+ int dummySequence = 0;
+ xmlSchemaParticlePtr particle =
+ (xmlSchemaParticlePtr) type->subtypes;
+ /*
+ * Corresponds to <complexType><complexContent>...
+ *
+ * NOTE that the effective mixed was already set during parsing of
+ * <complexType> and <complexContent>; its flag value is
+ * XML_SCHEMAS_TYPE_MIXED.
+ *
+ * Compute the "effective content":
+ * (2.1.1) + (2.1.2) + (2.1.3)
+ */
+ if ((particle == NULL) ||
+ ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
+ ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
+ (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
+ ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
+ (particle->minOccurs == 0))) &&
+ ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
+ if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
+ /*
+ * SPEC (2.1.4) "If the ·effective mixed· is true, then
+ * a particle whose properties are as follows:..."
+ *
+ * Empty sequence model group with
+ * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
+ * NOTE that we sill assign it the <complexType> node to
+ * somehow anchor it in the doc.
+ */
+ if ((particle == NULL) ||
+ (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
+ /*
+ * Create the particle.
+ */
+ particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
+ type->node, 1, 1);
+ if (particle == NULL)
+ goto exit_failure;
+ /*
+ * Create the model group.
+ */
+ particle->children = (xmlSchemaTreeItemPtr)
+ xmlSchemaAddModelGroup(pctxt, pctxt->schema,
+ XML_SCHEMA_TYPE_SEQUENCE, type->node);
+ if (particle->children == NULL)
+ goto exit_failure;
+
+ type->subtypes = (xmlSchemaTypePtr) particle;
+ }
+ dummySequence = 1;
+ type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
+ } else {
+ /*
+ * SPEC (2.1.5) "otherwise empty"
+ */
+ type->contentType = XML_SCHEMA_CONTENT_EMPTY;
+ }
+ } else {
+ /*
+ * SPEC (2.2) "otherwise the particle corresponding to the
+ * <all>, <choice>, <group> or <sequence> among the
+ * [children]."
+ */
+ type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
+ }
+ /*
+ * Compute the "content type".
+ */
+ if (WXS_IS_RESTRICTION(type)) {
+ /*
+ * SPEC (3.1) "If <restriction>..."
+ * (3.1.1) + (3.1.2) */
+ if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
+ if (type->flags & XML_SCHEMAS_TYPE_MIXED)
+ type->contentType = XML_SCHEMA_CONTENT_MIXED;
+ }
+ } else {
+ /*
+ * SPEC (3.2) "If <extension>..."
+ */
+ if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
+ /*
+ * SPEC (3.2.1)
+ */
+ type->contentType = baseType->contentType;
+ type->subtypes = baseType->subtypes;
+ /*
+ * NOTE that the effective mixed is ignored here.
+ */
+ } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
+ /*
+ * SPEC (3.2.2)
+ */
+ if (type->flags & XML_SCHEMAS_TYPE_MIXED)
+ type->contentType = XML_SCHEMA_CONTENT_MIXED;
+ } else {
+ /*
+ * SPEC (3.2.3)
+ */
+ if (type->flags & XML_SCHEMAS_TYPE_MIXED)
+ type->contentType = XML_SCHEMA_CONTENT_MIXED;
+ /*
+ * "A model group whose {compositor} is sequence and whose
+ * {particles} are..."
+ */
+ if (! dummySequence) {
+ xmlSchemaTreeItemPtr effectiveContent =
+ (xmlSchemaTreeItemPtr) type->subtypes;
+ /*
+ * Create the particle.
+ */
+ particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
+ type->node, 1, 1);
+ if (particle == NULL)
+ goto exit_failure;
+ /*
+ * Create the "sequence" model group.
+ */
+ particle->children = (xmlSchemaTreeItemPtr)
+ xmlSchemaAddModelGroup(pctxt, pctxt->schema,
+ XML_SCHEMA_TYPE_SEQUENCE, type->node);
+ if (particle->children == NULL)
+ goto exit_failure;
+ type->subtypes = (xmlSchemaTypePtr) particle;
+ /*
+ * SPEC "the particle of the {content type} of
+ * the ... base ..."
+ * Create a duplicate of the base type's particle
+ * and assign its "term" to it.
+ */
+ particle->children->children =
+ (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
+ pctxt->schema, type->node,
+ ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
+ ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
+ if (particle->children->children == NULL)
+ goto exit_failure;
+ particle = (xmlSchemaParticlePtr)
+ particle->children->children;
+ particle->children =
+ ((xmlSchemaParticlePtr) baseType->subtypes)->children;
+ /*
+ * SPEC "followed by the ·effective content·."
+ */
+ particle->next = effectiveContent;
+ } else {
+ /*
+ * This is the case when there is already an empty
+ * <sequence> with minOccurs==maxOccurs==1.
+ * Just add the base types's content type.
+ * NOTE that, although we miss to add an intermediate
+ * <sequence>, this should produce no difference to
+ * neither the regex compilation of the content model,
+ * nor to the complex type contraints.
+ */
+ particle->children->children =
+ (xmlSchemaTreeItemPtr) baseType->subtypes;
+ }
+ }
+ }
+ }
+ /*
+ * Apply the complex type component constraints; this will not
+ * check attributes, since this is done in
+ * xmlSchemaBuildAttributeValidation().
+ */
+ res = xmlSchemaCheckCTComponent(pctxt, type);
+ HFAILURE HERROR
+ /*
+ * Inherit & check constraints for attributes.
+ */
+ res = xmlSchemaBuildAttributeValidation(pctxt, type);
+ HFAILURE HERROR
+
+#ifdef DEBUG_TYPE
+ xmlSchemaDebugFixedType(pctxt, type);
+#endif
+ if (olderrs != pctxt->nberrors)
+ return(pctxt->err);
+ else
+ return(0);
+
+exit_error:
+ type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
+#ifdef DEBUG_TYPE
+ xmlSchemaDebugFixedType(pctxt, type);
+#endif
+ return(pctxt->err);
+
+exit_failure:
+ type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
+#ifdef DEBUG_TYPE
+ xmlSchemaDebugFixedType(pctxt, type);
+#endif
+ return(-1);
+}
+
+
+/**
+ * xmlSchemaTypeFixup:
+ * @typeDecl: the schema type definition
+ * @ctxt: the schema parser context
+ *
+ * Fixes the content model of the type.
+ * URGENT TODO: We need an int result!
+ */
+static int
+xmlSchemaTypeFixup(xmlSchemaTypePtr type,
+ xmlSchemaParserCtxtPtr pctxt)
+{
+ if (type == NULL)
+ return(0);
+ if (! IS_NOT_TYPEFIXED(type))
+ return(0);
+ if (type->type == XML_SCHEMA_TYPE_COMPLEX)
+ return(xmlSchemaFixupComplexType(pctxt, type));
+ else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
+ return(xmlSchemaFixupSimpleTypeStageTwo(pctxt, type));
+ return(0);
}
/**
@@ -17031,13 +17524,13 @@
* of the facet.
*/
ret = xmlSchemaVCheckCVCSimpleType(
- (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
+ ACTXT_CAST pctxt, facet->node, base,
facet->value, &(facet->val), 1, 1, 0);
if (ret != 0) {
if (ret < 0) {
/* No error message for RelaxNG. */
if (ctxtGiven) {
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
+ xmlSchemaCustomErr(ACTXT_CAST pctxt,
XML_SCHEMAP_INTERNAL, facet->node, NULL,
"Internal error: xmlSchemaCheckFacet, "
"failed to validate the value '%s' of the "
@@ -17051,7 +17544,7 @@
if (ctxtGiven) {
xmlChar *str = NULL;
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
+ xmlSchemaCustomErr(ACTXT_CAST pctxt,
ret, facet->node, (xmlSchemaTypePtr) facet,
"The value '%s' of the facet does not validate "
"against the base type '%s'",
@@ -17076,7 +17569,7 @@
ret = XML_SCHEMAP_REGEXP_INVALID;
/* No error message for RelaxNG. */
if (ctxtGiven) {
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
+ xmlSchemaCustomErr(ACTXT_CAST pctxt,
ret, facet->node, typeDecl,
"The value '%s' of the facet 'pattern' is not a "
"valid regular expression",
@@ -17105,7 +17598,7 @@
/* No error message for RelaxNG. */
if (ctxtGiven) {
/* error code */
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
+ xmlSchemaCustomErr(ACTXT_CAST pctxt,
ret, facet->node, typeDecl,
"The value '%s' of the facet '%s' is not a valid "
"'nonNegativeInteger'",
@@ -17127,7 +17620,7 @@
/* No error message for RelaxNG. */
if (ctxtGiven) {
/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
+ xmlSchemaCustomErr(ACTXT_CAST pctxt,
ret, facet->node, typeDecl,
"The value '%s' of the facet 'whitespace' is not "
"valid", facet->value, NULL);
@@ -17154,10 +17647,11 @@
*
* Checks the default values types, especially for facets
*/
-static void
+static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
- xmlSchemaParserCtxtPtr ctxt)
+ xmlSchemaParserCtxtPtr pctxt)
{
+ int res, olderrs = pctxt->nberrors;
const xmlChar *name = typeDecl->name;
/*
* NOTE: It is intended to use the facets list, instead
@@ -17170,19 +17664,23 @@
* Temporarily assign the "schema" to the validation context
* of the parser context. This is needed for NOTATION validation.
*/
- if (ctxt->vctxt == NULL) {
- if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
- return;
+ if (pctxt->vctxt == NULL) {
+ if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
+ return(-1);
}
- ctxt->vctxt->schema = ctxt->schema;
-
+ pctxt->vctxt->schema = pctxt->schema;
while (facet != NULL) {
- xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
+ res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
+ HFAILURE
facet = facet->next;
}
-
- ctxt->vctxt->schema = NULL;
+ pctxt->vctxt->schema = NULL;
}
+ if (olderrs != pctxt->nberrors)
+ return(pctxt->err);
+ return(0);
+exit_failure:
+ return(-1);
}
/**
@@ -17253,8 +17751,7 @@
*/
static void
xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
- xmlSchemaParserCtxtPtr ctxt,
- const xmlChar * name ATTRIBUTE_UNUSED)
+ xmlSchemaParserCtxtPtr ctxt)
{
/*
* Schema Component Constraint: Model Group Correct
@@ -17296,7 +17793,7 @@
}
/**
- * xmlSchemaGroupDefTermFixup:
+ * xmlSchemaGroupDefReferenceTermFixup:
* @item: the particle with a model group definition as term
* @ctxt: the parser context
* @name: the name
@@ -17305,11 +17802,11 @@
*
* Assigns the model group of model group definitions to the "term"
* of the referencing particle.
- * In xmlSchemaMiscRefFixup the model group definitions was assigned
+ * In xmlSchemaResolveParticleReferences the model group definitions was assigned
* to the "term", since needed for the circularity check.
*/
static void
-xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
+xmlSchemaGroupDefReferenceTermFixup(xmlSchemaParticlePtr item,
xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
const xmlChar * name ATTRIBUTE_UNUSED)
{
@@ -17402,9 +17899,8 @@
* Checks for circular references of attribute groups.
*/
static void
-xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
- xmlSchemaParserCtxtPtr ctxt,
- const xmlChar * name ATTRIBUTE_UNUSED)
+xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
+ xmlSchemaParserCtxtPtr ctxt)
{
/*
* Schema Representation Constraint:
@@ -17451,7 +17947,7 @@
}
/**
- * xmlSchemaAttrGrpFixup:
+ * xmlSchemaResolveAttrGroupReferences:
* @attrgrpDecl: the schema attribute definition
* @ctxt: the schema parser context
* @name: the attribute name
@@ -17459,7 +17955,7 @@
* Fixes finish doing the computations on the attributes definitions
*/
static void
-xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
+xmlSchemaResolveAttrGroupReferences(xmlSchemaAttributeGroupPtr attrgrp,
xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
{
if (name == NULL)
@@ -17481,9 +17977,11 @@
}
attrgrp->refItem = ref;
/*
- * Check for self reference!
- */
- xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
+ * URGENT TODO: Do we need to resolve refs of the
+ * referenced attr. group itself first? I don't think so.
+ * If we need this, then check for circularity first!
+ * REMOVED: xmlSchemaResolveAttrGroupReferences(ref, ctxt, NULL);
+ */
attrgrp->attributes = ref->attributes;
attrgrp->attributeWildcard = ref->attributeWildcard;
}
@@ -17504,8 +18002,7 @@
*/
static void
xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
- xmlSchemaParserCtxtPtr pctxt,
- const xmlChar * name ATTRIBUTE_UNUSED)
+ xmlSchemaParserCtxtPtr pctxt)
{
/*
@@ -17521,7 +18018,7 @@
"type is missing");
return;
}
- ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
+ ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
item->node, item->subtypes, item->defValue, &(item->defVal),
1, 1, 0);
if (ret != 0) {
@@ -17531,7 +18028,7 @@
return;
}
ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
+ xmlSchemaCustomErr(ACTXT_CAST pctxt,
ret, item->node, (xmlSchemaTypePtr) item,
"The value of the value constraint is not valid", NULL, NULL);
return;
@@ -17587,7 +18084,7 @@
if (SUBST_GROUP_AFF(elemDecl) != NULL) {
xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
- xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
+ xmlSchemaCheckElementDeclComponent(head, pctxt);
/*
* SPEC (3) "If there is a non-·absent· {substitution group
* affiliation}, then {scope} must be global."
@@ -17807,13 +18304,11 @@
* The set of all {derivation method}s involved in the derivation
*/
while ((type != NULL) && (type != headType)) {
- if ((type->flags &
- XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
+ if ((WXS_IS_EXTENSION(type)) &&
((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
- if ((type->flags &
- XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
+ if (WXS_IS_RESTRICTION(type) &&
((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
@@ -17867,8 +18362,7 @@
*/
static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
- xmlSchemaParserCtxtPtr ctxt,
- const xmlChar * name ATTRIBUTE_UNUSED)
+ xmlSchemaParserCtxtPtr ctxt)
{
if (elemDecl == NULL)
return;
@@ -17880,7 +18374,7 @@
}
/**
- * xmlSchemaMiscRefFixup:
+ * xmlSchemaResolveParticleReferences:
* @item: an schema component
* @ctxt: a schema parser context
* @name: the internal name of the component
@@ -17888,38 +18382,38 @@
* Resolves references of misc. schema components.
*/
static void
-xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
+xmlSchemaResolveParticleReferences(xmlSchemaTreeItemPtr item,
xmlSchemaParserCtxtPtr ctxt,
const xmlChar * name ATTRIBUTE_UNUSED)
{
- if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
- if ((item->children != NULL) &&
- (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
- xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
- xmlSchemaTreeItemPtr refItem;
- /*
- * Resolve the reference.
- */
- item->children = NULL;
- refItem = xmlSchemaGetNamedComponent(ctxt->schema,
- ref->itemType, ref->name, ref->targetNamespace);
- if (refItem == NULL) {
- xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
- NULL, GET_NODE(item), "ref", ref->name,
- ref->targetNamespace, ref->itemType, NULL);
- } else {
- if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
- /*
- * NOTE that we will assign the model group definition
- * itself to the "term" of the particle. This will ease
- * the check for circular model group definitions. After
- * that the "term" will be assigned the model group of the
- * model group definition.
- */
- item->children = refItem;
- } else
- item->children = refItem;
- }
+ if (item->type != XML_SCHEMA_TYPE_PARTICLE)
+ return;
+ if ((item->children != NULL) &&
+ (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
+ xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
+ xmlSchemaBasicItemPtr refItem;
+ /*
+ * Resolve the reference.
+ */
+ item->children = NULL;
+ refItem = xmlSchemaGetNamedComponent(ctxt->schema,
+ ref->itemType, ref->name, ref->targetNamespace);
+ if (refItem == NULL) {
+ xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
+ NULL, GET_NODE(item), "ref", ref->name,
+ ref->targetNamespace, ref->itemType, NULL);
+ } else {
+ if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
+ /*
+ * NOTE that we will assign the model group definition
+ * itself to the "term" of the particle. This will ease
+ * the check for circular model group definitions. After
+ * that the "term" will be assigned the model group of the
+ * model group definition.
+ */
+ item->children = (xmlSchemaTreeItemPtr) refItem;
+ } else
+ item->children = (xmlSchemaTreeItemPtr) refItem;
}
}
}
@@ -17984,7 +18478,7 @@
}
/**
- * xmlSchemaAttrFixup:
+ * xmlSchemaResolveAttrReferences:
* @item: an schema attribute declaration/use.
* @ctxt: a schema parser context
* @name: the name of the attribute
@@ -17992,7 +18486,7 @@
* Fixes finish doing the computations on attribute declarations/uses.
*/
static void
-xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
+xmlSchemaResolveAttrReferences(xmlSchemaAttributePtr item,
xmlSchemaParserCtxtPtr ctxt,
const xmlChar * name ATTRIBUTE_UNUSED)
{
@@ -18047,7 +18541,7 @@
return;
}
item->refDecl = decl;
- xmlSchemaAttrFixup(decl, ctxt, NULL);
+ xmlSchemaResolveAttrReferences(decl, ctxt, NULL);
item->subtypes = decl->subtypes;
/*
* Attribute Use Correct
@@ -18083,12 +18577,13 @@
*/
}
} else {
+ /* The type of this attribute is the xs:anySimpleType. */
item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
}
}
/**
- * xmlSchemaResolveIDCKeyRef:
+ * xmlSchemaResolveIDCKeyReferences:
* @idc: the identity-constraint definition
* @ctxt: the schema parser context
* @name: the attribute name
@@ -18096,27 +18591,27 @@
* Resolve keyRef references to key/unique IDCs.
*/
static void
-xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
+xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
xmlSchemaParserCtxtPtr pctxt,
const xmlChar * name ATTRIBUTE_UNUSED)
{
if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
return;
if (idc->ref->name != NULL) {
- idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
- pctxt->schema->idcDef,
- idc->ref->name,
- idc->ref->targetNamespace);
+ idc->ref->item = (xmlSchemaBasicItemPtr)
+ xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
+ idc->ref->targetNamespace);
if (idc->ref->item == NULL) {
/*
- * TODO: It is actually not an error to fail to resolve.
+ * TODO: It is actually not an error to fail to resolve
+ * at this stage. BUT we need to be that strict!
*/
xmlSchemaPResCompAttrErr(pctxt,
XML_SCHEMAP_SRC_RESOLVE,
(xmlSchemaTypePtr) idc, idc->node,
"refer", idc->ref->name,
idc->ref->targetNamespace,
- XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
+ XML_SCHEMA_TYPE_IDC_KEY, NULL);
return;
} else {
if (idc->nbFields !=
@@ -18145,6 +18640,277 @@
}
}
+
+static int
+xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt)
+{
+ xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
+ xmlSchemaTreeItemPtr item, *items;
+ int nbItems, i;
+
+#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
+
+ if ((con->pending == NULL) ||
+ (con->pending->nbItems == 0))
+ return(0);
+
+ pctxt->ctxtType = NULL;
+ pctxt->parentItem = NULL;
+ items = (xmlSchemaTreeItemPtr *) con->pending->items;
+ nbItems = con->pending->nbItems;
+ /*
+ * Now that we have parsed *all* the schema document(s) and converted
+ * them to schema components, we can resolve references, apply component
+ * constraints, create the FSA from the content model, etc.
+ */
+ /*
+ * Resolve references of..
+ *
+ * 1. element declarations:
+ * - the type definition
+ * - the substitution group affiliation
+ * 2. simple/complex types:
+ * - the base type definition
+ * - the memberTypes of union types
+ * - the itemType of list types
+ * 3. attributes declarations and attribute uses:
+ * - the type definition
+ * - if an attribute use, then the attribute declaration
+ * 4. attribute group references:
+ * - the attribute group definition
+ * 5. particles:
+ * - the term of the particle (e.g. a model group)
+ * 6. IDC key-references:
+ * - the referenced IDC 'key' or 'unique' definition
+ */
+ for (i = 0; i < nbItems; i++) {
+ item = items[i];
+ switch (item->type) {
+ case XML_SCHEMA_TYPE_ELEMENT:
+ xmlSchemaResolveElementReferences(
+ (xmlSchemaElementPtr) item, pctxt);
+ FIXHFAILURE;
+ break;
+ case XML_SCHEMA_TYPE_COMPLEX:
+ case XML_SCHEMA_TYPE_SIMPLE:
+ xmlSchemaResolveTypeReferences(
+ (xmlSchemaTypePtr) item, pctxt, NULL);
+ FIXHFAILURE;
+ break;
+ case XML_SCHEMA_TYPE_ATTRIBUTE:
+ xmlSchemaResolveAttrReferences(
+ (xmlSchemaAttributePtr) item, pctxt, NULL);
+ FIXHFAILURE;
+ break;
+ case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
+ xmlSchemaResolveAttrGroupReferences(
+ (xmlSchemaAttributeGroupPtr) item, pctxt, NULL);
+ FIXHFAILURE;
+ break;
+ case XML_SCHEMA_TYPE_PARTICLE:
+ xmlSchemaResolveParticleReferences(
+ (xmlSchemaTreeItemPtr) item, pctxt, NULL);
+ FIXHFAILURE;
+ break;
+ case XML_SCHEMA_TYPE_IDC_KEY:
+ case XML_SCHEMA_TYPE_IDC_UNIQUE:
+ case XML_SCHEMA_TYPE_IDC_KEYREF:
+ xmlSchemaResolveIDCKeyReferences(
+ (xmlSchemaIDCPtr) item, pctxt, NULL);
+ FIXHFAILURE;
+ break;
+ default:
+ break;
+ }
+ }
+ if (pctxt->nberrors != 0)
+ goto exit_error;
+
+ /*
+ * Now that all references are resolved we
+ * can check for circularity of...
+ * 1. the base axis of type definitions
+ * 2. nested model group definitions
+ * 3. nested attribute group definitions
+ * TODO: check for circual substitution groups.
+ */
+ for (i = 0; i < nbItems; i++) {
+ item = items[i];
+ /*
+ * Let's better stop on the first error here.
+ */
+ switch (item->type) {
+ case XML_SCHEMA_TYPE_COMPLEX:
+ case XML_SCHEMA_TYPE_SIMPLE:
+ xmlSchemaCheckTypeDefCircular(
+ (xmlSchemaTypePtr) item, pctxt);
+ FIXHFAILURE;
+ if (pctxt->nberrors != 0)
+ goto exit_error;
+ break;
+ case XML_SCHEMA_TYPE_GROUP:
+ xmlSchemaCheckGroupDefCircular(
+ (xmlSchemaModelGroupDefPtr) item, pctxt);
+ FIXHFAILURE;
+ if (pctxt->nberrors != 0)
+ goto exit_error;
+ break;
+ case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
+ xmlSchemaCheckAttrGroupCircular(
+ (xmlSchemaAttributeGroupPtr) item, pctxt);
+ FIXHFAILURE;
+ if (pctxt->nberrors != 0)
+ goto exit_error;
+ break;
+ default:
+ break;
+ }
+ }
+ /*
+ * Model group definition references:
+ * Such a reference is reflected by a particle at the component
+ * level. Until now the 'term' of such particles pointed
+ * to the model group definition; this was done, in order to
+ * ease circularity checks. Now we need to set the 'term' of
+ * such particles to the model group of the model group definition.
+ */
+ for (i = 0; i < nbItems; i++) {
+ item = items[i];
+ if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
+ (item->children != NULL) &&
+ (item->children->type == XML_SCHEMA_TYPE_GROUP)) {
+ xmlSchemaGroupDefReferenceTermFixup(
+ (xmlSchemaParticlePtr) item, pctxt, NULL);
+ FIXHFAILURE;
+ }
+ }
+ if (pctxt->nberrors != 0)
+ goto exit_error;
+ /*
+ * Now that all references are resolved, no circularity occured
+ * and the 'term's of particles was fixed we can:
+ * 1. finish computation of properties of types
+ * 2. restrict type definitions and check those restrictions
+ * 3. extend type definitions and check those extensions
+ *
+ * This is the most complex part during schema construction.
+ * TODO: Maybe it would be better to stop at the first error here.
+ */
+ /*
+ * First compute the variety of simple types. This is needed as
+ * a seperate step, since otherwise we won't be able to detect
+ * circular union types in all cases.
+ */
+ for (i = 0; i < nbItems; i++) {
+ item = items[i];
+ switch (item->type) {
+ case XML_SCHEMA_TYPE_SIMPLE:
+ if (TYPE_IS_NOT_FIXEDUP_1((xmlSchemaTypePtr) item)) {
+ xmlSchemaFixupSimpleTypeStageOne(pctxt,
+ (xmlSchemaTypePtr) item);
+ FIXHFAILURE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ /*
+ * Detect circular union types. Note that this needs the variety to
+ * be already computed.
+ */
+ for (i = 0; i < nbItems; i++) {
+ item = items[i];
+ switch (item->type) {
+ case XML_SCHEMA_TYPE_SIMPLE:
+ if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
+ xmlSchemaCheckUnionTypeDefCircular(pctxt,
+ (xmlSchemaTypePtr) item);
+ FIXHFAILURE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (pctxt->nberrors != 0)
+ goto exit_error;
+ /* Now do the complete type fixup. */
+ for (i = 0; i < nbItems; i++) {
+ item = items[i];
+ switch (item->type) {
+ case XML_SCHEMA_TYPE_SIMPLE:
+ case XML_SCHEMA_TYPE_COMPLEX:
+ xmlSchemaTypeFixup((xmlSchemaTypePtr) item, pctxt);
+ FIXHFAILURE;
+ break;
+ default:
+ break;
+ }
+ }
+ if (pctxt->nberrors != 0)
+ goto exit_error;
+
+ /*
+ * Now that we are sure the type definitions are finally constructed,
+ * we can:
+ * 1. check value contraint values of attribute declarations
+ * 2. apply various constraints to element declarations
+ */
+ for (i = 0; i < nbItems; i++) {
+ item = items[i];
+ switch (item->type) {
+ case XML_SCHEMA_TYPE_ATTRIBUTE:
+ if (((xmlSchemaAttributePtr)item)->defValue != NULL) {
+ xmlSchemaCheckAttrValConstr(
+ (xmlSchemaAttributePtr) item, pctxt);
+ FIXHFAILURE;
+ }
+ break;
+ case XML_SCHEMA_TYPE_ELEMENT:
+ if ((((xmlSchemaElementPtr) item)->flags &
+ XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) {
+ xmlSchemaCheckElementDeclComponent(
+ (xmlSchemaElementPtr) item, pctxt);
+ FIXHFAILURE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (pctxt->nberrors != 0)
+ goto exit_error;
+ /*
+ * Finally we can build the automaton from the content model of
+ * complex types.
+ */
+ for (i = 0; i < nbItems; i++) {
+ item = items[i];
+ switch (item->type) {
+ case XML_SCHEMA_TYPE_COMPLEX:
+ xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
+ FIXHFAILURE;
+ break;
+ default:
+ break;
+ }
+ }
+ if (pctxt->nberrors != 0)
+ goto exit_error;
+
+ /*
+ * URGENT TODO: cos-element-consistent, cos-all-limited
+ */
+ con->pending->nbItems = 0;
+ return(0);
+exit_error:
+ con->pending->nbItems = 0;
+ return(pctxt->err);
+exit_failure:
+ con->pending->nbItems = 0;
+ return(-1);
+}
/**
* xmlSchemaParse:
* @ctxt: a schema validation context
@@ -18159,10 +18925,9 @@
xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
{
- xmlSchemaPtr ret = NULL;
- xmlDocPtr doc;
- xmlNodePtr root;
- int preserve = 0;
+ xmlSchemaPtr schema = NULL;
+ xmlSchemaBucketPtr bucket = NULL;
+ int res;
/*
* This one is used if the schema to be parsed was specified via
@@ -18174,187 +18939,106 @@
if (ctxt == NULL)
return (NULL);
+ /* TODO: Init the context. Is this all we need?*/
ctxt->nberrors = 0;
+ ctxt->err = 0;
ctxt->counter = 0;
- ctxt->container = NULL;
+ /* Create the *main* schema. */
+ schema = xmlSchemaNewSchema(ctxt);
+ if (schema == NULL)
+ goto exit_failure;
/*
- * First step is to parse the input document into an DOM/Infoset
- */
- if (ctxt->URL != NULL) {
- doc = xmlReadFile((const char *) ctxt->URL, NULL,
- SCHEMAS_PARSE_OPTIONS);
- if (doc == NULL) {
- xmlSchemaPErr(ctxt, NULL,
- XML_SCHEMAP_FAILED_LOAD,
- "xmlSchemaParse: could not load '%s'.\n",
- ctxt->URL, NULL);
- return (NULL);
- }
- } else if (ctxt->buffer != NULL) {
- doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
- SCHEMAS_PARSE_OPTIONS);
- if (doc == NULL) {
- xmlSchemaPErr(ctxt, NULL,
- XML_SCHEMAP_FAILED_PARSE,
- "xmlSchemaParse: could not parse.\n",
- NULL, NULL);
- return (NULL);
- }
- doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
- ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
- } else if (ctxt->doc != NULL) {
- doc = ctxt->doc;
- preserve = 1;
- } else {
- xmlSchemaPErr(ctxt, NULL,
- XML_SCHEMAP_NOTHING_TO_PARSE,
- "xmlSchemaParse: could not parse.\n",
- NULL, NULL);
- return (NULL);
- }
-
- /*
- * Then extract the root and Schema parse it
- */
- root = xmlDocGetRootElement(doc);
- if (root == NULL) {
- xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
- XML_SCHEMAP_NOROOT,
- "The schema has no document element.\n", NULL, NULL);
- if (!preserve) {
- xmlFreeDoc(doc);
- }
- return (NULL);
- }
-
- /*
- * Remove all the blank text nodes
- */
- xmlSchemaCleanupDoc(ctxt, root);
-
- /*
- * Then do the parsing for good
- */
- ret = xmlSchemaParseSchema(ctxt, root);
- if (ret == NULL) {
- if (!preserve) {
- xmlFreeDoc(doc);
- }
- return (NULL);
- }
- ret->doc = doc;
- ret->preserve = preserve;
- ctxt->schema = ret;
- ctxt->ctxtType = NULL;
- ctxt->parentItem = NULL;
-
- /*
- * Resolve base types of simple/complex types.
+ * Create the schema constructor.
*/
- xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
+ if (ctxt->constructor == NULL) {
+ ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
+ if (ctxt->constructor == NULL)
+ return(NULL);
+ /* Take ownership of the constructor to be able to free it. */
+ ctxt->ownsConstructor = 1;
+ }
+ ctxt->constructor->schema = schema;
+ /*
+ * Locate and add the schema document.
+ */
+ res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
+ ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
+ NULL, NULL, &bucket);
+ if (res == -1)
+ goto exit_failure;
+ if (res != 0)
+ goto exit;
+ if (bucket == NULL) {
+ /* TODO: Error code, actually we failed to *locate* the schema. */
+ if (ctxt->URL)
+ xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
+ NULL, NULL,
+ "Failed to locate the main schema resource at '%s'",
+ ctxt->URL, NULL);
+ else
+ xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
+ NULL, NULL,
+ "Failed to locate the main schema resource",
+ NULL, NULL);
+ goto exit;
+ }
+ /* Set the main schema bucket. */
+ ctxt->constructor->bucket = bucket;
+ ctxt->targetNamespace = bucket->targetNamespace;
+ schema->targetNamespace = bucket->targetNamespace;
+
+ /* Then do the parsing for good. */
+ if (xmlSchemaParseNewDocWithContext(ctxt, schema, bucket) == -1)
+ goto exit_failure;
if (ctxt->nberrors != 0)
goto exit;
- if (ret->volatiles != NULL) {
- xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
- int i;
- xmlSchemaTreeItemPtr item;
+ schema->doc = bucket->doc;
+ schema->preserve = ctxt->preserve;
- for (i = 0; i < list->nbItems; i++) {
- item = (xmlSchemaTreeItemPtr) list->items[i];
- if (item->type == XML_SCHEMA_TYPE_PARTICLE)
- xmlSchemaMiscRefFixup(item, ctxt, NULL);
+ ctxt->schema = schema;
+
+ if (xmlSchemaFixupComponents(ctxt) == -1)
+ goto exit_failure;
+
+ /*
+ * TODO: This is not nice, since we cannot distinguish from the
+ * result if there was an internal error or not.
+ */
+exit:
+ if (ctxt->nberrors != 0) {
+ if (schema) {
+ xmlSchemaFree(schema);
+ schema = NULL;
+ }
+ if (ctxt->constructor) {
+ xmlSchemaConstructionCtxtFree(ctxt->constructor);
+ ctxt->constructor = NULL;
+ ctxt->ownsConstructor = 0;
}
}
- /*
- * Then fixup all attributes declarations
- */
- xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
- /*
- * Then fixup all attributes group declarations
- */
- xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
- ctxt);
- /*
- * Resolve identity-constraint keyRefs.
+ ctxt->schema = NULL;
+ return(schema);
+exit_failure:
+ /*
+ * Quite verbose, but should catch internal errors, which were
+ * not communitated.
*/
- xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
- /*
- * Check type defnitions for circular references.
- */
- xmlHashScan(ret->typeDecl, (xmlHashScanner)
- xmlSchemaCheckTypeDefCircular, ctxt);
- /*
- * Check model groups defnitions for circular references.
- */
- xmlHashScan(ret->groupDecl, (xmlHashScanner)
- xmlSchemaCheckGroupDefCircular, ctxt);
- /*
- * Set the "term" of particles pointing to model group definitions
- * to the contained model group.
- */
- if (ret->volatiles != NULL) {
- xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
- int i;
- xmlSchemaParticlePtr item;
-
- for (i = 0; i < list->nbItems; i++) {
- item = (xmlSchemaParticlePtr) list->items[i];
- if (item->type == XML_SCHEMA_TYPE_PARTICLE)
- xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
- }
+ if (schema) {
+ xmlSchemaFree(schema);
+ schema = NULL;
}
- /*
- * Check attribute groups for circular references.
- */
- xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
- xmlSchemaCheckAttributeGroupCircular, ctxt);
- /*
- * Then fix references of element declaration; apply constraints.
- */
- xmlHashScanFull(ret->elemDecl,
- (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
- /*
- * We will stop here if the schema was not valid to avoid internal errors
- * on missing sub-components. This is not conforming to the spec, since it
- * allows missing components, but it might make further processing crash.
- * So see it as a very strict handling, which might be made more lax in the
- * future.
- */
- if (ctxt->nberrors != 0)
- goto exit;
- /*
- * Then fixup all types properties
- */
- xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
- /*
- * Validate the value constraint of attribute declarations/uses.
- */
- xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
- /*
- * Validate the value constraint of element declarations.
- */
- xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
-
- if (ctxt->nberrors != 0)
- goto exit;
-
- /*
- * TODO: cos-element-consistent, cos-all-limited
- *
- * Then build the content model for all complex types
- */
- xmlHashScan(ret->typeDecl,
- (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
-
-exit:
- if (ctxt->nberrors != 0) {
- xmlSchemaFree(ret);
- ret = NULL;
+ if (ctxt->constructor) {
+ xmlSchemaConstructionCtxtFree(ctxt->constructor);
+ ctxt->constructor = NULL;
+ ctxt->ownsConstructor = 0;
}
- return (ret);
+ PERROR_INT2("xmlSchemaParse",
+ "An internal error occured");
+ ctxt->schema = NULL;
+ return(NULL);
}
/**
@@ -18504,154 +19188,6 @@
* *
************************************************************************/
-static void
-xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
-{
- int i, nbItems;
- xmlSchemaTypePtr item, *items;
-
-
- /*
- * During the Assemble of the schema ctxt->curItems has
- * been filled with the relevant new items. Fix those up.
- */
- nbItems = ctxt->assemble->nbItems;
- items = (xmlSchemaTypePtr *) ctxt->assemble->items;
-
- for (i = 0; i < nbItems; i++) {
- item = items[i];
- switch (item->type) {
- case XML_SCHEMA_TYPE_COMPLEX:
- case XML_SCHEMA_TYPE_SIMPLE:
- xmlSchemaResolveTypeDefs(item, ctxt, NULL);
- break;
- case XML_SCHEMA_TYPE_ATTRIBUTE:
- xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
- break;
- case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
- xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
- ctxt, NULL);
- break;
- case XML_SCHEMA_TYPE_PARTICLE:
- xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
- break;
- case XML_SCHEMA_TYPE_IDC_KEY:
- case XML_SCHEMA_TYPE_IDC_UNIQUE:
- case XML_SCHEMA_TYPE_IDC_KEYREF:
- xmlSchemaResolveIDCKeyRef((xmlSchemaIDCPtr) item, ctxt, NULL);
- break;
- default:
- break;
- }
- }
- if (ctxt->nberrors != 0)
- return;
- /*
- * Circularity checks.
- */
- for (i = 0; i < nbItems; i++) {
- item = items[i];
- switch (item->type) {
- case XML_SCHEMA_TYPE_COMPLEX:
- case XML_SCHEMA_TYPE_SIMPLE:
- xmlSchemaCheckTypeDefCircular(
- (xmlSchemaTypePtr) item, ctxt, NULL);
- break;
- case XML_SCHEMA_TYPE_GROUP:
- xmlSchemaCheckGroupDefCircular(
- (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
- break;
- case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
- xmlSchemaCheckAttributeGroupCircular(
- (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
- break;
- default:
- break;
- }
- }
- if (ctxt->nberrors != 0)
- return;
- /*
- * Set the "term" of particles pointing to model group definitions
- * to the contained model group.
- */
- for (i = 0; i < nbItems; i++) {
- item = items[i];
- if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
- (((xmlSchemaParticlePtr) item)->children != NULL) &&
- (((xmlSchemaParticlePtr) item)->children->type ==
- XML_SCHEMA_TYPE_GROUP)) {
- xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
- ctxt, NULL);
- }
- }
- if (ctxt->nberrors != 0)
- return;
- for (i = 0; i < nbItems; i++) {
- item = items[i];
- switch (item->type) {
- case XML_SCHEMA_TYPE_ELEMENT:
- xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
- NULL, NULL, NULL);
- break;
- default:
- break;
- }
- }
- if (ctxt->nberrors != 0)
- return;
-
- /*
- * Fixup for simple/complex types.
- */
- for (i = 0; i < nbItems; i++) {
- item = items[i];
- switch (item->type) {
- case XML_SCHEMA_TYPE_SIMPLE:
- case XML_SCHEMA_TYPE_COMPLEX:
- xmlSchemaTypeFixup(item, ctxt, NULL);
- break;
- default:
- break;
- }
- }
- if (ctxt->nberrors != 0)
- return;
- /*
- * Validate value contraint values.
- */
- for (i = 0; i < nbItems; i++) {
- item = items[i];
- switch (item->type) {
- case XML_SCHEMA_TYPE_ATTRIBUTE:
- xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
- ctxt, NULL);
- break;
- case XML_SCHEMA_TYPE_ELEMENT:
- xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
- ctxt, NULL);
- break;
- default:
- break;
- }
- }
- if (ctxt->nberrors != 0)
- return;
- /*
- * Build the content model for complex types.
- */
- for (i = 0; i < nbItems; i++) {
- item = items[i];
- switch (item->type) {
- case XML_SCHEMA_TYPE_COMPLEX:
- xmlSchemaBuildContentModel(item, ctxt, NULL);
- break;
- default:
- break;
- }
- }
-}
-
/**
* xmlSchemaAssembleByLocation:
* @pctxt: a schema parser context
@@ -18673,108 +19209,89 @@
const xmlChar *nsName,
const xmlChar *location)
{
- const xmlChar *targetNs, *oldtns;
- xmlDocPtr doc, olddoc;
- int oldflags, ret = 0, oldIsS4S;
- xmlNodePtr docElem;
+ int ret = 0;
xmlSchemaParserCtxtPtr pctxt;
+ xmlSchemaBucketPtr bucket = NULL;
- /*
- * This should be used:
- * 1. on <import>(s)
- * 2. if requested by the validated instance
- * 3. if requested via the API
- */
if ((vctxt == NULL) || (schema == NULL))
return (-1);
- /*
- * Create a temporary parser context.
- */
- if ((vctxt->pctxt == NULL) &&
- (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
- return (-1);
+
+ if (vctxt->pctxt == NULL) {
+ VERROR_INT("xmlSchemaAssembleByLocation",
+ "no parser context available");
+ return(-1);
+ }
pctxt = vctxt->pctxt;
- /*
- * Set the counter to produce unique names for anonymous items.
- */
- pctxt->counter = schema->counter;
+ if (pctxt->constructor == NULL) {
+ PERROR_INT("xmlSchemaAssembleByLocation",
+ "no constructor");
+ return(-1);
+ }
/*
* Acquire the schema document.
*/
- ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
- node, nsName, location, &doc, &targetNs, 0);
- if (ret != 0) {
- if (doc != NULL)
- xmlFreeDoc(doc);
- } else if (doc != NULL) {
- docElem = xmlDocGetRootElement(doc);
- /*
- * Create new assemble info.
- */
- if (pctxt->assemble == NULL) {
- pctxt->assemble = xmlSchemaNewAssemble();
- if (pctxt->assemble == NULL) {
- xmlSchemaVErrMemory(vctxt,
- "Memory error: xmlSchemaAssembleByLocation, "
- "allocating assemble info", NULL);
- xmlFreeDoc(doc);
- return (-1);
- }
- }
- /*
- * Save and reset the context & schema.
- */
- oldflags = schema->flags;
- oldtns = schema->targetNamespace;
- olddoc = schema->doc;
- oldIsS4S = vctxt->pctxt->isS4S;
-
- xmlSchemaClearSchemaDefaults(schema);
- schema->targetNamespace = targetNs;
- if ((targetNs != NULL) &&
- xmlStrEqual(targetNs, xmlSchemaNs)) {
- /*
- * We are parsing the schema for schema!
- */
- vctxt->pctxt->isS4S = 1;
- }
- /* schema->nbCurItems = 0; */
- pctxt->schema = schema;
- pctxt->ctxtType = NULL;
- pctxt->parentItem = NULL;
-
- xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
- if (pctxt->nberrors != 0) {
- vctxt->nberrors += pctxt->nberrors;
- goto finally;
- }
- xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
- if (pctxt->nberrors != 0) {
- vctxt->nberrors += pctxt->nberrors;
- goto finally;
- }
- xmlSchemaPostSchemaAssembleFixup(pctxt);
- if (pctxt->nberrors != 0)
- vctxt->nberrors += pctxt->nberrors;
-finally:
- /*
- * Set the counter of items.
- */
- schema->counter = pctxt->counter;
- /*
- * Free the list of assembled components.
- */
- pctxt->assemble->nbItems = 0;
- /*
- * Restore the context & schema.
- */
- vctxt->pctxt->isS4S = oldIsS4S;
- schema->flags = oldflags;
- schema->targetNamespace = oldtns;
- schema->doc = olddoc;
- ret = pctxt->err;
+ location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
+ location, node);
+ /*
+ * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
+ * the process will automatically change this to
+ * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
+ */
+ ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
+ location, NULL, NULL, 0, node, NULL, nsName,
+ &bucket);
+ if (ret != 0)
+ return(ret);
+ if (bucket == NULL) {
+ PERROR_INT("xmlSchemaAssembleByLocation",
+ "no schema bucket aquired");
+ return(-1);
+ }
+ /*
+ * The first located schema will be handled as if all other
+ * schemas imported by XSI were imported by this first schema.
+ */
+ if ((bucket != NULL) &&
+ (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
+ WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
+ /*
+ * TODO: Is this handled like an import? I.e. is it not an error
+ * if the schema cannot be located?
+ */
+ if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
+ return(0);
+ /*
+ * We will reuse the parser context for every schema imported
+ * directly via XSI. So reset the context.
+ */
+ pctxt->nberrors = 0;
+ pctxt->err = 0;
+ pctxt->doc = bucket->doc;
+
+ ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
+ if (ret == -1) {
+ pctxt->doc = NULL;
+ goto exit_failure;
}
- return (ret);
+ /* Paranoid error channelling. */
+ if ((ret == 0) && (pctxt->nberrors != 0))
+ ret = pctxt->err;
+ if (pctxt->nberrors == 0) {
+ /*
+ * Only bother to fixup pending components, if there was
+ * no error yet.
+ */
+ xmlSchemaFixupComponents(pctxt);
+ vctxt->nberrors += pctxt->nberrors;
+ } else {
+ /* Add to validation error sum. */
+ vctxt->nberrors += pctxt->nberrors;
+ }
+ pctxt->doc = NULL;
+ return(ret);
+exit_failure:
+ pctxt->doc = NULL;
+ return (-1);
}
static xmlSchemaAttrInfoPtr
@@ -18973,8 +19490,7 @@
xmlFree(localName);
return (1);
}
- if (xmlHashLookup2(schema->notaDecl, localName,
- nsName) != NULL) {
+ if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
if (valNeeded && (val != NULL)) {
(*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
BAD_CAST xmlStrdup(nsName));
@@ -18986,7 +19502,7 @@
xmlFree(prefix);
xmlFree(localName);
} else {
- if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
+ if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
if (valNeeded && (val != NULL)) {
(*val) = xmlSchemaNewNOTATIONValue(
BAD_CAST xmlStrdup(value), NULL);
@@ -19683,16 +20199,19 @@
}
if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
if (! IS_SIMPLE_TYPE(type)) {
+ xmlChar *str = NULL;
/*
* Not qualified if the field resolves to a node of non
* simple type.
*/
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaCustomErr(ACTXT_CAST vctxt,
XML_SCHEMAV_CVC_IDC, NULL,
(xmlSchemaTypePtr) sto->matcher->aidc->def,
- "The field '%s' does evaluate to a node of "
- "non-simple type", sto->sel->xpath, NULL);
-
+ "The field '%s' of %s does evaluate to a node of "
+ "non-simple type",
+ sto->sel->xpath,
+ xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
+ FREE_AND_NULL(str);
sto->nbHistory--;
goto deregister_check;
}
@@ -19771,6 +20290,7 @@
goto create_sequence;
} else {
if (keySeq[idx] != NULL) {
+ xmlChar *str = NULL;
/*
* cvc-identity-constraint:
* 3 For each node in the ·target node set· all
@@ -19781,12 +20301,14 @@
*
* The key was already set; report an error.
*/
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaCustomErr(ACTXT_CAST vctxt,
XML_SCHEMAV_CVC_IDC, NULL,
(xmlSchemaTypePtr) matcher->aidc->def,
- "The field '%s' evaluates to a node-set "
+ "The field '%s' of %s evaluates to a node-set "
"with more than one member",
- sto->sel->xpath, NULL);
+ sto->sel->xpath,
+ xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
+ FREE_AND_NULL(str);
sto->nbHistory--;
goto deregister_check;
} else {
@@ -19939,17 +20461,19 @@
i++;
} while (i < bind->nbNodes);
if (i != bind->nbNodes) {
- xmlChar *str = NULL;
+ xmlChar *str = NULL, *strB = NULL;
/*
* TODO: Try to report the key-sequence.
*/
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaCustomErr(ACTXT_CAST vctxt,
XML_SCHEMAV_CVC_IDC, NULL,
(xmlSchemaTypePtr) idc,
- "Duplicate key-sequence %s",
+ "Duplicate key-sequence %s in %s",
xmlSchemaFormatIDCKeySequence(vctxt, &str,
- (*keySeq), nbKeys), NULL);
- FREE_AND_NULL(str)
+ (*keySeq), nbKeys),
+ xmlSchemaGetIDCDesignation(&strB, idc));
+ FREE_AND_NULL(str);
+ FREE_AND_NULL(strB);
goto selector_leave;
}
}
@@ -20014,14 +20538,21 @@
goto selector_leave;
selector_key_error:
- /*
- * 4.2.1 (KEY) The ·target node set· and the
- * ·qualified node set· are equal, that is, every
- * member of the ·target node set· is also a member
- * of the ·qualified node set· and vice versa.
- */
- VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
- "All 'key' fields must evaluate to a node");
+ {
+ xmlChar *str = NULL;
+ /*
+ * 4.2.1 (KEY) The ·target node set· and the
+ * ·qualified node set· are equal, that is, every
+ * member of the ·target node set· is also a member
+ * of the ·qualified node set· and vice versa.
+ */
+ xmlSchemaCustomErr(ACTXT_CAST vctxt,
+ XML_SCHEMAV_CVC_IDC, NULL,
+ (xmlSchemaTypePtr) idc,
+ "Not all fields of %s evaluate to a node",
+ xmlSchemaGetIDCDesignation(&str, idc), NULL);
+ FREE_AND_NULL(str);
+ }
selector_leave:
/*
* Free the key-sequence if not added to the IDC table.
@@ -21046,7 +21577,7 @@
*/
if (nsName == NULL) {
ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
+ xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
"The QName value '%s' has no "
"corresponding namespace declaration in "
@@ -21430,7 +21961,7 @@
if (ret == -1)
return (-1);
if (ret > 0) {
- xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
return (1);
@@ -21459,7 +21990,7 @@
* A namespace must be found if the prefix is NOT NULL.
*/
if (*nsName == NULL) {
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaCustomErr(ACTXT_CAST vctxt,
XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
"The QName value '%s' has no "
@@ -21521,7 +22052,7 @@
if (*localType == NULL) {
xmlChar *str = NULL;
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaCustomErr(ACTXT_CAST vctxt,
XML_SCHEMAV_CVC_ELT_4_2, NULL,
xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
"The QName value '%s' of the xsi:type attribute does not "
@@ -21563,7 +22094,7 @@
elemDecl->subtypes, set) != 0) {
xmlChar *str = NULL;
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaCustomErr(ACTXT_CAST vctxt,
XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
"The type definition '%s', specified by xsi:type, is "
"blocked or not validly derived from the type definition "
@@ -21628,7 +22159,7 @@
* Validate the value.
*/
ret = xmlSchemaVCheckCVCSimpleType(
- (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
+ ACTXT_CAST vctxt, NULL,
xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
iattr->value, &(iattr->val), 1, 0, 0);
ACTIVATE_ELEM;
@@ -21732,7 +22263,7 @@
iattr = vctxt->attrInfos[i];
if (! iattr->metaType) {
ACTIVATE_ATTRIBUTE(iattr)
- xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
}
@@ -22204,12 +22735,12 @@
* Request a computed value.
*/
res = xmlSchemaVCheckCVCSimpleType(
- (xmlSchemaAbstractCtxtPtr) vctxt,
+ ACTXT_CAST vctxt,
attr->node, attr->typeDef, attr->value, &(attr->val),
1, 1, 0);
} else {
res = xmlSchemaVCheckCVCSimpleType(
- (xmlSchemaAbstractCtxtPtr) vctxt,
+ ACTXT_CAST vctxt,
attr->node, attr->typeDef, attr->value, NULL,
1, 0, 0);
}
@@ -22318,7 +22849,7 @@
case XML_SCHEMAS_ATTR_ERR_MISSING: {
xmlChar *str = NULL;
ACTIVATE_ELEM;
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaCustomErr(ACTXT_CAST vctxt,
XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
"The attribute '%s' is required but missing",
xmlSchemaFormatQName(&str,
@@ -22333,7 +22864,7 @@
"The type definition is absent");
break;
case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaCustomErr(ACTXT_CAST vctxt,
XML_SCHEMAV_CVC_AU, NULL, NULL,
"The value '%s' does not match the fixed "
"value constraint '%s'",
@@ -22352,10 +22883,10 @@
* for the following errors.
*/
if (type->attributeWildcard == NULL) {
- xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
} else {
- xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
}
break;
@@ -22398,9 +22929,8 @@
{
xmlSchemaElementPtr decl = NULL;
- decl = xmlHashLookup3(vctxt->schema->elemDecl,
- vctxt->inode->localName, vctxt->inode->nsName,
- NULL);
+ decl = xmlSchemaGetElem(vctxt->schema,
+ vctxt->inode->localName, vctxt->inode->nsName);
if (decl != NULL) {
vctxt->inode->decl = decl;
return (0);
@@ -22503,12 +23033,12 @@
*/
if (IS_SIMPLE_TYPE(inode->typeDef)) {
- ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
+ ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
NULL, inode->typeDef, value, val, 1, 1, 0);
} else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
- ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
+ ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
}
if (ret < 0) {
@@ -22567,11 +23097,11 @@
{
if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
return (xmlSchemaVCheckCVCSimpleType(
- (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
+ ACTXT_CAST vctxt, NULL,
type, value, &(inode->val), 1, 1, 0));
else
return (xmlSchemaVCheckCVCSimpleType(
- (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
+ ACTXT_CAST vctxt, NULL,
type, value, NULL, 1, 0, 0));
}
@@ -22654,7 +23184,7 @@
ret = 1;
inode->flags |=
XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
- xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
"Missing child element(s)",
nbval, nbneg, values);
@@ -22889,7 +23419,7 @@
* VAL TODO: Implement the canonical stuff.
*/
ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaCustomErr(ACTXT_CAST vctxt,
ret, NULL, NULL,
"The initial value '%s' does not match the fixed "
"value constraint '%s'",
@@ -22912,7 +23442,7 @@
if (! xmlStrEqual(inode->value,
inode->decl->value)) {
ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaCustomErr(ACTXT_CAST vctxt,
ret, NULL, NULL,
"The actual value '%s' does not match the fixed "
"value constraint '%s'",
@@ -23183,7 +23713,7 @@
if (ret < 0) {
xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
&values[0], &terminal);
- xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
+ xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
"This element is not expected",
nbval, nbneg, values);
@@ -23377,6 +23907,10 @@
goto internal_error;
}
if (vctxt->xsiAssemble) {
+ /*
+ * URGENT TODO: Better to fully stop validation
+ * if there was an error during dynamic schema construction.
+ */
if (xmlSchemaAssembleByXSI(vctxt) == -1)
goto internal_error;
}
@@ -23488,11 +24022,13 @@
* during validation against the declaration. This must be done
* _before_ attribute validation.
*/
- ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
- if (ret == -1) {
- VERROR_INT("xmlSchemaValidateElem",
- "calling xmlSchemaXPathEvaluate()");
- goto internal_error;
+ if (vctxt->xpathStates != NULL) {
+ ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
+ if (ret == -1) {
+ VERROR_INT("xmlSchemaValidateElem",
+ "calling xmlSchemaXPathEvaluate()");
+ goto internal_error;
+ }
}
/*
* Validate attributes.
@@ -24477,24 +25013,43 @@
vctxt->nberrors = 0;
vctxt->depth = -1;
vctxt->skipDepth = -1;
+ vctxt->xsiAssemble = 0;
/*
* Create a schema + parser if necessary.
*/
if (vctxt->schema == NULL) {
-
+ xmlSchemaParserCtxtPtr pctxt;
+
+ vctxt->xsiAssemble = 1;
+ /*
+ * If not schema was given then we will create a schema
+ * dynamically using XSI schema locations.
+ *
+ * Create the schema parser context.
+ */
if ((vctxt->pctxt == NULL) &&
(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
return (-1);
-
- vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
- if (vctxt->schema == NULL) {
- VERROR_INT("xmlSchemaVStartValidation",
- "creating a schema");
- return (-1);
- }
- vctxt->xsiAssemble = 1;
- } else
- vctxt->xsiAssemble = 0;
+ pctxt = vctxt->pctxt;
+ pctxt->xsiAssemble = 1;
+ /*
+ * Create the schema.
+ */
+ vctxt->schema = xmlSchemaNewSchema(pctxt);
+ if (vctxt->schema == NULL)
+ return (-1);
+ /*
+ * Create the schema construction context.
+ */
+ pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
+ if (pctxt->constructor == NULL)
+ return(-1);
+ pctxt->constructor->schema = vctxt->schema;
+ /*
+ * Take ownership of the constructor to be able to free it.
+ */
+ pctxt->ownsConstructor = 1;
+ }
/*
* Augment the IDC definitions.
*/
@@ -24544,7 +25099,7 @@
*/
ret = xmlParseDocument(vctxt->parserCtxt);
} else {
- VERROR_INT("xmlSchemaVStartValidation",
+ VERROR_INT("xmlSchemaVStart",
"no instance to validate");
ret = -1;
}
@@ -24599,7 +25154,7 @@
ctxt->doc = doc;
ctxt->node = xmlDocGetRootElement(doc);
if (ctxt->node == NULL) {
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
+ xmlSchemaCustomErr(ACTXT_CAST ctxt,
XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
(xmlNodePtr) doc, NULL,
"The document has no document element", NULL, NULL);