Changed output for keyref-match errors; the target-node will be now
* xmlschemas.c include/libxml/xmlerror.h:
Changed output for keyref-match errors; the target-node will
be now reported rather than the scope-node of the keyref
definition - allowing easier chasing of instance errors.
This was reported by Guy Fabrice to the mailing list.
Some initial parsing code for schema redefinitions.
* result/schemas/bug303566_1_1.err
result/schemas/bug312957_1_0.err: Adapted test results due
to the keyref changes.
diff --git a/xmlschemas.c b/xmlschemas.c
index 9876764..4cd009b 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -100,8 +100,6 @@
"attribute decl.";
static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
"attribute use";
-static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
- "complex type";
static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
"model group";
#if 0
@@ -199,13 +197,21 @@
typedef struct _xmlSchemaItemList xmlSchemaItemList;
typedef xmlSchemaItemList *xmlSchemaItemListPtr;
-
struct _xmlSchemaItemList {
void **items; /* used for dynamic addition of schemata */
int nbItems; /* used for dynamic addition of schemata */
int sizeItems; /* used for dynamic addition of schemata */
};
+/*
+typedef struct _xmlSchemaItemListChain xmlSchemaItemListChain;
+typedef xmlSchemaItemListChain xmlSchemaItemListChainPtr;
+struct _xmlSchemaItemListChain {
+ xmlSchemaItemListChainPtr next;
+ xmlSchemaItemListPtr list;
+}
+*/
+
typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
struct _xmlSchemaAbstractCtxt {
@@ -258,6 +264,7 @@
int nbLocalImports;
xmlHashTablePtr substGroups;
int isS4S;
+ int isRedefine;
};
#define XML_SCHEMAS_ATTR_UNKNOWN 1
@@ -289,6 +296,22 @@
xmlSchemaTypeType type;
};
+#define XML_SCHEMA_SCHEMA_REF_IMPORT 1
+#define XML_SCHEMA_SCHEMA_REF_INCLUDE 2
+#define XML_SCHEMA_SCHEMA_REF_REDEFINE 3
+/**
+ * xmlSchemaSchemaRef:
+ *
+ * Used to create a graph of schema relationships.
+ */
+typedef struct _xmlSchemaSchemaRef xmlSchemaSchemaRef;
+typedef xmlSchemaSchemaRef *xmlSchemaSchemaRefPtr;
+struct _xmlSchemaSchemaRef {
+ int type; /* E.g. XML_SCHEMA_SCHEMA_REF_IMPORT */
+ xmlSchemaSchemaRefPtr next;
+ xmlSchemaSchemaRefPtr children;
+};
+
/**
* xmlSchemaAnnotItem:
*
@@ -462,6 +485,8 @@
struct _xmlSchemaPSVIIDCNode {
xmlNodePtr node;
xmlSchemaPSVIIDCKeyPtr *keys;
+ int nodeLine;
+ int nodeQNameID;
};
/**
@@ -552,14 +577,17 @@
* Holds information of an element node.
*/
struct _xmlSchemaNodeInfo {
- xmlNodePtr node;
int nodeType;
+ xmlNodePtr node;
+ int nodeLine;
const xmlChar *localName;
const xmlChar *nsName;
const xmlChar *value;
xmlSchemaValPtr val; /* the pre-computed value if any */
xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
int flags; /* combination of node info flags */
+
+
int valNeeded;
int normVal;
@@ -588,8 +616,9 @@
typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
struct _xmlSchemaAttrInfo {
- xmlNodePtr node;
int nodeType;
+ xmlNodePtr node;
+ int nodeLine;
const xmlChar *localName;
const xmlChar *nsName;
const xmlChar *value;
@@ -674,6 +703,7 @@
int sizeAttrInfos;
int skipDepth;
+ xmlSchemaItemListPtr nodeQNames;
};
/*
@@ -722,6 +752,11 @@
static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaPtr schema,
xmlNodePtr node);
+#if 0
+static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
+ xmlSchemaPtr schema,
+ xmlNodePtr node);
+#endif
static void
xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
@@ -1570,9 +1605,10 @@
* Handle a validation error
*/
static void
-xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
- int error, xmlNodePtr node, const char *msg,
- const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
+xmlSchemaErr3Line(xmlSchemaAbstractCtxtPtr ctxt,
+ int error, xmlNodePtr node, int line, const char *msg,
+ const xmlChar *str1, const xmlChar *str2,
+ const xmlChar *str3)
{
xmlStructuredErrorFunc schannel = NULL;
xmlGenericErrorFunc channel = NULL;
@@ -1581,7 +1617,6 @@
if (ctxt != NULL) {
if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
- int line = 0;
const char *file = NULL;
vctxt->nberrors++;
@@ -1589,15 +1624,41 @@
channel = vctxt->error;
schannel = vctxt->serror;
data = vctxt->userData;
- if ((node == NULL) && (vctxt->depth >= 0) &&
- (vctxt->inode != NULL)) {
- node = vctxt->inode->node;
- }
- if ((node == NULL) && (vctxt->parserCtxt != NULL) &&
- (vctxt->parserCtxt->input != NULL)) {
- file = vctxt->parserCtxt->input->filename;
- line = vctxt->parserCtxt->input->line;
- }
+
+ /*
+ * Error node. If we specify a line number, then
+ * do not channel any node to the error function.
+ */
+ if (line == 0) {
+ if ((node == NULL) &&
+ (vctxt->depth >= 0) &&
+ (vctxt->inode != NULL)) {
+ node = vctxt->inode->node;
+ }
+ /*
+ * Get filename and line if no node-tree.
+ */
+ if ((node == NULL) &&
+ (vctxt->parserCtxt != NULL) &&
+ (vctxt->parserCtxt->input != NULL)) {
+ file = vctxt->parserCtxt->input->filename;
+ line = vctxt->parserCtxt->input->line;
+ }
+ } else {
+ /*
+ * Override the given node's (if any) position
+ * and channel only the given line number.
+ */
+ node = NULL;
+ /*
+ * Get filename.
+ */
+ if (vctxt->doc != NULL)
+ file = (const char *) vctxt->doc->URL;
+ else if ((vctxt->parserCtxt != NULL) &&
+ (vctxt->parserCtxt->input != NULL))
+ file = vctxt->parserCtxt->input->filename;
+ }
__xmlRaiseError(schannel, channel, data, ctxt,
node, XML_FROM_SCHEMASV,
error, XML_ERR_ERROR, file, line,
@@ -1623,6 +1684,26 @@
}
}
+/**
+ * xmlSchemaErr3:
+ * @ctxt: the validation context
+ * @node: the context node
+ * @error: the error code
+ * @msg: the error message
+ * @str1: extra data
+ * @str2: extra data
+ * @str3: extra data
+ *
+ * Handle a validation error
+ */
+static void
+xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
+ int error, xmlNodePtr node, const char *msg,
+ const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
+{
+ xmlSchemaErr3Line(actxt, error, node, 0, msg, str1, str2, str3);
+}
+
static void
xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
int error, xmlNodePtr node, const char *msg,
@@ -1772,6 +1853,30 @@
FREE_AND_NULL(msg)
}
+static void
+xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
+ xmlParserErrors error,
+ xmlSchemaPSVIIDCNodePtr idcNode,
+ xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
+ const char *message,
+ const xmlChar *str1,
+ const xmlChar *str2)
+{
+ xmlChar *msg = NULL, *qname = NULL;
+
+ msg = xmlStrdup(BAD_CAST "Element '%s': ");
+ msg = xmlStrcat(msg, (const xmlChar *) message);
+ msg = xmlStrcat(msg, BAD_CAST ".\n");
+ xmlSchemaErr3Line((xmlSchemaAbstractCtxtPtr) vctxt,
+ error, NULL, idcNode->nodeLine, (const char *) msg,
+ xmlSchemaFormatQName(&qname,
+ vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
+ vctxt->nodeQNames->items[idcNode->nodeQNameID]),
+ str1, str2);
+ FREE_AND_NULL(qname);
+ FREE_AND_NULL(msg);
+}
+
static int
xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
xmlNodePtr node)
@@ -2129,6 +2234,7 @@
#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
+#define PERROR_INT2(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) ctxt, func, msg);
#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
@@ -2768,6 +2874,43 @@
return (ret);
}
+static void
+xmlSchemaItemListClear(xmlSchemaItemListPtr list)
+{
+ if (list->items != NULL) {
+ xmlFree(list->items);
+ list->items = NULL;
+ }
+ list->nbItems = 0;
+ list->sizeItems = 0;
+}
+
+static int
+xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
+{
+ if (list->items == NULL) {
+ list->items = (void **) xmlMalloc(
+ 20 * sizeof(void *));
+ if (list->items == NULL) {
+ xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
+ return(-1);
+ }
+ list->sizeItems = 20;
+ } else if (list->sizeItems <= list->nbItems) {
+ list->sizeItems *= 2;
+ list->items = (void **) xmlRealloc(list->items,
+ list->sizeItems * sizeof(void *));
+ if (list->items == NULL) {
+ xmlSchemaPErrMemory(NULL, "growing item list", NULL);
+ list->sizeItems = 0;
+ return(-1);
+ }
+ }
+ /* ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item; */
+ list->items[list->nbItems++] = item;
+ return(0);
+}
+
/**
* xmlSchemaAddElementSubstitutionMember:
* @pctxt: a schema parser context
@@ -3104,8 +3247,6 @@
xmlSchemaAddVolatile(xmlSchemaPtr schema,
xmlSchemaBasicItemPtr item)
{
- xmlSchemaItemListPtr list;
-
if (schema->volatiles == NULL) {
schema->volatiles = (void *) xmlSchemaNewItemList();
if (schema->volatiles == NULL) {
@@ -3114,29 +3255,7 @@
return (-1);
}
}
- list = (xmlSchemaItemListPtr) schema->volatiles;
- if (list->items == NULL) {
- list->items = (void **) xmlMalloc(
- 20 * sizeof(xmlSchemaBasicItemPtr));
- if (list->items == NULL) {
- xmlSchemaPErrMemory(NULL,
- "allocating new volatile item buffer", NULL);
- return (-1);
- }
- list->sizeItems = 20;
- } else if (list->sizeItems <= list->nbItems) {
- list->sizeItems *= 2;
- list->items = (void **) xmlRealloc(list->items,
- list->sizeItems * sizeof(xmlSchemaTypePtr));
- if (list->items == NULL) {
- xmlSchemaPErrMemory(NULL,
- "growing volatile item buffer", NULL);
- list->sizeItems = 0;
- return (-1);
- }
- }
- ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
- return (0);
+ return(xmlSchemaItemListAdd((xmlSchemaItemListPtr) schema->volatiles, item));
}
/**
@@ -3950,35 +4069,19 @@
*/
static xmlSchemaElementPtr
xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
- const xmlChar * namespace)
+ const xmlChar * nsName)
{
xmlSchemaElementPtr ret;
if ((name == NULL) || (schema == NULL))
return (NULL);
- ret = xmlHashLookup2(schema->elemDecl, name, namespace);
+ ret = xmlHashLookup2(schema->elemDecl, name, nsName);
if ((ret != NULL) &&
(ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
return (ret);
} else
ret = NULL;
- /*
- * This one was removed, since top level element declarations have
- * the target namespace specified in targetNamespace of the <schema>
- * information element, even if elementFormDefault is "unqualified".
- */
-
- /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
- if (xmlStrEqual(namespace, schema->targetNamespace))
- ret = xmlHashLookup2(schema->elemDecl, name, NULL);
- else
- ret = xmlHashLookup2(schema->elemDecl, name, namespace);
- if ((ret != NULL) &&
- ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
- return (ret);
- }
- */
/*
* Removed since imported components will be hold by the main schema only.
@@ -4019,18 +4122,25 @@
*/
static xmlSchemaTypePtr
xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
- const xmlChar * namespace)
+ const xmlChar * nsName)
{
xmlSchemaTypePtr ret;
if (name == NULL)
return (NULL);
if (schema != NULL) {
- ret = xmlHashLookup2(schema->typeDecl, name, namespace);
- if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
+ ret = xmlHashLookup2(schema->typeDecl, name, nsName);
+ if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
+ if (ret->redef != NULL) {
+ /*
+ * Return the last redefinition.
+ */
+ return(ret->redef);
+ }
return (ret);
+ }
}
- ret = xmlSchemaGetPredefinedType(name, namespace);
+ ret = xmlSchemaGetPredefinedType(name, nsName);
if (ret != NULL)
return (ret);
/*
@@ -4050,14 +4160,14 @@
*/
#ifdef DEBUG
if (ret == NULL) {
- if (namespace == NULL)
+ if (nsName == NULL)
fprintf(stderr, "Unable to lookup type %s", name);
else
fprintf(stderr, "Unable to lookup type %s:%s", name,
- namespace);
+ nsName);
}
#endif
- return (ret);
+ return (NULL);
}
/**
@@ -4604,8 +4714,8 @@
*/
static xmlSchemaTypePtr
xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
- const xmlChar * name, const xmlChar * namespace,
- xmlNodePtr node)
+ const xmlChar * name, const xmlChar * nsName,
+ xmlNodePtr node, int topLevel)
{
xmlSchemaTypePtr ret = NULL;
int val;
@@ -4615,8 +4725,8 @@
#ifdef DEBUG
fprintf(stderr, "Adding type %s\n", name);
- if (namespace != NULL)
- fprintf(stderr, " target namespace %s\n", namespace);
+ if (nsName != NULL)
+ fprintf(stderr, " target namespace %s\n", nsName);
#endif
if (schema->typeDecl == NULL)
@@ -4632,25 +4742,37 @@
memset(ret, 0, sizeof(xmlSchemaType));
ret->name = xmlDictLookup(ctxt->dict, name, -1);
ret->redef = NULL;
- val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
+ val = xmlHashAddEntry2(schema->typeDecl, name, nsName, ret);
if (val != 0) {
- if (ctxt->includes == 0) {
- xmlSchemaPCustomErr(ctxt,
- XML_SCHEMAP_REDEFINED_TYPE,
- NULL, NULL, node,
- "A global type definition with the name '%s' does already exist", name);
+ if (! ctxt->isRedefine) {
+ xmlChar *str = NULL;
+ if (topLevel) {
+ xmlSchemaPCustomErr(ctxt,
+ XML_SCHEMAP_REDEFINED_TYPE,
+ NULL, NULL, node,
+ "A global type definition with the name '%s' does "
+ "already exist",
+ xmlSchemaFormatQName(&str, nsName, name));
+ } else {
+ xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
+ NULL, NULL, node, "Internal error: xmlSchemaAddType, "
+ "local type '%s' has a duplicate",
+ xmlSchemaFormatQName(&str, nsName, name));
+ }
xmlFree(ret);
+ FREE_AND_NULL(str);
return (NULL);
} else {
xmlSchemaTypePtr prev;
- prev = xmlHashLookup2(schema->typeDecl, name, namespace);
+ /*
+ * REDEFINE: Add a redefinition.
+ */
+ TODO
+ prev = xmlHashLookup2(schema->typeDecl, name, nsName);
if (prev == NULL) {
- xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
- XML_ERR_INTERNAL_ERROR,
- "Internal error: xmlSchemaAddType, on type "
- "'%s'.\n",
- name, NULL);
+ PERROR_INT2("xmlSchemaAddType", "hash list didn't return "
+ "a type component, but should");
xmlFree(ret);
return (NULL);
}
@@ -8104,6 +8226,7 @@
xmlNodePtr child = NULL;
const xmlChar *attrValue = NULL;
xmlAttrPtr attr;
+ int hasRestriction = 0;
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
return (NULL);
@@ -8127,6 +8250,18 @@
if (ctxt->isS4S) {
xmlSchemaTypePtr biType;
+ if (ctxt->isRedefine) {
+ /*
+ * REDEFINE: Disallow redefinition of built-in-types.
+ * TODO: It seems that the spec does not say anything
+ * about this case.
+ */
+ xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
+ NULL, NULL, node,
+ "Redefinition of built-in simple types is not "
+ "supported", NULL);
+ return(NULL);
+ }
biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
if (biType != NULL)
return (biType);
@@ -8141,7 +8276,8 @@
* Parse as local simple type definition.
*/
snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
- type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
+ type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL,
+ node, 0);
if (type == NULL)
return (NULL);
type->node = node;
@@ -8171,7 +8307,8 @@
*
* Note that attrValue is the value of the attribute "name" here.
*/
- type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
+ type = xmlSchemaAddType(ctxt, schema, attrValue,
+ schema->targetNamespace, node, 1);
if (type == NULL)
return (NULL);
type->node = node;
@@ -8242,9 +8379,10 @@
xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
NULL, type, node, child, NULL,
"(annotation?, (restriction | list | union))");
- } else if (IS_SCHEMA(child, "restriction")) {
+ } else if (IS_SCHEMA(child, "restriction")) {
xmlSchemaParseRestriction(ctxt, schema, child,
- XML_SCHEMA_TYPE_SIMPLE);
+ XML_SCHEMA_TYPE_SIMPLE);
+ hasRestriction = 1;
child = child->next;
} else if (IS_SCHEMA(child, "list")) {
xmlSchemaParseList(ctxt, schema, child);
@@ -8258,9 +8396,21 @@
NULL, type, node, child, NULL,
"(annotation?, (restriction | list | union))");
}
+ /*
+ * REDEFINE: SPEC src-redefine (5)
+ * "Within the [children], each <simpleType> must have a
+ * <restriction> among its [children] ... the ·actual value· of whose
+ * base [attribute] must be the same as the ·actual value· of its own
+ * name attribute plus target namespace;"
+ */
+ if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
+ xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
+ NULL, NULL, node, "This is a redefinition, thus the "
+ "<simpleType> must have a <restriction> child", NULL);
+ }
+
ctxt->parentItem = oldParentItem;
ctxt->ctxtType = oldCtxtType;
-
return (type);
}
@@ -8669,6 +8819,9 @@
ctxt->includes--;
} else if (IS_SCHEMA(child, "redefine")) {
TODO
+ /*
+ xmlSchemaParseRedefine(ctxt, schema, child);
+ */
}
child = child->next;
}
@@ -8745,6 +8898,28 @@
return (ret);
}
+#if 0
+static xmlSchemaSchemaRefPtr
+xmlSchemaNewSchemaRef(void)
+{
+ xmlSchemaSchemaRefPtr ret;
+
+ ret = (xmlSchemaSchemaRefPtr) xmlMalloc(sizeof(xmlSchemaSchemaRef));
+ if (ret == NULL) {
+ xmlSchemaPErrMemory(NULL, "allocating schema reference", NULL);
+ return(NULL);
+ }
+ memset(ret, 0, sizeof(xmlSchemaSchemaRef));
+ return(ret);
+}
+
+static void
+xmlSchemaFreeSchemaRef(xmlSchemaSchemaRefPtr ref)
+{
+ xmlFree(ref);
+}
+#endif
+
/**
* xmlSchemaNewParserCtxtUseDict:
* @URL: the location of the schema
@@ -9089,7 +9264,7 @@
* not valid and -1 in case of an internal error.
*/
static int
-xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
+xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
xmlNodePtr node)
{
xmlNodePtr child;
@@ -9100,7 +9275,7 @@
xmlDocPtr doc;
int ret = 0;
- if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+ if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
return (-1);
/*
@@ -9112,12 +9287,12 @@
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
- xmlSchemaPIllegalAttrErr(ctxt,
+ xmlSchemaPIllegalAttrErr(pctxt,
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
NULL, NULL, attr);
}
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
- xmlSchemaPIllegalAttrErr(ctxt,
+ xmlSchemaPIllegalAttrErr(pctxt,
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
NULL, NULL, attr);
}
@@ -9126,26 +9301,26 @@
/*
* Extract and validate attributes.
*/
- if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
+ if (xmlSchemaPValAttr(pctxt, NULL, NULL, node,
"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
&namespaceName) != 0) {
- xmlSchemaPSimpleTypeErr(ctxt,
- XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
+ xmlSchemaPSimpleTypeErr(pctxt,
+ XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
NULL, node,
xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
NULL, namespaceName, NULL, NULL, NULL);
- return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
+ return (pctxt->err);
}
- if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
+ if (xmlSchemaPValAttr(pctxt, NULL, NULL, node,
"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
&schemaLocation) != 0) {
- xmlSchemaPSimpleTypeErr(ctxt,
- XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
+ xmlSchemaPSimpleTypeErr(pctxt,
+ XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
NULL, node,
xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
NULL, namespaceName, NULL, NULL, NULL);
- return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
+ return (pctxt->err);
}
/*
* And now for the children...
@@ -9159,8 +9334,8 @@
child = child->next;
}
if (child != NULL) {
- xmlSchemaPContentErr(ctxt,
- XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
+ xmlSchemaPContentErr(pctxt,
+ XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
NULL, NULL, node, child, NULL,
"(annotation?)");
}
@@ -9174,13 +9349,13 @@
* targetNamespace [attribute].
*/
if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
- xmlSchemaPCustomErr(ctxt,
+ xmlSchemaPCustomErr(pctxt,
XML_SCHEMAP_SRC_IMPORT_1_1,
NULL, NULL, node,
"The value of the attribute 'namespace' must not match "
"the target namespace '%s' of the importing schema",
schema->targetNamespace);
- return (XML_SCHEMAP_SRC_IMPORT_1_1);
+ return (pctxt->err);
}
} else {
/*
@@ -9188,34 +9363,34 @@
* <schema> must have a targetNamespace [attribute].
*/
if (schema->targetNamespace == NULL) {
- xmlSchemaPCustomErr(ctxt,
+ xmlSchemaPCustomErr(pctxt,
XML_SCHEMAP_SRC_IMPORT_1_2,
NULL, NULL, node,
"The attribute 'namespace' must be existent if "
"the importing schema has no target namespace",
NULL);
- return (XML_SCHEMAP_SRC_IMPORT_1_2);
+ return (pctxt->err);
}
}
/*
* Add the namespace to the list of locally imported namespace.
*/
- if (ctxt->localImports == NULL) {
- ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
+ if (pctxt->localImports == NULL) {
+ pctxt->localImports = (const xmlChar **) xmlMalloc(10 *
sizeof(const xmlChar*));
- ctxt->sizeLocalImports = 10;
- ctxt->nbLocalImports = 0;
- } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
- ctxt->sizeLocalImports *= 2;
- ctxt->localImports = (const xmlChar **) xmlRealloc(
- (xmlChar **) ctxt->localImports,
- ctxt->sizeLocalImports * sizeof(const xmlChar*));
+ pctxt->sizeLocalImports = 10;
+ pctxt->nbLocalImports = 0;
+ } else if (pctxt->sizeLocalImports <= pctxt->nbLocalImports) {
+ pctxt->sizeLocalImports *= 2;
+ pctxt->localImports = (const xmlChar **) xmlRealloc(
+ (xmlChar **) pctxt->localImports,
+ pctxt->sizeLocalImports * sizeof(const xmlChar*));
}
- ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
+ pctxt->localImports[pctxt->nbLocalImports++] = namespaceName;
/*
* Locate and aquire the schema document.
*/
- ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
+ ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) pctxt,
schema, node, namespaceName,
schemaLocation, &doc, &targetNamespace, 0);
if (ret != 0) {
@@ -9223,7 +9398,7 @@
xmlFreeDoc(doc);
return (ret);
} else if (doc != NULL) {
- xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
+ xmlSchemaParseForImpInc(pctxt, schema, targetNamespace,
xmlDocGetRootElement(doc));
}
@@ -9231,120 +9406,28 @@
}
/**
- * xmlSchemaParseInclude:
- * @ctxt: a schema validation context
+ * xmlSchemaParseIncludedDoc:
+ * @pctxt: a schema validation context
* @schema: the schema being built
* @node: a subtree containing XML Schema informations
*
- * parse a XML schema Include definition
+ * Parse an included (and to-be-redefined) XML schema document.
*
- * Returns -1 in case of error, 0 if the declaration is improper and
- * 1 in case of success.
+ * Returns 0 on success, a positive error code on errors and
+ * -1 in case of an internal or API error.
*/
static int
-xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
- xmlNodePtr node)
+xmlSchemaParseIncludedDoc(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
+ xmlNodePtr node, const xmlChar *schemaLocation)
{
- xmlNodePtr child = NULL;
- const xmlChar *schemaLocation, *targetNamespace;
+ const xmlChar *targetNamespace;
xmlDocPtr doc = NULL;
xmlNodePtr root = NULL;
xmlSchemaIncludePtr include = NULL;
int wasConvertingNs = 0;
- xmlAttrPtr attr;
xmlParserCtxtPtr parserCtxt;
- if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
- return (-1);
-
- /*
- * Check for illegal attributes.
- */
- attr = node->properties;
- while (attr != NULL) {
- if (attr->ns == NULL) {
- if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
- (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
- xmlSchemaPIllegalAttrErr(ctxt,
- XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
- NULL, NULL, attr);
- }
- } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
- xmlSchemaPIllegalAttrErr(ctxt,
- XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
- NULL, NULL, attr);
- }
- attr = attr->next;
- }
- /*
- * Extract and validate attributes.
- */
- xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
- /*
- * Preliminary step, extract the URI-Reference for the include and
- * make an URI from the base.
- */
- attr = xmlSchemaGetPropNode(node, "schemaLocation");
- if (attr != NULL) {
- xmlChar *base = NULL;
- xmlChar *uri = NULL;
-
- if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
- xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
- goto exit_invalid;
- base = xmlNodeGetBase(node->doc, node);
- if (base == NULL) {
- uri = xmlBuildURI(schemaLocation, node->doc->URL);
- } else {
- uri = xmlBuildURI(schemaLocation, base);
- xmlFree(base);
- }
- if (uri == NULL) {
- xmlSchemaPErr(ctxt,
- node,
- XML_SCHEMAP_INTERNAL,
- "Internal error: xmlSchemaParseInclude, "
- "could not build an URI from the schemaLocation.\n",
- NULL, NULL);
- goto exit_failure;
- }
- schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
- xmlFree(uri);
- } else {
- xmlSchemaPMissingAttrErr(ctxt,
- XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
- NULL, node, "schemaLocation", NULL);
- goto exit_invalid;
- }
- /*
- * And now for the children...
- */
- child = node->children;
- while (IS_SCHEMA(child, "annotation")) {
- /*
- * the annotations here are simply discarded ...
- * TODO: really?
- */
- child = child->next;
- }
- if (child != NULL) {
- xmlSchemaPContentErr(ctxt,
- XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
- NULL, NULL, node, child, NULL,
- "(annotation?)");
- }
- /*
- * Report self-inclusion.
- */
- if (xmlStrEqual(schemaLocation, ctxt->URL)) {
- xmlSchemaPCustomErr(ctxt,
- XML_SCHEMAP_SRC_INCLUDE,
- NULL, NULL, node,
- "The schema document '%s' cannot include itself.",
- schemaLocation);
- return (XML_SCHEMAP_SRC_INCLUDE);
- }
/*
* Check if this one was already processed to avoid incorrect
* duplicate component errors and infinite circular inclusion.
@@ -9379,9 +9462,9 @@
goto exit_failure;
}
- if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
+ if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
xmlDictFree(parserCtxt->dict);
- parserCtxt->dict = ctxt->dict;
+ parserCtxt->dict = pctxt->dict;
xmlDictReference(parserCtxt->dict);
}
@@ -9395,11 +9478,11 @@
* case no corresponding inclusion is performed.
* So do we need a warning report here?
*/
- xmlSchemaPCustomErr(ctxt,
+ xmlSchemaPCustomErr(pctxt,
XML_SCHEMAP_FAILED_LOAD,
NULL, NULL, node,
"Failed to load the document '%s' for inclusion", schemaLocation);
- goto exit_invalid;
+ goto exit_error;
}
/*
@@ -9407,32 +9490,32 @@
*/
root = xmlDocGetRootElement(doc);
if (root == NULL) {
- xmlSchemaPCustomErr(ctxt,
+ xmlSchemaPCustomErr(pctxt,
XML_SCHEMAP_NOROOT,
NULL, NULL, node,
"The included document '%s' has no document "
"element", schemaLocation);
- goto exit_invalid;
+ goto exit_error;
}
/*
* Remove all the blank text nodes
*/
- xmlSchemaCleanupDoc(ctxt, root);
+ xmlSchemaCleanupDoc(pctxt, root);
/*
* Check the schemas top level element
*/
if (!IS_SCHEMA(root, "schema")) {
- xmlSchemaPCustomErr(ctxt,
+ xmlSchemaPCustomErr(pctxt,
XML_SCHEMAP_NOT_SCHEMA,
NULL, NULL, node,
"The document '%s' to be included is not a schema document",
schemaLocation);
- goto exit_invalid;
+ goto exit_error;
}
- targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
+ targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
/*
* 2.1 SII has a targetNamespace [attribute], and its ·actual
* value· is identical to the ·actual value· of the targetNamespace
@@ -9441,22 +9524,22 @@
check_targetNamespace:
if (targetNamespace != NULL) {
if (schema->targetNamespace == NULL) {
- xmlSchemaPCustomErr(ctxt,
+ xmlSchemaPCustomErr(pctxt,
XML_SCHEMAP_SRC_INCLUDE,
NULL, NULL, node,
"The target namespace of the included schema "
"'%s' has to be absent, since the including schema "
"has no target namespace",
schemaLocation);
- goto exit_invalid;
+ goto exit_error;
} else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
- xmlSchemaPCustomErrExt(ctxt,
+ xmlSchemaPCustomErrExt(pctxt,
XML_SCHEMAP_SRC_INCLUDE,
NULL, NULL, node,
"The target namespace '%s' of the included schema '%s' "
"differs from '%s' of the including schema",
targetNamespace, schemaLocation, schema->targetNamespace);
- goto exit_invalid;
+ goto exit_error;
}
} else if (schema->targetNamespace != NULL) {
if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
@@ -9477,13 +9560,14 @@
* the moment.
* TODO: Check when the namespace in wildcards for chameleons needs
* to be converted: before we built wildcard intersections or after.
+ * Answer: after!
*/
/*
* Register the include.
*/
include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
if (include == NULL) {
- xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
+ xmlSchemaPErrMemory(pctxt, "allocating include entry", NULL);
goto exit_failure;
}
memset(include, 0, sizeof(xmlSchemaInclude));
@@ -9515,7 +9599,7 @@
/*
* Compile the included schema.
*/
- xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
+ xmlSchemaParseForImpInc(pctxt, schema, schema->targetNamespace, root);
exit:
/*
@@ -9524,15 +9608,15 @@
if ((wasConvertingNs == 0) &&
(schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
- return (1);
+ return (0);
-exit_invalid:
+exit_error:
if (doc != NULL) {
if (include != NULL)
include->doc = NULL;
xmlFreeDoc(doc);
}
- return (ctxt->err);
+ return (pctxt->err);
exit_failure:
if (doc != NULL) {
@@ -9543,6 +9627,216 @@
return (-1);
}
+
+static int
+xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
+ xmlSchemaPtr schema,
+ xmlNodePtr node,
+ xmlChar **schemaLocation,
+ int isRedefine)
+{
+ xmlAttrPtr attr;
+
+ if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
+ (schemaLocation == NULL))
+ return (-1);
+
+ *schemaLocation = NULL;
+ /*
+ * Check for illegal attributes.
+ * Applies for both <include> and <redefine>.
+ */
+ attr = node->properties;
+ while (attr != NULL) {
+ if (attr->ns == NULL) {
+ if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
+ (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
+ xmlSchemaPIllegalAttrErr(pctxt,
+ XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
+ NULL, NULL, attr);
+ }
+ } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
+ xmlSchemaPIllegalAttrErr(pctxt,
+ XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
+ NULL, NULL, attr);
+ }
+ attr = attr->next;
+ }
+ xmlSchemaPValAttrID(pctxt, NULL, NULL, node, BAD_CAST "id");
+ /*
+ * Preliminary step, extract the URI-Reference and make an URI
+ * from the base.
+ */
+ /*
+ * Attribute "schemaLocation" is mandatory.
+ */
+ attr = xmlSchemaGetPropNode(node, "schemaLocation");
+ if (attr != NULL) {
+ xmlChar *base = NULL;
+ xmlChar *uri = NULL;
+
+ if (xmlSchemaPValAttrNode(pctxt, NULL, NULL, attr,
+ xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
+ (const xmlChar **) schemaLocation) != 0)
+ goto exit_error;
+ base = xmlNodeGetBase(node->doc, node);
+ if (base == NULL) {
+ uri = xmlBuildURI(*schemaLocation, node->doc->URL);
+ } else {
+ uri = xmlBuildURI(*schemaLocation, base);
+ xmlFree(base);
+ }
+ if (uri == NULL) {
+ PERROR_INT("xmlSchemaParseIncludeOrRedefine",
+ "could not build an URI from the schemaLocation")
+ goto exit_failure;
+ }
+ (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
+ xmlFree(uri);
+ } else {
+ xmlSchemaPMissingAttrErr(pctxt,
+ XML_SCHEMAP_S4S_ATTR_MISSING,
+ NULL, node, "schemaLocation", NULL);
+ goto exit_error;
+ }
+ /*
+ * Report self-inclusion and self-redefinition.
+ */
+ if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
+ if (isRedefine) {
+ xmlSchemaPCustomErr(pctxt,
+ XML_SCHEMAP_SRC_REDEFINE,
+ NULL, NULL, node,
+ "The schema document '%s' cannot redefine itself.",
+ *schemaLocation);
+ } else {
+ xmlSchemaPCustomErr(pctxt,
+ XML_SCHEMAP_SRC_INCLUDE,
+ NULL, NULL, node,
+ "The schema document '%s' cannot include itself.",
+ *schemaLocation);
+ }
+ goto exit_error;
+ }
+
+ return(0);
+exit_error:
+ return(pctxt->err);
+exit_failure:
+ return(-1);
+}
+
+static int
+xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
+ xmlSchemaPtr schema,
+ xmlNodePtr node,
+ int isRedefine)
+{
+ xmlNodePtr child = NULL;
+ const xmlChar *schemaLocation = NULL;
+ int res = 0;
+
+ if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
+ return (-1);
+
+ /*
+ * Parse attributes.
+ */
+ res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
+ node, (xmlChar **) (&schemaLocation), isRedefine);
+ if (res != 0)
+ return(res);
+
+ /*
+ * Include the schema.
+ */
+ res = xmlSchemaParseIncludedDoc(pctxt, schema, node, schemaLocation);
+ if (res != 0)
+ return(res);
+ /*
+ * And now for the children...
+ */
+ child = node->children;
+
+ if (isRedefine) {
+ /*
+ * Parse (simpleType | complexType | group | attributeGroup))*
+ */
+ pctxt->isRedefine = 1;
+ while (IS_SCHEMA(child, "annotation") ||
+ IS_SCHEMA(child, "simpleType") ||
+ IS_SCHEMA(child, "complexType") ||
+ IS_SCHEMA(child, "group") ||
+ IS_SCHEMA(child, "attributeGroup")) {
+ if (IS_SCHEMA(child, "annotation")) {
+ /*
+ * TODO: discard or not?
+ */
+ } else if (IS_SCHEMA(child, "simpleType")) {
+ xmlSchemaParseSimpleType(pctxt, schema, child, 1);
+ } else if (IS_SCHEMA(child, "complexType")) {
+ xmlSchemaParseComplexType(pctxt, schema, child, 1);
+ } else if (IS_SCHEMA(child, "group")) {
+ TODO
+ /* xmlSchemaParseModelGroupDefinition(pctxt, schema, child); */
+ } else if (IS_SCHEMA(child, "attributeGroup")) {
+ TODO
+ /* xmlSchemaParseAttributeGroup(pctxt, schema, child, 1); */
+ }
+ child = child->next;
+ }
+ pctxt->isRedefine = 0;
+ } else {
+ if (IS_SCHEMA(child, "annotation")) {
+ /*
+ * TODO: discard or not?
+ */
+ child = child->next;
+ }
+ }
+ if (child != NULL) {
+ if (isRedefine) {
+ xmlSchemaPContentErr(pctxt,
+ XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
+ NULL, NULL, node, child, NULL,
+ "(annotation | (simpleType | complexType | group | attributeGroup))*");
+ } else {
+ xmlSchemaPContentErr(pctxt,
+ XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
+ NULL, NULL, node, child, NULL,
+ "(annotation?)");
+ }
+ return(pctxt->err);
+ }
+ return(0);
+}
+
+#if 0
+static int
+xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
+ xmlNodePtr node)
+{
+ int res;
+
+ res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, 1);
+ if (res != 0)
+ return(res);
+ return(0);
+}
+#endif
+
+static int
+xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
+ xmlNodePtr node)
+{
+ int res;
+
+ res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, 0);
+ if (res != 0)
+ return(res);
+ return(0);
+}
+
/**
* xmlSchemaParseModelGroup:
* @ctxt: a schema validation context
@@ -9791,22 +10085,54 @@
*/
xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
/*
- * Attribute "base" - mandatory if inside a complex type.
+ * Attribute
*/
/*
- * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
+ * Extract the base type. The "base" attribute is mandatory if inside
+ * a complex type or if redefining.
+ *
+ * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
* among its [children]), the simple type definition which is
* the {content type} of the type definition ·resolved· to by
* the ·actual value· of the base [attribute]"
*/
- if ((xmlSchemaPValAttrQName(ctxt, schema,
+ if (xmlSchemaPValAttrQName(ctxt, schema,
NULL, NULL, node, "base",
- &(type->baseNs), &(type->base)) == 0) &&
- (type->base == NULL) &&
- (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
- xmlSchemaPMissingAttrErr(ctxt,
- XML_SCHEMAP_S4S_ATTR_MISSING,
- type, node, "base", NULL);
+ &(type->baseNs), &(type->base)) == 0)
+ {
+ if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
+ xmlSchemaPMissingAttrErr(ctxt,
+ XML_SCHEMAP_S4S_ATTR_MISSING,
+ type, node, "base", NULL);
+ } else if ((ctxt->isRedefine) &&
+ (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
+ {
+ if (type->base == NULL) {
+ xmlSchemaPMissingAttrErr(ctxt,
+ XML_SCHEMAP_S4S_ATTR_MISSING,
+ type, node, "base", NULL);
+ } else if ((! xmlStrEqual(type->base, type->name)) ||
+ (! xmlStrEqual(type->baseNs, type->targetNamespace)))
+ {
+ xmlChar *str1 = NULL, *str2 = NULL;
+ /*
+ * REDEFINE: SPEC src-redefine (5)
+ * "Within the [children], each <simpleType> must have a
+ * <restriction> among its [children] ... the ·actual value· of
+ * whose base [attribute] must be the same as the ·actual value·
+ * of its own name attribute plus target namespace;"
+ */
+ xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
+ NULL, NULL, node, "This is a redefinition, but the QName "
+ "value '%s' of the 'base' attribute does not match the "
+ "type's designation '%s'",
+ xmlSchemaFormatQName(&str1, type->baseNs, type->base),
+ xmlSchemaFormatQName(&str1, type->targetNamespace,
+ type->name), NULL);
+ FREE_AND_NULL(str1);
+ FREE_AND_NULL(str2);
+ }
+ }
}
/*
* And now for the children...
@@ -10160,14 +10486,17 @@
*/
static int
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
- xmlSchemaPtr schema, xmlNodePtr node)
+ xmlSchemaPtr schema, xmlNodePtr node,
+ int *hasRestrictionOrExtension)
{
xmlSchemaTypePtr type;
xmlNodePtr child = NULL;
xmlAttrPtr attr;
- if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+ if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
+ (hasRestrictionOrExtension == NULL))
return (-1);
+ *hasRestrictionOrExtension = 0;
/* Not a component, don't create it. */
type = ctxt->ctxtType;
type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
@@ -10204,13 +10533,21 @@
xmlSchemaParseAnnotation(ctxt, schema, child));
child = child->next;
}
+ if (child == NULL) {
+ xmlSchemaPContentErr(ctxt,
+ XML_SCHEMAP_S4S_ELEM_MISSING,
+ NULL, NULL, node, NULL, NULL,
+ "(annotation?, (restriction | extension))");
+ }
if (IS_SCHEMA(child, "restriction")) {
xmlSchemaParseRestriction(ctxt, schema, child,
XML_SCHEMA_TYPE_SIMPLE_CONTENT);
+ (*hasRestrictionOrExtension) = 1;
child = child->next;
} else if (IS_SCHEMA(child, "extension")) {
xmlSchemaParseExtension(ctxt, schema, child,
XML_SCHEMA_TYPE_SIMPLE_CONTENT);
+ (*hasRestrictionOrExtension) = 1;
child = child->next;
}
if (child != NULL) {
@@ -10235,14 +10572,17 @@
*/
static int
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
- xmlSchemaPtr schema, xmlNodePtr node)
+ xmlSchemaPtr schema, xmlNodePtr node,
+ int *hasRestrictionOrExtension)
{
xmlSchemaTypePtr type;
xmlNodePtr child = NULL;
xmlAttrPtr attr;
- if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
+ if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
+ (hasRestrictionOrExtension == NULL))
return (-1);
+ *hasRestrictionOrExtension = 0;
/* Not a component, don't create it. */
type = ctxt->ctxtType;
/*
@@ -10284,13 +10624,21 @@
xmlSchemaParseAnnotation(ctxt, schema, child));
child = child->next;
}
+ if (child == NULL) {
+ xmlSchemaPContentErr(ctxt,
+ XML_SCHEMAP_S4S_ELEM_MISSING,
+ NULL, NULL, node, NULL,
+ NULL, "(annotation?, (restriction | extension))");
+ }
if (IS_SCHEMA(child, "restriction")) {
xmlSchemaParseRestriction(ctxt, schema, child,
XML_SCHEMA_TYPE_COMPLEX_CONTENT);
+ (*hasRestrictionOrExtension) = 1;
child = child->next;
} else if (IS_SCHEMA(child, "extension")) {
xmlSchemaParseExtension(ctxt, schema, child,
XML_SCHEMA_TYPE_COMPLEX_CONTENT);
+ (*hasRestrictionOrExtension) = 1;
child = child->next;
}
if (child != NULL) {
@@ -10322,9 +10670,8 @@
const xmlChar *oldcontainer, *name = NULL;
xmlAttrPtr attr;
const xmlChar *attrValue;
- xmlChar *des = NULL; /* The reported designation. */
char buf[40];
- int final = 0, block = 0;
+ int final = 0, block = 0, hasRestrictionOrExtension = 0;
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
@@ -10339,10 +10686,10 @@
XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
return (NULL);
} else if (xmlSchemaPValAttrNode(ctxt,
- (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
+ NULL, NULL, attr,
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
return (NULL);
- }
+ }
}
if (topLevel == 0) {
@@ -10350,7 +10697,8 @@
* Parse as local complex type definition.
*/
snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
- type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
+ type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL,
+ node, 0);
if (type == NULL)
return (NULL);
name = type->name;
@@ -10363,7 +10711,8 @@
/*
* Parse as global complex type definition.
*/
- type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
+ type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace,
+ node, 1);
if (type == NULL)
return (NULL);
type->node = node;
@@ -10387,7 +10736,7 @@
/*
* Attribute "mixed".
*/
- if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
+ if (xmlSchemaPGetBoolNodeValue(ctxt, NULL, type,
(xmlNodePtr) attr))
type->flags |= XML_SCHEMAS_TYPE_MIXED;
} else if (topLevel) {
@@ -10400,7 +10749,7 @@
/*
* Attribute "abstract".
*/
- if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
+ if (xmlSchemaPGetBoolNodeValue(ctxt, NULL, type,
(xmlNodePtr) attr))
type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
@@ -10444,17 +10793,17 @@
} else {
xmlSchemaPIllegalAttrErr(ctxt,
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
- &des, type, attr);
+ NULL, type, attr);
}
} else {
xmlSchemaPIllegalAttrErr(ctxt,
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
- &des, type, attr);
+ NULL, type, attr);
}
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
xmlSchemaPIllegalAttrErr(ctxt,
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
- &des, type, attr);
+ NULL, type, attr);
}
attr = attr->next;
}
@@ -10489,20 +10838,28 @@
ctxt->ctxtType = type;
if (IS_SCHEMA(child, "simpleContent")) {
/*
+ * <complexType><simpleContent>...
* 3.4.3 : 2.2
* Specifying mixed='true' when the <simpleContent>
* alternative is chosen has no effect
*/
if (type->flags & XML_SCHEMAS_TYPE_MIXED)
type->flags ^= XML_SCHEMAS_TYPE_MIXED;
- xmlSchemaParseSimpleContent(ctxt, schema, child);
+ xmlSchemaParseSimpleContent(ctxt, schema, child,
+ &hasRestrictionOrExtension);
child = child->next;
} else if (IS_SCHEMA(child, "complexContent")) {
+ /*
+ * <complexType><complexContent>...
+ */
type->contentType = XML_SCHEMA_CONTENT_EMPTY;
- xmlSchemaParseComplexContent(ctxt, schema, child);
+ xmlSchemaParseComplexContent(ctxt, schema, child,
+ &hasRestrictionOrExtension);
child = child->next;
} else {
/*
+ * E.g <complexType><sequence>... or <complexType><attribute>... etc.
+ *
* SPEC
* "...the third alternative (neither <simpleContent> nor
* <complexContent>) is chosen. This case is understood as shorthand
@@ -10549,12 +10906,20 @@
if (child != NULL) {
xmlSchemaPContentErr(ctxt,
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
- &des, type, node, child,
+ NULL, type, node, child,
NULL, "(annotation?, (simpleContent | complexContent | "
"((group | all | choice | sequence)?, ((attribute | "
"attributeGroup)*, anyAttribute?))))");
}
- FREE_AND_NULL(des);
+ /*
+ * REDEFINE: SPEC src-redefine (5)
+ */
+ if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
+ xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
+ NULL, NULL, node, "This is a redefinition, thus the "
+ "<complexType> must have a <restriction> or <extension> "
+ "grand-child", NULL);
+ }
ctxt->container = oldcontainer;
ctxt->ctxtType = ctxtType;
return (type);
@@ -10591,6 +10956,7 @@
ctxt->isS4S = 0;
if (IS_SCHEMA(node, "schema")) {
xmlSchemaImportPtr import;
+ /* xmlSchemaSchemaRefPtr ref; */
schema = xmlSchemaNewSchema(ctxt);
if (schema == NULL)
@@ -10618,14 +10984,22 @@
* if all schemata are constructed dynamically fired by the
* instance or if the schema to be used was specified via
* the API.
+ * TODO
*/
+ /*
+ ref = xmlSchemaNewSchemaRef();
+ if (ref == NULL) {
+ xmlSchemaFree(schema);
+ schema = NULL;
+ return NULL;
+ }
+ */
+
import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
schema->targetNamespace);
if (import == NULL) {
- xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
- NULL, NULL, (xmlNodePtr) ctxt->doc,
- "Internal error: xmlSchemaParseSchema, "
- "failed to add an import entry", NULL);
+ xmlSchemaPInternalErr(ctxt, "xmlSchemaParseSchema",
+ "failed to add an import entry", NULL, NULL);
xmlSchemaFree(schema);
schema = NULL;
return (NULL);
@@ -13268,7 +13642,14 @@
((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
(item->type != XML_SCHEMA_TYPE_SIMPLE)))
return;
- xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
+ if (item->redef != NULL) {
+ xmlSchemaTypePtr cur = item;
+ do {
+ xmlSchemaCheckTypeDefCircularInternal(ctxt, cur, cur->baseType);
+ cur = cur->redef;
+ } while (cur != NULL);
+ } else
+ xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
}
@@ -16046,7 +16427,7 @@
snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
content = xmlSchemaAddType(pctxt,
- pctxt->schema, tmpname, tmpname, type->node);
+ pctxt->schema, tmpname, tmpname, type->node, 0);
if (content == NULL)
return;
/*
@@ -18365,8 +18746,6 @@
return (ret);
}
-#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
-
static const xmlChar *
xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
const xmlChar *prefix)
@@ -18402,7 +18781,6 @@
if (nsName != NULL) {
const xmlChar *ret;
- VAL_CREATE_DICT;
ret = xmlDictLookup(vctxt->dict, nsName, -1);
xmlFree(nsName);
return (ret);
@@ -18498,6 +18876,34 @@
return (ret);
}
+static int
+xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
+ const xmlChar* lname,
+ const xmlChar* nsname)
+{
+ int i;
+
+ lname = xmlDictLookup(vctxt->dict, lname, -1);
+ if (lname == NULL)
+ return(-1);
+ if (nsname != NULL) {
+ nsname = xmlDictLookup(vctxt->dict, nsname, -1);
+ if (nsname == NULL)
+ return(-1);
+ }
+ for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
+ if ((vctxt->nodeQNames->items [i] == lname) &&
+ (vctxt->nodeQNames->items[i +1] == nsname))
+ /* Already there */
+ return(i);
+ }
+ /* Add new entry. */
+ i = vctxt->nodeQNames->nbItems;
+ xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
+ xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
+ return(i);
+}
+
/************************************************************************
* *
* Validation of identity-constraints (IDC) *
@@ -19435,7 +19841,7 @@
*keySeq = NULL;
return(-1);
}
- memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
+ memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
/*
* Store the node-table item on global list.
@@ -19447,11 +19853,27 @@
*keySeq = NULL;
return (-1);
}
+ ntItem->nodeQNameID = -1;
+ } else {
+ /*
+ * Save a cached QName for this node on the IDC node, to be
+ * able to report it, even if the node is not saved.
+ */
+ ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
+ vctxt->inode->localName, vctxt->inode->nsName);
+ if (ntItem->nodeQNameID == -1) {
+ xmlFree(ntItem);
+ xmlFree(*keySeq);
+ *keySeq = NULL;
+ return (-1);
+ }
}
/*
- * Init the node-table item. Consume the key-sequence.
+ * Init the node-table item: Save the node, position and
+ * consume the key-sequence.
*/
ntItem->node = vctxt->node;
+ ntItem->nodeLine = vctxt->inode->nodeLine;
ntItem->keys = *keySeq;
*keySeq = NULL;
if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
@@ -19922,6 +20344,7 @@
int i, j, k, res;
xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
xmlSchemaPSVIIDCKeyPtr refKey, key;
+ xmlSchemaPSVIIDCNodePtr refNode = NULL;
/*
* Find the referred key/unique.
@@ -19939,8 +20362,9 @@
*/
for (i = 0; i < refbind->nbNodes; i++) {
res = 0;
- if (bind != NULL) {
- refKeys = refbind->nodeTable[i]->keys;
+ refNode = refbind->nodeTable[i];
+ if (bind != NULL) {
+ refKeys = refNode->keys;
for (j = 0; j < bind->nbNodes; j++) {
keys = bind->nodeTable[j]->keys;
for (k = 0; k < bind->definition->nbFields; k++) {
@@ -19965,8 +20389,8 @@
if (res == 0) {
xmlChar *str = NULL, *strB = NULL;
/* TODO: Report the key-sequence. */
- xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
- XML_SCHEMAV_CVC_IDC, NULL,
+ xmlSchemaKeyrefErr(vctxt,
+ XML_SCHEMAV_CVC_IDC, refNode,
(xmlSchemaTypePtr) refbind->definition,
"No match found for key-sequence %s of key "
"reference '%s'",
@@ -20047,8 +20471,9 @@
static int
xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
xmlNodePtr attrNode,
+ int nodeLine,
const xmlChar *localName,
- const xmlChar *nsName,
+ const xmlChar *nsName,
int ownedNames,
xmlChar *value,
int ownedValue)
@@ -20062,6 +20487,7 @@
return (-1);
}
attr->node = attrNode;
+ attr->nodeLine = nodeLine;
attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
attr->localName = localName;
attr->nsName = nsName;
@@ -20895,7 +21321,6 @@
* string.
*/
local = xmlSplitQName2(value, &prefix);
- VAL_CREATE_DICT;
if (local == NULL)
*localName = xmlDictLookup(vctxt->dict, value, -1);
else {
@@ -23280,6 +23705,10 @@
goto internal_error;
}
ielem = vctxt->inode;
+ /*
+ * TODO: Is this OK?
+ */
+ ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
ielem->localName = localname;
ielem->nsName = URI;
ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
@@ -23347,8 +23776,11 @@
*/
value = xmlStrndup(attributes[j+3],
attributes[j+4] - attributes[j+3]);
+ /*
+ * TODO: Set the node line.
+ */
ret = xmlSchemaValidatorPushAttribute(vctxt,
- NULL, attributes[j], attributes[j+2], 0,
+ NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
value, 1);
if (ret == -1) {
VERROR_INT("xmlSchemaSAXHandleStartElementNs",
@@ -23449,6 +23881,8 @@
}
memset(ret, 0, sizeof(xmlSchemaValidCtxt));
ret->type = XML_SCHEMA_CTXT_VALIDATOR;
+ ret->dict = xmlDictCreate();
+ ret->nodeQNames = xmlSchemaNewItemList();
ret->schema = schema;
return (ret);
}
@@ -23526,7 +23960,11 @@
break;
xmlSchemaClearElemInfo(ei);
}
- }
+ }
+ xmlSchemaItemListClear(vctxt->nodeQNames);
+ /* Recreate the dict. */
+ xmlDictFree(vctxt->dict);
+ vctxt->dict = xmlDictCreate();
}
/**
@@ -23604,6 +24042,8 @@
}
xmlFree(ctxt->elemInfos);
}
+ if (ctxt->nodeQNames != NULL)
+ xmlSchemaFreeItemList(ctxt->nodeQNames);
if (ctxt->dict != NULL)
xmlDictFree(ctxt->dict);
xmlFree(ctxt);
@@ -23780,6 +24220,7 @@
goto internal_error;
ielem = vctxt->inode;
ielem->node = node;
+ ielem->nodeLine = node->line;
ielem->localName = node->name;
if (node->ns != NULL)
ielem->nsName = node->ns->href;
@@ -23799,6 +24240,11 @@
nsName = NULL;
ret = xmlSchemaValidatorPushAttribute(vctxt,
(xmlNodePtr) attr,
+ /*
+ * Note that we give it the line number of the
+ * parent element.
+ */
+ ielem->nodeLine,
attr->name, nsName, 0,
xmlNodeListGetString(attr->doc, attr->children, 1), 1);
if (ret == -1) {