applied a patch from Kasimier Buchcik implementing attribute uses and
* xmlschemas.c include/libxml/schemasInternals.h
include/libxml/xmlerror.h: applied a patch from Kasimier Buchcik
implementing attribute uses and wildcards.
* test/schemas/* result/schemas/*: added/fixed a bunch of tests
Daniel
diff --git a/xmlschemas.c b/xmlschemas.c
index e9dfadb..9c9f17f 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -42,6 +42,8 @@
/* #define DEBUG_AUTOMATA 1 */
+/* #define DEBUG_ATTR_VALIDATION 1 */
+
#define UNBOUNDED (1 << 30)
#define TODO \
xmlGenericError(xmlGenericErrorContext, \
@@ -105,12 +107,18 @@
#define XML_SCHEMAS_ATTR_UNKNOWN 1
#define XML_SCHEMAS_ATTR_CHECKED 2
+#define XML_SCHEMAS_ATTR_PROHIBITED 3
+#define XML_SCHEMAS_ATTR_MISSING 4
+#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
+#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
struct _xmlSchemaAttrState {
+ xmlSchemaAttrStatePtr next;
xmlAttrPtr attr;
int state;
+ xmlSchemaAttributePtr decl;
};
/**
@@ -143,9 +151,9 @@
xmlRegExecCtxtPtr regexp;
xmlSchemaValPtr value;
- int attrNr;
- int attrBase;
- int attrMax;
+ xmlSchemaAttrStatePtr attrTop;
+ /* xmlSchemaAttrStatePtr attrBase; */
+ /* int attrMax; */
xmlSchemaAttrStatePtr attr;
};
@@ -267,6 +275,47 @@
}
/**
+ * xmlSchemaPErrExt:
+ * @ctxt: the parsing context
+ * @node: the context node
+ * @error: the error code
+ * @strData1: extra data
+ * @strData2: extra data
+ * @strData3: extra data
+ * @msg: the message
+ * @str1: extra parameter for the message display
+ * @str2: extra parameter for the message display
+ * @str3: extra parameter for the message display
+ * @str4: extra parameter for the message display
+ * @str5: extra parameter for the message display
+ *
+ * Handle a parser error
+ */
+static void
+xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
+ const xmlChar * strData1, const xmlChar * strData2,
+ const xmlChar * strData3, const char *msg, const xmlChar * str1,
+ const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
+ const xmlChar * str5)
+{
+
+ xmlGenericErrorFunc channel = NULL;
+ xmlStructuredErrorFunc schannel = NULL;
+ void *data = NULL;
+
+ if (ctxt != NULL) {
+ ctxt->nberrors++;
+ channel = ctxt->error;
+ data = ctxt->userData;
+ schannel = ctxt->serror;
+ }
+ __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
+ error, XML_ERR_ERROR, NULL, 0,
+ (const char *) strData1, (const char *) strData2,
+ (const char *) strData3, 0, 0, msg, str1, str2, str3, str4, str5);
+}
+
+/**
* xmlSchemaVTypeErrMemory:
* @node: a context node
* @extra: extra informations
@@ -524,6 +573,44 @@
}
/**
+ * xmlSchemaFreeWildcardNsSet:
+ * set: a schema wildcard namespace
+ *
+ * Deallocate a list of wildcard constraint structures.
+ */
+static void
+xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
+{
+ xmlSchemaWildcardNsPtr next;
+
+ while (set != NULL) {
+ next = set->next;
+ xmlFree(set);
+ set = next;
+ }
+}
+
+/**
+ * xmlSchemaFreeWildcard:
+ * @schema: a schema attribute group structure
+ *
+ * Deallocate a Schema Attribute Group structure.
+ */
+static void
+xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
+{
+ if (wildcard == NULL)
+ return;
+ if (wildcard->annot != NULL)
+ xmlSchemaFreeAnnot(wildcard->annot);
+ if (wildcard->nsSet != NULL)
+ xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
+ if (wildcard->negNsSet != NULL)
+ xmlFree(wildcard->negNsSet);
+ xmlFree(wildcard);
+}
+
+/**
* xmlSchemaFreeAttributeGroup:
* @schema: a schema attribute group structure
*
@@ -534,10 +621,34 @@
{
if (attr == NULL)
return;
+ if (attr->annot != NULL)
+ xmlSchemaFreeAnnot(attr->annot);
+ if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
+ (attr->attributeWildcard != NULL))
+ xmlSchemaFreeWildcard(attr->attributeWildcard);
+
xmlFree(attr);
}
/**
+ * xmlSchemaFreeAttributeUseList:
+ * @attrUse: a schema attribute link structure
+ *
+ * Deallocate a list of schema attribute uses.
+ */
+static void
+xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
+{
+ xmlSchemaAttributeLinkPtr next;
+
+ while (attrUse != NULL) {
+ next = attrUse->next;
+ xmlFree(attrUse);
+ attrUse = next;
+ }
+}
+
+/**
* xmlSchemaFreeElement:
* @schema: a schema element structure
*
@@ -598,6 +709,16 @@
facet = next;
}
}
+ if (type->type != XML_SCHEMA_TYPE_BASIC) {
+ if (type->attributeUses != NULL)
+ xmlSchemaFreeAttributeUseList(type->attributeUses);
+ if ((type->attributeWildcard != NULL) &&
+ ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
+ ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
+ (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)))) {
+ xmlSchemaFreeWildcard(type->attributeWildcard);
+ }
+ }
xmlFree(type);
}
@@ -689,16 +810,14 @@
return;
fprintf(output, "Element ");
- if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
- fprintf(output, "toplevel ");
+ if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
+ fprintf(output, "global ");
fprintf(output, ": %s ", elem->name);
if (namespace != NULL)
fprintf(output, "namespace '%s' ", namespace);
if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
fprintf(output, "nillable ");
- if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
- fprintf(output, "global ");
if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
fprintf(output, "default ");
if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
@@ -1040,12 +1159,13 @@
if ((name == NULL) || (schema == NULL))
return (NULL);
- if (namespace == NULL) {
+
ret = xmlHashLookup2(schema->elemDecl, name, namespace);
if ((ret != NULL) &&
- ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
+ ((level == 0) || (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>
@@ -1062,17 +1182,19 @@
return (ret);
}
*/
- } else {
- ret = xmlHashLookup2(schema->elemDecl, name, namespace);
- if ((ret != NULL) &&
- ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
- return (ret);
- }
- }
- if (level > 0)
+
+ /* if (level > 0) */
+ if (namespace == NULL)
+ import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
+ else
import = xmlHashLookup(schema->schemasImports, namespace);
- if (import != NULL)
+ if (import != NULL) {
ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
+ if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
+ return (ret);
+ } else
+ ret = NULL;
+ }
#ifdef DEBUG
if (ret == NULL) {
if (namespace == NULL)
@@ -1106,15 +1228,23 @@
return (NULL);
if (schema != NULL) {
ret = xmlHashLookup2(schema->typeDecl, name, namespace);
- if (ret != NULL)
+ if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
return (ret);
}
ret = xmlSchemaGetPredefinedType(name, namespace);
if (ret != NULL)
return (ret);
+ if (namespace == NULL)
+ import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
+ else
import = xmlHashLookup(schema->schemasImports, namespace);
- if (import != NULL)
+ if (import != NULL) {
ret = xmlSchemaGetType(import->schema, name, namespace);
+ if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
+ return (ret);
+ } else
+ ret = NULL;
+ }
#ifdef DEBUG
if (ret == NULL) {
if (namespace == NULL)
@@ -1127,6 +1257,153 @@
return (ret);
}
+/**
+ * xmlSchemaGetAttribute:
+ * @schema: the context of the schema
+ * @name: the name of the attribute
+ * @ns: the target namespace of the attribute
+ *
+ * Lookup a an attribute in the schema or imported schemas
+ *
+ * Returns the attribute declaration or NULL if not found.
+ */
+static xmlSchemaAttributePtr
+xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
+ const xmlChar * namespace)
+{
+ xmlSchemaAttributePtr ret;
+ xmlSchemaImportPtr import = 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;
+ if (namespace == NULL)
+ import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
+ else
+ import = xmlHashLookup(schema->schemasImports, namespace);
+ if (import != NULL) {
+ ret = xmlSchemaGetAttribute(import->schema, name, namespace);
+ if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
+ return (ret);
+ } else
+ ret = NULL;
+ }
+#ifdef DEBUG
+ if (ret == NULL) {
+ if (namespace == NULL)
+ fprintf(stderr, "Unable to lookup attribute %s", name);
+ else
+ fprintf(stderr, "Unable to lookup attribute %s:%s", name,
+ namespace);
+ }
+#endif
+ return (ret);
+}
+
+/**
+ * xmlSchemaGetAttributeGroup:
+ * @schema: the context of the schema
+ * @name: the name of the attribute group
+ * @ns: the target namespace of the attribute group
+ *
+ * Lookup a an attribute group in the schema or imported schemas
+ *
+ * Returns the attribute group definition or NULL if not found.
+ */
+static xmlSchemaAttributeGroupPtr
+xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
+ const xmlChar * namespace)
+{
+ xmlSchemaAttributeGroupPtr ret;
+ xmlSchemaImportPtr import = 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;
+ if (namespace == NULL)
+ import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
+ else
+ import = xmlHashLookup(schema->schemasImports, namespace);
+ if (import != NULL) {
+ ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
+ if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
+ return (ret);
+ else
+ ret = NULL;
+ }
+#ifdef DEBUG
+ if (ret == NULL) {
+ if (namespace == NULL)
+ fprintf(stderr, "Unable to lookup attribute group %s", name);
+ else
+ fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
+ namespace);
+ }
+#endif
+ return (ret);
+}
+
+/**
+ * xmlSchemaGetGroup:
+ * @schema: the context of the schema
+ * @name: the name of the group
+ * @ns: the target namespace of the group
+ *
+ * Lookup a group in the schema or imported schemas
+ *
+ * Returns the group definition or NULL if not found.
+ */
+static xmlSchemaTypePtr
+xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
+ const xmlChar * namespace)
+{
+ xmlSchemaTypePtr ret;
+ xmlSchemaImportPtr import = NULL;
+
+ if ((name == NULL) || (schema == NULL))
+ return (NULL);
+
+
+ ret = xmlHashLookup2(schema->groupDecl, name, namespace);
+ if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
+ return (ret);
+ else
+ ret = NULL;
+ if (namespace == NULL)
+ import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
+ else
+ import = xmlHashLookup(schema->schemasImports, namespace);
+ if (import != NULL) {
+ ret = xmlSchemaGetGroup(import->schema, name, namespace);
+ if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
+ return (ret);
+ else
+ ret = NULL;
+ }
+#ifdef DEBUG
+ if (ret == NULL) {
+ if (namespace == NULL)
+ fprintf(stderr, "Unable to lookup group %s", name);
+ else
+ fprintf(stderr, "Unable to lookup group %s:%s", name,
+ namespace);
+ }
+#endif
+ return (ret);
+}
+
/************************************************************************
* *
* Parsing functions *
@@ -1434,6 +1711,8 @@
}
ret->minOccurs = 1;
ret->maxOccurs = 1;
+ ret->attributeUses = NULL;
+ ret->attributeWildcard = NULL;
return (ret);
}
@@ -1487,6 +1766,60 @@
return (ret);
}
+/**
+ * xmlSchemaNewWildcardNs:
+ * @ctxt: a schema validation context
+ *
+ * Creates a new wildcard namespace constraint.
+ *
+ * Returns the new struture or NULL in case of error
+ */
+static xmlSchemaWildcardNsPtr
+xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
+{
+ xmlSchemaWildcardNsPtr ret;
+
+ ret = (xmlSchemaWildcardNsPtr)
+ xmlMalloc(sizeof(xmlSchemaWildcardNs));
+ if (ret == NULL) {
+ xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
+ return (NULL);
+ }
+ ret->value = NULL;
+ ret->next = NULL;
+ return (ret);
+}
+
+/**
+ * xmlSchemaAddWildcard:
+ * @ctxt: a schema validation context
+ * @schema: the schema being built
+ * @name: the group name
+ *
+ * Add an XML schema Group definition
+ *
+ * Returns the new struture or NULL in case of error
+ */
+static xmlSchemaWildcardPtr
+xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
+{
+ xmlSchemaWildcardPtr ret = NULL;
+
+ if (ctxt == NULL)
+ return (NULL);
+
+ ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
+ if (ret == NULL) {
+ xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(xmlSchemaWildcard));
+ ret->minOccurs = 1;
+ ret->maxOccurs = 1;
+
+ return (ret);
+}
+
/************************************************************************
* *
* Utilities for parsing *
@@ -1661,11 +1994,13 @@
************************************************************************/
static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
ctxt, xmlSchemaPtr schema,
- xmlNodePtr node);
+ xmlNodePtr node,
+ int topLevel);
static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
ctxt,
xmlSchemaPtr schema,
- xmlNodePtr node);
+ xmlNodePtr node,
+ int topLevel);
static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
ctxt,
xmlSchemaPtr schema,
@@ -1684,14 +2019,15 @@
int topLevel);
static xmlSchemaAttributeGroupPtr
xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
- xmlSchemaPtr schema, xmlNodePtr node);
+ xmlSchemaPtr schema, xmlNodePtr node,
+ int topLevel);
static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaPtr schema,
xmlNodePtr node);
static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaPtr schema,
xmlNodePtr node);
-static xmlSchemaAttributePtr
+static xmlSchemaWildcardPtr
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaPtr schema, xmlNodePtr node);
@@ -1720,10 +2056,13 @@
attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
} else if (IS_SCHEMA(child, "attributeGroup")) {
attr = (xmlSchemaAttributePtr)
- xmlSchemaParseAttributeGroup(ctxt, schema, child);
+ xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
}
if (attr != NULL) {
if (lastattr == NULL) {
+ if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
+ ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
+ else
type->attributes = attr;
lastattr = attr;
} else {
@@ -1734,15 +2073,14 @@
child = child->next;
}
if (IS_SCHEMA(child, "anyAttribute")) {
- attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
- if (attr != NULL) {
- if (lastattr == NULL) {
- type->attributes = attr;
- lastattr = attr;
- } else {
- lastattr->next = attr;
- lastattr = attr;
- }
+ xmlSchemaWildcardPtr wildcard;
+
+ wildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
+ if (wildcard != NULL) {
+ if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
+ ((xmlSchemaAttributeGroupPtr) type)->attributeWildcard = wildcard;
+ else
+ type->attributeWildcard = wildcard;
}
child = child->next;
}
@@ -1955,28 +2293,20 @@
*
* Returns an attribute def structure or NULL
*/
-static xmlSchemaAttributePtr
+static xmlSchemaWildcardPtr
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaPtr schema, xmlNodePtr node)
{
- const xmlChar *processContents;
- xmlSchemaAttributePtr ret;
+ const xmlChar *processContents, *nsConstraint, *end, *cur, *dictMember;
+ xmlChar *member;
+ xmlSchemaWildcardPtr ret;
+ xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
xmlNodePtr child = NULL;
- char name[100];
-
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
return (NULL);
- snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
-
- /* local = xmlSchemaGetNamespace(ctxt, schema, node, BAD_CAST "anyattr", &ns); */
-
- /*
- * TODO: namespace = ((##any | ##other) | List of (anyURI |
- * (##targetNamespace | * ##local)) ) : ##any
- */
- ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, NULL);
+ ret = xmlSchemaAddWildcard(ctxt);
if (ret == NULL) {
return (NULL);
}
@@ -1985,18 +2315,87 @@
processContents = xmlSchemaGetProp(ctxt, node, "processContents");
if ((processContents == NULL)
|| (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
- ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
+ ret->processContents = XML_SCHEMAS_ANYATTR_STRICT;
} else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
- ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
+ ret->processContents = XML_SCHEMAS_ANYATTR_SKIP;
} else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
- ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
+ ret->processContents = XML_SCHEMAS_ANYATTR_LAX;
} else {
- xmlSchemaPErr2(ctxt, node, child,
+ xmlSchemaPErr(ctxt, node,
XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
"anyAttribute has unexpected content "
"for processContents: %s\n",
processContents, NULL);
- ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
+ ret->processContents = XML_SCHEMAS_ANYATTR_STRICT;
+ }
+ /*
+ * Build the namespace constraints.
+ */
+ nsConstraint = xmlSchemaGetProp(ctxt, node, "namespace");
+ if ((nsConstraint == NULL) || (xmlStrEqual(nsConstraint, "##any")))
+ ret->any = 1;
+ else if (xmlStrEqual(nsConstraint, "##other")) {
+ ret->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
+ if (ret->negNsSet == NULL) {
+ xmlSchemaFreeWildcard(ret);
+ return (NULL);
+ }
+ ret->negNsSet->value = schema->targetNamespace;
+ } else {
+ cur = nsConstraint;
+ do {
+ while (IS_BLANK_CH(*cur))
+ cur++;
+ end = cur;
+ while ((*end != 0) && (!(IS_BLANK_CH(*end))))
+ end++;
+ if (end == cur)
+ break;
+ member = xmlStrndup(cur, end - cur);
+ if ((xmlStrEqual(member, "##other")) || (xmlStrEqual(member, "##any"))) {
+ xmlSchemaPErr(ctxt, ret->node, XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
+ "The namespace constraint of an anyAttribute "
+ "is a set and must not contain \"%s\"\n",
+ member, NULL);
+ } else {
+ /*
+ * TODO: Validate the value (anyURI).
+ */
+ if (xmlStrEqual(member, "##targetNamespace")) {
+ dictMember = schema->targetNamespace;
+ } else if (xmlStrEqual(member, "##local")) {
+ dictMember = NULL;
+ } else
+ dictMember = xmlDictLookup(ctxt->dict, member, -1);
+ /*
+ * Avoid dublicate namespaces.
+ */
+ tmp = ret->nsSet;
+ while (tmp != NULL) {
+ if (dictMember == tmp->value)
+ break;
+ tmp = tmp->next;
+ }
+ if (tmp == NULL) {
+ tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
+ if (tmp == NULL) {
+ xmlFree(member);
+ xmlSchemaFreeWildcard(ret);
+ return (NULL);
+ }
+ tmp->value = dictMember;
+ tmp->next = NULL;
+ if (ret->nsSet == NULL)
+ ret->nsSet = tmp;
+ else
+ lastNs->next = tmp;
+ lastNs = tmp;
+ }
+
+ }
+ xmlFree(member);
+ cur = end;
+ } while (*cur != 0);
}
child = node->children;
@@ -2007,8 +2406,8 @@
if (child != NULL) {
xmlSchemaPErr2(ctxt, node, child,
XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
- "anyAttribute %s has unexpected content\n",
- (const xmlChar *) name, NULL);
+ "anyAttribute has unexpected content\n",
+ NULL, NULL);
}
return (ret);
@@ -2093,8 +2492,8 @@
if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
xmlSchemaPErr(ctxt, node,
XML_SCHEMAP_INVALID_ATTR_COMBINATION,
- "Attribute declaration has both, \"name\" and "
- "\"ref\"\n", NULL, NULL);
+ "Attribute declaration \"%s\" has both, \"name\" and "
+ "\"ref\"\n", name, NULL);
}
/* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
@@ -2112,7 +2511,8 @@
}
}
ret = xmlSchemaAddAttribute(ctxt, schema, name, ns);
-
+ if (ret == NULL)
+ return (NULL);
/* 3.2.6 Schema Component Constraint: xmlns Not Allowed */
if (xmlStrEqual(name, BAD_CAST "xmlns")) {
xmlSchemaPErr(ctxt, node,
@@ -2134,6 +2534,8 @@
return (NULL);
}
ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
+ if (topLevel)
+ ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
/* Handle the "use" attribute. */
attrVal = xmlSchemaGetProp(ctxt, node, "use");
@@ -2210,7 +2612,7 @@
"Attribute declaration %s has both (\"ref\" or "
"\"type\") and <simpleType>\n", name, NULL);
} else
- ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
+ ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
child = child->next;
}
if (child != NULL) {
@@ -2235,11 +2637,12 @@
*/
static xmlSchemaAttributeGroupPtr
xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
- xmlSchemaPtr schema, xmlNodePtr node)
+ xmlSchemaPtr schema, xmlNodePtr node,
+ int topLevel)
{
const xmlChar *name, *refNs = NULL, *ref = NULL;
xmlSchemaAttributeGroupPtr ret;
- xmlSchemaAttributePtr last = NULL, attr;
+ xmlSchemaAttributePtr last = NULL;
xmlNodePtr child = NULL;
const xmlChar *oldcontainer;
char buf[100];
@@ -2249,7 +2652,6 @@
oldcontainer = ctxt->container;
name = xmlSchemaGetProp(ctxt, node, "name");
if (name == NULL) {
-
ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
if (ref == NULL) {
xmlSchemaPErr2(ctxt, node, child,
@@ -2272,6 +2674,8 @@
ret->ref = ref;
ret->refNs = refNs;
ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
+ if (topLevel)
+ ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
ret->node = node;
child = node->children;
ctxt->container = name;
@@ -2279,6 +2683,9 @@
ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
child = child->next;
}
+ child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
+ /* Seems that this can be removed. */
+ /*
while ((IS_SCHEMA(child, "attribute")) ||
(IS_SCHEMA(child, "attributeGroup"))) {
attr = NULL;
@@ -2286,7 +2693,7 @@
attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
} else if (IS_SCHEMA(child, "attributeGroup")) {
attr = (xmlSchemaAttributePtr)
- xmlSchemaParseAttributeGroup(ctxt, schema, child);
+ xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
}
if (attr != NULL) {
if (last == NULL) {
@@ -2303,6 +2710,7 @@
TODO
child = child->next;
}
+ */
if (child != NULL) {
xmlSchemaPErr2(ctxt, node, child,
XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
@@ -2326,7 +2734,7 @@
*/
static xmlSchemaElementPtr
xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
- xmlNodePtr node, int toplevel)
+ xmlNodePtr node, int topLevel)
{
const xmlChar *name, *fixed;
const xmlChar *refNs = NULL, *ref = NULL;
@@ -2344,7 +2752,6 @@
oldcontainer = ctxt->container;
name = xmlSchemaGetProp(ctxt, node, "name");
if (name == NULL) {
-
ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
/* 3.3.3 : 2.1
* One of ref or name must be present, but not both
@@ -2352,9 +2759,10 @@
if (ref == NULL) {
xmlSchemaPErr(ctxt, node,
XML_SCHEMAP_ELEM_NONAME_NOREF,
- "Element has no name nor ref\n", NULL, NULL);
+ "Element declaration has no name nor ref\n", NULL, NULL);
return (NULL);
}
+
snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
name = (const xmlChar *) buf;
ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
@@ -2363,7 +2771,7 @@
/* Evaluate the target namespace */
if (schema->targetNamespace != NULL) {
- if (toplevel) {
+ if (topLevel) {
ns = schema->targetNamespace;
} else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
@@ -2379,7 +2787,7 @@
/* 3.3.3 : 2.1
* One of ref or name must be present, but not both
*/
- if ((!toplevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
+ if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
xmlSchemaPErr(ctxt, node,
XML_SCHEMAP_INVALID_ATTR_COMBINATION,
"Element declaration has both, \"name\" and "
@@ -2398,7 +2806,7 @@
ret->flags |= XML_SCHEMAS_ELEM_REF;
/* 3.3.3 : 2.2 */
- if ((!toplevel) && (ref != NULL)) {
+ if ((!topLevel) && (ref != NULL)) {
attr = node->properties;
while (attr != NULL) {
if ((attr->ns == NULL) &&
@@ -2416,12 +2824,14 @@
}
}
- if (toplevel)
+ if (topLevel) {
+ ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
+ }
if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
- ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
+ ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
ctxt->container = name;
ret->id = xmlSchemaGetProp(ctxt, node, "id");
@@ -2430,7 +2840,7 @@
ret->substGroup =
xmlGetQNameProp(ctxt, node, "substitutionGroup",
&(ret->substGroupNs));
- if ((ret->substGroup != NULL) && (!toplevel)) {
+ if ((ret->substGroup != NULL) && (!topLevel)) {
/* 3.3.6 : 3 */
/*
* TODO: This seems to be redundant, since the schema for schemas
@@ -2464,6 +2874,7 @@
ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
child = child->next;
}
+
if (ref != NULL) {
/* 3.3.3 (2.2) */
while (child != NULL) {
@@ -2496,7 +2907,7 @@
"and a local complex type\n",
ret->name, NULL);
} else
- ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
+ ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
child = child->next;
} else if (IS_SCHEMA(child, "simpleType")) {
/* 3.3.3 : 3
@@ -2510,7 +2921,7 @@
"and a local simple type\n",
ret->name, NULL);
} else
- ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
+ ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
child = child->next;
}
@@ -2568,7 +2979,7 @@
}
while (IS_SCHEMA(child, "simpleType")) {
subtype = (xmlSchemaTypePtr)
- xmlSchemaParseSimpleType(ctxt, schema, child);
+ xmlSchemaParseSimpleType(ctxt, schema, child, 0);
if (subtype != NULL) {
if (last == NULL) {
type->subtypes = subtype;
@@ -2630,7 +3041,7 @@
subtype = NULL;
if (IS_SCHEMA(child, "simpleType")) {
subtype = (xmlSchemaTypePtr)
- xmlSchemaParseSimpleType(ctxt, schema, child);
+ xmlSchemaParseSimpleType(ctxt, schema, child, 0);
child = child->next;
type->subtypes = subtype;
}
@@ -2656,7 +3067,7 @@
*/
static xmlSchemaTypePtr
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
- xmlNodePtr node)
+ xmlNodePtr node, int topLevel)
{
xmlSchemaTypePtr type, subtype;
xmlNodePtr child = NULL;
@@ -2680,6 +3091,8 @@
return (NULL);
type->node = node;
type->type = XML_SCHEMA_TYPE_SIMPLE;
+ if (topLevel)
+ type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
type->id = xmlSchemaGetProp(ctxt, node, "id");
child = node->children;
@@ -2733,7 +3146,7 @@
*/
static xmlSchemaTypePtr
xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
- xmlNodePtr node)
+ xmlNodePtr node, int topLevel)
{
xmlSchemaTypePtr type, subtype;
xmlNodePtr child = NULL;
@@ -2747,7 +3160,6 @@
name = xmlSchemaGetProp(ctxt, node, "name");
if (name == NULL) {
-
ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
if (ref == NULL) {
xmlSchemaPErr2(ctxt, node, child,
@@ -2763,9 +3175,10 @@
type = xmlSchemaAddGroup(ctxt, schema, name);
if (type == NULL)
return (NULL);
-
type->node = node;
type->type = XML_SCHEMA_TYPE_GROUP;
+ if (topLevel)
+ type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
type->id = xmlSchemaGetProp(ctxt, node, "id");
type->ref = ref;
type->refNs = refNs;
@@ -2898,7 +3311,7 @@
newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
if (newctxt == NULL) {
- xmlSchemaPErrMemory(ctxt, "allocating schama parser context",
+ xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
NULL);
return (NULL);
}
@@ -3066,8 +3479,39 @@
if (import == NULL) {
return (-1);
}
+ if (!xmlStrEqual(import->schema->targetNamespace, namespace)) {
+ if (namespace == NULL) {
+ if (import->schema->targetNamespace != NULL) {
+ xmlSchemaPErr(ctxt, node, XML_SCHRMAP_SRC_IMPORT_3_2,
+ "There is no namespace attribute on the <import> "
+ "element information item, so the imported document "
+ "must have no targetNamespace attribute.\n",
+ NULL, NULL);
+ }
+ } else {
+ if (import->schema->targetNamespace != NULL) {
+ xmlSchemaPErr(ctxt, node, XML_SCHRMAP_SRC_IMPORT_3_1,
+ "The namespace attribute \"%s\" of an <import> "
+ "element information item must be identical to the "
+ "targetNamespace attribute \"%s\" of the "
+ "imported document.\n",
+ namespace, import->schema->targetNamespace);
+ } else {
+ xmlSchemaPErr(ctxt, node, XML_SCHRMAP_SRC_IMPORT_3_1,
+ "The namespace attribute on the <import> "
+ "element information item, requires the imported "
+ "document to have a targetNamespace attribute "
+ "with the value \"%s\".\n",
+ namespace, NULL);
+ }
+ }
+ xmlSchemaFreeImport(import);
+ return (-1);
+ }
+
xmlHashAddEntry(schema->schemasImports,
namespace, import);
+
}
}
}
@@ -3205,10 +3649,10 @@
}
while (child != NULL) {
if (IS_SCHEMA(child, "complexType")) {
- xmlSchemaParseComplexType(ctxt, schema, child);
+ xmlSchemaParseComplexType(ctxt, schema, child, 1);
child = child->next;
} else if (IS_SCHEMA(child, "simpleType")) {
- xmlSchemaParseSimpleType(ctxt, schema, child);
+ xmlSchemaParseSimpleType(ctxt, schema, child, 1);
child = child->next;
} else if (IS_SCHEMA(child, "element")) {
xmlSchemaParseElement(ctxt, schema, child, 1);
@@ -3217,10 +3661,10 @@
xmlSchemaParseAttribute(ctxt, schema, child, 1);
child = child->next;
} else if (IS_SCHEMA(child, "attributeGroup")) {
- xmlSchemaParseAttributeGroup(ctxt, schema, child);
+ xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
child = child->next;
} else if (IS_SCHEMA(child, "group")) {
- xmlSchemaParseGroup(ctxt, schema, child);
+ xmlSchemaParseGroup(ctxt, schema, child, 1);
child = child->next;
} else if (IS_SCHEMA(child, "notation")) {
xmlSchemaParseNotation(ctxt, schema, child);
@@ -3435,7 +3879,7 @@
subtype = (xmlSchemaTypePtr)
xmlSchemaParseElement(ctxt, schema, child, 0);
} else if (IS_SCHEMA(child, "group")) {
- subtype = xmlSchemaParseGroup(ctxt, schema, child);
+ subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
} else if (IS_SCHEMA(child, "any")) {
subtype = xmlSchemaParseAny(ctxt, schema, child);
} else if (IS_SCHEMA(child, "sequence")) {
@@ -3513,7 +3957,7 @@
subtype = (xmlSchemaTypePtr)
xmlSchemaParseElement(ctxt, schema, child, 0);
} else if (IS_SCHEMA(child, "group")) {
- subtype = xmlSchemaParseGroup(ctxt, schema, child);
+ subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
} else if (IS_SCHEMA(child, "any")) {
subtype = xmlSchemaParseAny(ctxt, schema, child);
} else if (IS_SCHEMA(child, "choice")) {
@@ -3608,13 +4052,13 @@
type->subtypes = subtype;
} else if (IS_SCHEMA(child, "group")) {
subtype = (xmlSchemaTypePtr)
- xmlSchemaParseGroup(ctxt, schema, child);
+ xmlSchemaParseGroup(ctxt, schema, child, 0);
child = child->next;
type->subtypes = subtype;
} else {
if (IS_SCHEMA(child, "simpleType")) {
subtype = (xmlSchemaTypePtr)
- xmlSchemaParseSimpleType(ctxt, schema, child);
+ xmlSchemaParseSimpleType(ctxt, schema, child, 0);
child = child->next;
type->baseType = subtype;
}
@@ -3647,6 +4091,9 @@
child = child->next;
}
}
+ /* TODO: a restriction of simpleType does not contain any
+ * attribute declarations.
+ */
child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
if (child != NULL) {
xmlSchemaPErr2(ctxt, node, child,
@@ -3714,7 +4161,7 @@
subtype = xmlSchemaParseSequence(ctxt, schema, child);
child = child->next;
} else if (IS_SCHEMA(child, "group")) {
- subtype = xmlSchemaParseGroup(ctxt, schema, child);
+ subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
child = child->next;
}
if (subtype != NULL)
@@ -3752,7 +4199,6 @@
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
return (NULL);
-
snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
type = xmlSchemaAddType(ctxt, schema, name, NULL);
if (type == NULL)
@@ -3855,7 +4301,7 @@
*/
static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
- xmlNodePtr node)
+ xmlNodePtr node, int topLevel)
{
xmlSchemaTypePtr type, subtype;
xmlNodePtr child = NULL;
@@ -3869,7 +4315,6 @@
oldcontainer = ctxt->container;
name = xmlSchemaGetProp(ctxt, node, "name");
if (name == NULL) {
-
snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
name = (const xmlChar *)buf;
type = xmlSchemaAddType(ctxt, schema, name, NULL);
@@ -3881,12 +4326,13 @@
if (type == NULL) {
return (NULL);
}
-
if (xmlGetBooleanProp(ctxt, node, "mixed", 0))
type->flags |= XML_SCHEMAS_TYPE_MIXED;
type->node = node;
type->type = XML_SCHEMA_TYPE_COMPLEX;
+ if (topLevel)
+ type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
type->id = xmlSchemaGetProp(ctxt, node, "id");
ctxt->container = name;
@@ -3920,7 +4366,7 @@
subtype = xmlSchemaParseSequence(ctxt, schema, child);
child = child->next;
} else if (IS_SCHEMA(child, "group")) {
- subtype = xmlSchemaParseGroup(ctxt, schema, child);
+ subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
child = child->next;
}
if (subtype != NULL)
@@ -3933,6 +4379,8 @@
"ComplexType %s has unexpected content\n",
type->name, NULL);
}
+ if (type->attributeWildcard != NULL)
+ type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
ctxt->container = oldcontainer;
return (type);
}
@@ -4027,7 +4475,6 @@
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParse() failed\n");
#endif
-
return (schema);
}
@@ -4464,7 +4911,11 @@
case XML_SCHEMA_TYPE_ALL:{
xmlAutomataStatePtr start;
xmlSchemaTypePtr subtypes;
- xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
+ /*
+ * Changed, since type in not an xmlSchemaElement here.
+ */
+ /* xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type; */
+ xmlSchemaElementPtr elem;
int lax;
subtypes = type->subtypes;
@@ -4531,7 +4982,7 @@
if (type->subtypes == NULL) {
xmlSchemaTypePtr rgroup;
if (type->ref != NULL) {
- rgroup = xmlHashLookup2(ctxt->schema->groupDecl, type->ref,
+ rgroup = xmlSchemaGetGroup(ctxt->schema, type->ref,
type->refNs);
if (rgroup == NULL) {
xmlSchemaPErr(ctxt, type->node,
@@ -4634,13 +5085,14 @@
{
if ((ctxt == NULL) || (elem == NULL))
return;
+
if (elem->ref != NULL) {
xmlSchemaElementPtr elemDecl;
if (elem->subtypes != NULL) {
xmlSchemaPErr(ctxt, elem->node,
XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
- "Schemas: element %s have both ref and subtype\n",
+ "Schemas: element %s has both ref and subtype\n",
name, NULL);
return;
}
@@ -4658,7 +5110,7 @@
if (elem->subtypes != NULL) {
xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
- "Schemas: element %s have both type and subtype\n",
+ "Schemas: element %s has both type and subtype\n",
name, NULL);
return;
}
@@ -4771,6 +5223,1023 @@
}
/**
+ * xmlSchemaGetOnymousTypeName:
+ * @attr: the attribute declaration/use
+ *
+ * Returns the name of the attribute; if the attribute
+ * is a reference, the name of the referenced global type will be returned.
+ */
+static const xmlChar *
+xmlSchemaGetOnymousAttrName(xmlSchemaAttributePtr attr)
+{
+ if (attr->ref != NULL)
+ return(attr->ref);
+ else
+ return(attr->name);
+}
+
+/**
+ * xmlSchemaGetOnymousTargetNsURI:
+ * @type: the type (element or attribute)
+ *
+ * Returns the target namespace URI of the type; if the type is a reference,
+ * the target namespace of the referenced type will be returned.
+ */
+static const xmlChar *
+xmlSchemaGetOnymousTargetNsURI(xmlSchemaTypePtr type)
+{
+ if (type->type == XML_SCHEMA_TYPE_ELEMENT) {
+ if (type->ref != NULL)
+ return(((xmlSchemaElementPtr)((xmlSchemaElementPtr)
+ type)->subtypes)->targetNamespace);
+ else
+ return(((xmlSchemaElementPtr) type)->targetNamespace);
+ } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
+ if (type->ref != NULL)
+ return(((xmlSchemaAttributePtr)((xmlSchemaAttributePtr)
+ type)->subtypes)->targetNamespace);
+ else
+ return(((xmlSchemaAttributePtr) type)->targetNamespace);
+ } else
+ return (NULL);
+}
+
+/**
+ * xmlSchemaIsDerivedFromBuiltInType:
+ * @ctxt: the schema parser context
+ * @type: the type definition
+ * @valType: the value type
+ *
+ *
+ * Returns 1 if the type has the given value type, or
+ * is derived from such a type.
+ */
+int
+xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
+ xmlSchemaTypePtr type, int valType)
+{
+ /* TODO: Check if this works in every case. */
+ if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
+ (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
+ if (type->flags == valType)
+ return(1);
+ } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
+ if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
+ return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
+ ((xmlSchemaAttributePtr) type)->subtypes, valType));
+ } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
+ (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
+ if (type->baseType != NULL)
+ return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
+ valType));
+ } else if ((type->subtypes != NULL) &&
+ ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
+ (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
+ (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
+ (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
+ return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
+ valType));
+ }
+
+ return (0);
+}
+
+/**
+ * xmlSchemaBuildAttributeUsesOwned:
+ * @ctxt: the schema parser context
+ * @type: the complex type definition
+ * @cur: the attribute declaration list
+ * @lastUse: the top of the attribute use list
+ *
+ * Builds the attribute uses list on the given complex type.
+ * This one is supposed to be called by
+ * xmlSchemaBuildAttributeValidation only.
+ */
+static int
+xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
+ xmlSchemaAttributePtr cur,
+ xmlSchemaAttributeLinkPtr *uses,
+ xmlSchemaAttributeLinkPtr *lastUse)
+{
+ xmlSchemaAttributeLinkPtr tmp;
+ while (cur != NULL) {
+ if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
+ /*
+ * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
+ * to by the ·actual value·s of the ref [attribute] of the
+ * <attributeGroup> [children], if any."
+ */
+ if (xmlSchemaBuildAttributeUsesOwned(ctxt,
+ ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
+ lastUse) == -1) {
+ return (-1);
+ }
+ } else {
+ /* W3C: "1 The set of attribute uses corresponding to the
+ * <attribute> [children], if any."
+ */
+ tmp = (xmlSchemaAttributeLinkPtr)
+ xmlMalloc(sizeof(xmlSchemaAttributeLink));
+ if (tmp == NULL) {
+ xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
+ return (-1);
+ }
+ tmp->attr = cur;
+ tmp->next = NULL;
+ if (*uses == NULL)
+ *uses = tmp;
+ else
+ (*lastUse)->next = tmp;
+ *lastUse = tmp;
+ }
+ cur = cur->next;
+ }
+ return (0);
+}
+
+static int
+xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
+ xmlSchemaWildcardPtr *dest,
+ xmlSchemaWildcardPtr source)
+{
+ xmlSchemaWildcardNsPtr cur, tmp, last;
+
+ if ((source == NULL) || (*dest == NULL))
+ return(-1);
+ (*dest)->any = source->any;
+ cur = source->nsSet;
+ last = NULL;
+ while (cur != NULL) {
+ tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
+ if (tmp == NULL)
+ return(-1);
+ tmp->value = cur->value;
+ if (last == NULL)
+ (*dest)->nsSet = tmp;
+ else
+ last->next = tmp;
+ last = tmp;
+ cur = cur->next;
+ }
+ if ((*dest)->negNsSet != NULL)
+ xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
+ if (source->negNsSet != NULL) {
+ (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
+ if ((*dest)->negNsSet == NULL)
+ return(-1);
+ (*dest)->negNsSet->value = source->negNsSet->value;
+ } else
+ (*dest)->negNsSet = NULL;
+ return(0);
+}
+
+static int
+xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
+ xmlSchemaWildcardPtr completeWild,
+ xmlSchemaWildcardPtr curWild)
+{
+ xmlSchemaWildcardNsPtr cur, curB, tmp;
+
+ /*
+ * 1 If O1 and O2 are the same value, then that value must be the
+ * value.
+ */
+ if ((completeWild->any == curWild->any) &&
+ ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
+ ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
+
+ if ((completeWild->negNsSet == NULL) ||
+ (completeWild->negNsSet->value == curWild->negNsSet->value)) {
+
+ if (completeWild->nsSet != NULL) {
+ int found;
+
+ /*
+ * Check equality of sets.
+ */
+ cur = completeWild->nsSet;
+ while (cur != NULL) {
+ found = 0;
+ curB = curWild->nsSet;
+ while (curB != NULL) {
+ if (cur->value == curB->value) {
+ found = 1;
+ break;
+ }
+ curB = curB->next;
+ }
+ if (!found)
+ break;
+ cur = cur->next;
+ }
+ if (found)
+ return(0);
+ } else
+ return(0);
+ }
+ }
+ /*
+ * 2 If either O1 or O2 is any, then any must be the value
+ */
+ if ((completeWild->any != curWild->any) && (completeWild->any)) {
+ if (completeWild->any == 0) {
+ completeWild->any = 1;
+ if (completeWild->nsSet != NULL) {
+ xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
+ completeWild->nsSet = NULL;
+ }
+ if (completeWild->negNsSet != NULL) {
+ xmlFree(completeWild->negNsSet);
+ completeWild->negNsSet = NULL;
+ }
+ }
+ }
+ /*
+ * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
+ * then the union of those sets must be the value.
+ */
+ if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
+ int found;
+ xmlSchemaWildcardNsPtr start;
+
+ cur = curWild->nsSet;
+ start = completeWild->nsSet;
+ while (cur != NULL) {
+ found = 0;
+ curB = start;
+ while (curB != NULL) {
+ if (cur->value == curB->value) {
+ found = 1;
+ break;
+ }
+ curB = curB->next;
+ }
+ if (!found) {
+ tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
+ if (tmp == NULL)
+ return (-1);
+ tmp->value = cur->value;
+ tmp->next = completeWild->nsSet;
+ completeWild->nsSet = tmp;
+ }
+ cur = cur->next;
+ }
+
+ return(0);
+ }
+ /*
+ * 4 If the two are negations of different values (namespace names
+ * or ·absent·), then a pair of not and ·absent· must be the value.
+ */
+ if ((completeWild->negNsSet != NULL) &&
+ (curWild->negNsSet != NULL) &&
+ (completeWild->negNsSet->value != curWild->negNsSet->value)) {
+ completeWild->negNsSet->value = NULL;
+ }
+ /*
+ * 5.
+ */
+ if (((completeWild->negNsSet != NULL) &&
+ (completeWild->negNsSet->value != NULL) &&
+ (curWild->nsSet != NULL)) ||
+ ((curWild->negNsSet != NULL) &&
+ (curWild->negNsSet->value != NULL) &&
+ (completeWild->nsSet != NULL))) {
+
+ int nsFound, absentFound = 0;
+
+ if (completeWild->nsSet != NULL) {
+ cur = completeWild->nsSet;
+ curB = curWild->negNsSet;
+ } else {
+ cur = curWild->nsSet;
+ curB = completeWild->negNsSet;
+ }
+ nsFound = 0;
+ while (cur != NULL) {
+ if (cur->value == NULL)
+ absentFound = 1;
+ else if (cur->value == curB->value)
+ nsFound = 1;
+ if (nsFound && absentFound)
+ break;
+ cur = cur->next;
+ }
+
+ if (nsFound && absentFound) {
+ /*
+ * 5.1 If the set S includes both the negated namespace
+ * name and ·absent·, then any must be the value.
+ */
+ completeWild->any = 1;
+ if (completeWild->nsSet != NULL) {
+ xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
+ completeWild->nsSet = NULL;
+ }
+ if (completeWild->negNsSet != NULL) {
+ xmlFree(completeWild->negNsSet);
+ completeWild->negNsSet = NULL;
+ }
+ } else if (nsFound && (!absentFound)) {
+ /*
+ * 5.2 If the set S includes the negated namespace name
+ * but not ·absent·, then a pair of not and ·absent· must
+ * be the value.
+ */
+ if (completeWild->nsSet != NULL) {
+ xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
+ completeWild->nsSet = NULL;
+ }
+ if (completeWild->negNsSet == NULL) {
+ completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
+ if (completeWild->negNsSet == NULL)
+ return (-1);
+ }
+ completeWild->negNsSet->value = NULL;
+ } else if ((!nsFound) && absentFound) {
+ /*
+ * 5.3 If the set S includes ·absent· but not the negated
+ * namespace name, then the union is not expressible.
+ */
+ xmlSchemaPErr(ctxt, completeWild->node,
+ XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
+ "The union of the wilcard is not expressible\n",
+ NULL, NULL);
+ return(0);
+ } else if ((!nsFound) && (!absentFound)) {
+ /*
+ * 5.4 If the set S does not include either the negated namespace
+ * name or ·absent·, then whichever of O1 or O2 is a pair of not
+ * and a namespace name must be the value.
+ */
+ if (completeWild->negNsSet == NULL) {
+ if (completeWild->nsSet != NULL) {
+ xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
+ completeWild->nsSet = NULL;
+ }
+ completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
+ if (completeWild->negNsSet == NULL)
+ return (-1);
+ completeWild->negNsSet->value = curWild->negNsSet->value;
+ }
+ }
+ return (0);
+ }
+ /*
+ * 6.
+ */
+ if (((completeWild->negNsSet != NULL) &&
+ (completeWild->negNsSet->value == NULL) &&
+ (curWild->nsSet != NULL)) ||
+ ((curWild->negNsSet != NULL) &&
+ (curWild->negNsSet->value == NULL) &&
+ (completeWild->nsSet != NULL))) {
+
+ if (completeWild->nsSet != NULL) {
+ cur = completeWild->nsSet;
+ } else {
+ cur = curWild->nsSet;
+ }
+ while (cur != NULL) {
+ if (cur->value == NULL) {
+ /*
+ * 6.1 If the set S includes ·absent·, then any must be the
+ * value.
+ */
+ completeWild->any = 1;
+ if (completeWild->nsSet != NULL) {
+ xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
+ completeWild->nsSet = NULL;
+ }
+ if (completeWild->negNsSet != NULL) {
+ xmlFree(completeWild->negNsSet);
+ completeWild->negNsSet = NULL;
+ }
+ return (0);
+ }
+ cur = cur->next;
+ }
+ if (completeWild->negNsSet == NULL) {
+ /*
+ * 6.2 If the set S does not include ·absent·, then a pair of not
+ * and ·absent· must be the value.
+ */
+ if (completeWild->nsSet != NULL) {
+ xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
+ completeWild->nsSet = NULL;
+ }
+ completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
+ if (completeWild->negNsSet == NULL)
+ return (-1);
+ completeWild->negNsSet->value = NULL;
+ }
+ return (0);
+ }
+ return (0);
+
+}
+
+static int
+xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
+ xmlSchemaWildcardPtr completeWild,
+ xmlSchemaWildcardPtr curWild)
+{
+ xmlSchemaWildcardNsPtr cur, curB, prev, last = NULL, tmp;
+
+ /*
+ * 1 If O1 and O2 are the same value, then that value must be the
+ * value.
+ */
+ if ((completeWild->any == curWild->any) &&
+ ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
+ ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
+
+ if ((completeWild->negNsSet == NULL) ||
+ (completeWild->negNsSet->value == curWild->negNsSet->value)) {
+
+ if (completeWild->nsSet != NULL) {
+ int found;
+
+ /*
+ * Check equality of sets.
+ */
+ cur = completeWild->nsSet;
+ while (cur != NULL) {
+ found = 0;
+ curB = curWild->nsSet;
+ while (curB != NULL) {
+ if (cur->value == curB->value) {
+ found = 1;
+ break;
+ }
+ curB = curB->next;
+ }
+ if (!found)
+ break;
+ cur = cur->next;
+ }
+ if (found)
+ return(0);
+ } else
+ return(0);
+ }
+ }
+ /*
+ * 2 If either O1 or O2 is any, then the other must be the value.
+ */
+ if ((completeWild->any != curWild->any) && (completeWild->any)) {
+ if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
+ return(-1);
+ return(0);
+ }
+ /*
+ * 3 If either O1 or O2 is a pair of not and a value (a namespace
+ * name or ·absent·) and the other is a set of (namespace names or
+ * ·absent·), then that set, minus the negated value if it was in
+ * the set, minus ·absent· if it was in the set, must be the value.
+ */
+ if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
+ ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
+ const xmlChar *neg;
+
+ if (completeWild->nsSet == NULL) {
+ neg = completeWild->negNsSet->value;
+ if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
+ return(-1);
+ } else
+ neg = curWild->negNsSet->value;
+ /*
+ * Remove absent and negated.
+ */
+ prev = NULL;
+ cur = completeWild->nsSet;
+ while (cur != NULL) {
+ if (cur->value == NULL) {
+ if (prev == NULL)
+ completeWild->nsSet = cur->next;
+ else
+ prev->next = cur->next;
+ xmlFree(cur);
+ break;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if (neg != NULL) {
+ prev = NULL;
+ cur = completeWild->nsSet;
+ while (cur != NULL) {
+ if (cur->value == neg) {
+ if (prev == NULL)
+ completeWild->nsSet = cur->next;
+ else
+ prev->next = cur->next;
+ xmlFree(cur);
+ break;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ }
+
+ return(0);
+ }
+ /*
+ * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
+ * then the intersection of those sets must be the value.
+ */
+ if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
+ int found;
+
+ cur = completeWild->nsSet;
+ prev = NULL;
+ while (cur != NULL) {
+ found = 0;
+ curB = curWild->nsSet;
+ while (curB != NULL) {
+ if (cur->value == curB->value) {
+ found = 1;
+ break;
+ }
+ curB = curB->next;
+ }
+ if (!found) {
+ if (prev == NULL)
+ completeWild->nsSet = cur->next;
+ else
+ prev->next = cur->next;
+ tmp = cur->next;
+ xmlFree(cur);
+ cur = tmp;
+ continue;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+
+ return(0);
+ }
+ /* 5 If the two are negations of different namespace names,
+ * then the intersection is not expressible
+ */
+ if ((completeWild->negNsSet != NULL) &&
+ (curWild->negNsSet != NULL) &&
+ (completeWild->negNsSet->value != curWild->negNsSet->value) &&
+ (completeWild->negNsSet->value != NULL) &&
+ (curWild->negNsSet->value != NULL)) {
+
+ xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
+ "The intersection of the wilcard is not expressible\n",
+ NULL, NULL);
+ return(0);
+ }
+ /*
+ * 6 If the one is a negation of a namespace name and the other
+ * is a negation of ·absent·, then the one which is the negation
+ * of a namespace name must be the value.
+ */
+ if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
+ (completeWild->negNsSet->value != curWild->negNsSet->value) &&
+ (completeWild->negNsSet->value == NULL)) {
+ completeWild->negNsSet->value = curWild->negNsSet->value;
+ }
+ return(0);
+}
+
+
+static xmlSchemaWildcardPtr
+xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
+ xmlSchemaAttributePtr attrs,
+ xmlSchemaWildcardPtr completeWild)
+{
+ while (attrs != NULL) {
+ if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
+ xmlSchemaAttributeGroupPtr group;
+
+ group = (xmlSchemaAttributeGroupPtr) attrs;
+ if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
+ if (group->attributes != NULL) {
+ if (group->attributeWildcard != NULL)
+ xmlSchemaBuildCompleteAttributeWildcard(ctxt,
+ group->attributes, group->attributeWildcard);
+ else
+ group->attributeWildcard =
+ xmlSchemaBuildCompleteAttributeWildcard(ctxt,
+ group->attributes, group->attributeWildcard);
+ }
+ group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
+ }
+ if (group->attributeWildcard != NULL) {
+ if (completeWild == NULL) {
+ /*
+ * Copy the first encountered wildcard as context, except for the annotation.
+ */
+ completeWild = xmlSchemaAddWildcard(ctxt);
+ completeWild->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
+ if (!xmlSchemaCloneWildcardNsConstraints(ctxt,
+ &completeWild, group->attributeWildcard))
+ return(NULL);
+ completeWild->processContents = group->attributeWildcard->processContents;
+ /*
+ * Although the complete wildcard might not correspond to any
+ * node in the schema, we will save this context node.
+ */
+ completeWild->node = group->attributeWildcard->node;
+ return(completeWild);
+ }
+ if (xmlSchemaIntersectWildcards(ctxt, completeWild, group->attributeWildcard) == -1) {
+ xmlSchemaFreeWildcard(completeWild);
+ return(NULL);
+ }
+ }
+ }
+ attrs = attrs->next;
+ }
+
+ return (completeWild);
+}
+
+/**
+ * xmlSchemaMatchesWildcardNs:
+ * @wild: the wildcard
+ * @ns: the namespace
+ *
+ *
+ * Returns 1 if the given namespace matches the wildcard,
+ * 0 otherwise.
+ */
+static int
+xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
+{
+ if (wild == NULL)
+ return(0);
+
+ if (wild->any)
+ return(1);
+ else if (wild->nsSet != NULL) {
+ xmlSchemaWildcardNsPtr cur;
+
+ cur = wild->nsSet;
+ while (cur != NULL) {
+ if (xmlStrEqual(cur->value, ns))
+ return(1);
+ cur = cur->next;
+ }
+ } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
+ (!xmlStrEqual(wild->negNsSet->value, ns)))
+ return(1);
+
+ return(0);
+}
+
+/**
+ * xmlSchemaBuildAttributeValidation:
+ * @ctxt: the schema parser context
+ * @type: the complex type definition
+ *
+ *
+ * Builds the wildcard and the attribute uses on the given complex type.
+ * Returns -1 if an internal error occurs, 0 otherwise.
+ */
+static int
+xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
+{
+ xmlSchemaTypePtr baseType = NULL;
+ xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
+ lastUse = NULL, lastBaseUse;
+ xmlSchemaAttributePtr attrs;
+ int baseIsAnyType = 0;
+
+ /*
+ * Complex Type Definition with complex content Schema Component.
+ *
+ * Attribute uses.
+ */
+ if (type->attributeUses != NULL) {
+ xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaParseBuildAttributeUses: "
+ "attribute uses already builded.\n",
+ NULL, NULL);
+ return (-1);
+ }
+ if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) ||
+ (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
+ /*
+ * Inherit the attribute uses of the base type.
+ */
+ baseType = type->subtypes->subtypes->baseType;
+ /*
+ * TODO: URGENT: This is not nice, but currently
+ * xmlSchemaTypeAnyTypeDef is static in xmlschematypes.c.
+ */
+ if ((baseType->type == XML_SCHEMA_TYPE_BASIC) &&
+ xmlStrEqual(baseType->name, "anyType")) {
+ baseIsAnyType = 1;
+ }
+ /*
+ * TODO: Does the spec state that it is an error to "extend" the
+ * anyType?
+ */
+ if (!baseIsAnyType) {
+ if (baseType != NULL) {
+ for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
+ tmp = (xmlSchemaAttributeLinkPtr)
+ xmlMalloc(sizeof(xmlSchemaAttributeLink));
+ if (tmp == NULL) {
+ xmlSchemaPErrMemory(ctxt,
+ "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;
+ }
+ }
+ }
+ attrs = type->subtypes->subtypes->attributes;
+ /*
+ * Handle attribute wildcards.
+ */
+ type->attributeWildcard =
+ xmlSchemaBuildCompleteAttributeWildcard(ctxt,
+ attrs,
+ type->subtypes->subtypes->attributeWildcard);
+ if ((type->attributeWildcard != NULL) &&
+ (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard))
+ type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
+
+ if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
+ (baseType != NULL) && (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
+ (baseType->attributeWildcard != NULL)) {
+ if (type->attributeWildcard != NULL) {
+ /*
+ * Union the complete wildcard with the base wildcard.
+ */
+ if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
+ baseType->attributeWildcard) == -1)
+ return (-1);
+ } else {
+ /*
+ * Just inherit the wildcard.
+ */
+ type->attributeWildcard = baseType->attributeWildcard;
+ }
+ }
+ } else {
+ /*
+ * Although the complexType is implicitely derived by "restriction"
+ * from the ur-type, this is not (yet?) reflected by libxml2.
+ */
+ baseType = NULL;
+ attrs = type->attributes;
+ if (attrs != NULL)
+ type->attributeWildcard =
+ xmlSchemaBuildCompleteAttributeWildcard(ctxt, attrs, type->attributeWildcard);
+ }
+ /*
+ * Gather attribute uses defined by this type.
+ */
+ if (attrs != NULL) {
+ if (xmlSchemaBuildAttributeUsesOwned(ctxt, 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(xmlSchemaGetOnymousAttrName(cur->attr),
+ xmlSchemaGetOnymousAttrName(tmp->attr))) &&
+ (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr ),
+ xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) tmp->attr)))) {
+
+ xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_4,
+ "ct-props-correct.4: Duplicate attribute use with the name \"%s\" specified\n",
+ xmlSchemaGetOnymousAttrName(cur->attr), NULL);
+ break;
+ }
+ tmp = tmp->next;
+ }
+ cur = cur->next;
+ }
+ }
+ if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
+ /*
+ * Derive by restriction.
+ */
+ if (baseIsAnyType) {
+ type->attributeUses = uses;
+ } else {
+ int found;
+
+ cur = uses;
+ while (cur != NULL) {
+ found = 0;
+ base = type->attributeUses;
+ while (base != NULL) {
+ if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
+ xmlSchemaGetOnymousAttrName(base->attr))) &&
+ (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr),
+ xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) base->attr)))) {
+
+ found = 1;
+ if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
+ (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
+ /*
+ * derivation-ok-restriction 2.1.1
+ */
+ xmlSchemaPErr(ctxt, cur->attr->node,
+ XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
+ "derivation-ok-restriction.2.1.1: "
+ "The \"optional\" attribute "
+ "use \"%s\" is inconsistent with a matching "
+ "\"required\" attribute use of the base type\n",
+ xmlSchemaGetOnymousAttrName(cur->attr), NULL);
+ } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
+ (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
+ /*
+ * derivation-ok-restriction 3
+ */
+ xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
+ "derivation-ok-restriction.3: "
+ "The \"required\" attribute use \"%s\" of the base type "
+ "does not have a matching attribute use in the derived type\n",
+ xmlSchemaGetOnymousAttrName(cur->attr), NULL);
+
+ } else {
+ /*
+ * Override the attribute use.
+ */
+ base->attr = cur->attr;
+ }
+ /*
+ * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
+ */
+ break;
+ }
+ base = base->next;
+ }
+
+ if (!found) {
+ if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
+ /*
+ * derivation-ok-restriction 2.2
+ */
+ if ((type->attributeWildcard != NULL) &&
+ xmlSchemaMatchesWildcardNs(type->attributeWildcard,
+ cur->attr->targetNamespace))
+ found = 1;
+
+ if (!found) {
+ xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
+ "derivation-ok-restriction.2.2: "
+ "The attribute use \"%s\" has neither a matching attribute use, "
+ "nor a matching wildcard in the base type\n",
+ xmlSchemaGetOnymousAttrName(cur->attr), NULL);
+ } else {
+ /*
+ * Add the attribute use.
+ *
+ * Note that this may lead to funny derivation error reports, if
+ * multiple equal attribute uses exist; but this is not
+ * allowed anyway, and it will be reported beforehand.
+ */
+ tmp = cur;
+ if (prev != NULL)
+ prev->next = cur->next;
+ else
+ uses = cur->next;
+ cur = cur->next;
+ if (type->attributeUses == NULL) {
+ type->attributeUses = tmp;
+ } else
+ lastBaseUse->next = tmp;
+ lastBaseUse = tmp;
+
+ continue;
+ }
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if (uses != NULL)
+ xmlSchemaFreeAttributeUseList(uses);
+ }
+ } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
+ /*
+ * 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 (type->attributeUses == NULL) {
+ type->attributeUses = uses;
+ } else
+ lastBaseUse->next = uses;
+ }
+ } else {
+ /*
+ * Derive implicitely from the ur-type.
+ */
+ type->attributeUses = uses;
+}
+ /*
+ * 3.4.6 -> Complex Type Definition Properties Correct
+ */
+ if (type->attributeUses != NULL) {
+ cur = type->attributeUses;
+ prev = NULL;
+ while (cur != NULL) {
+ /*
+ * 4. Two distinct attribute declarations in the {attribute uses} must
+ * not have identical {name}s and {target namespace}s.
+ *
+ * Note that this was already done for "restriction" and types derived from
+ * the ur-type.
+ */
+ if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
+ tmp = cur->next;
+ while (tmp != NULL) {
+ if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
+ xmlSchemaGetOnymousAttrName(tmp->attr))) &&
+ (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr ),
+ xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) tmp->attr)))) {
+
+ xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_4,
+ "ct-props-correct.4: Duplicate attribute use with the name \"%s\" specified\n",
+ xmlSchemaGetOnymousAttrName(cur->attr), NULL);
+ break;
+ }
+ 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.
+ */
+ if ((cur->attr->subtypes != NULL) &&
+ /*
+ * TODO: FIXME: XML_SCHEMAS_ID should be used instead of "23" !!!,
+ * but the xmlSchemaValType is not made public yet.
+ */
+ (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, 23))) {
+ if (id != NULL) {
+ xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_5,
+ "ct-props-correct.5: Two attribute declarations, "
+ "\"%s\" and \"%s\" have types which derived from ID\n",
+ xmlSchemaGetOnymousAttrName(id->attr),
+ xmlSchemaGetOnymousAttrName(cur->attr));
+ }
+ 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;
+ }
+ }
+ }
+ /*
+ * TODO: This check should be removed if we are 100% sure of
+ * the base type attribute uses already being built.
+ */
+ if ((baseType != NULL) && (!baseIsAnyType) &&
+ (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
+ (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
+ xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaParseBuildAttributeUses: "
+ "attribute uses not builded on base type \"%s\".\n",
+ baseType->name, NULL);
+ }
+ return (0);
+}
+
+/**
* xmlSchemaTypeFixup:
* @typeDecl: the schema type definition
* @ctxt: the schema parser context
@@ -4809,16 +6278,21 @@
XML_SCHEMAP_UNKNOWN_BASE_TYPE,
"Schemas: type %s base type %s not found\n",
name, typeDecl->base);
+ } else if (baseType->contentType ==
+ XML_SCHEMA_CONTENT_UNKNOWN) {
+ /*
+ * The base type might be not "type fixed" yet,
+ * so do it now. */
+ /*
+ * TODO: Is a check for circular derivation already
+ * done?
+ */
+ xmlSchemaTypeFixup(baseType, ctxt, NULL);
}
typeDecl->baseType = baseType;
}
if (typeDecl->subtypes == NULL)
if (typeDecl->baseType != NULL) {
- /* The base type might be not "type fixed" yet,
- * so do it now. */
- if (typeDecl->baseType->contentType ==
- XML_SCHEMA_CONTENT_UNKNOWN)
- xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
typeDecl->contentType =
typeDecl->baseType->contentType;
} else
@@ -4858,6 +6332,16 @@
XML_SCHEMAP_UNKNOWN_BASE_TYPE,
"Schemas: type %s base type %s not found\n",
name, typeDecl->base);
+ } else if (baseType->contentType ==
+ XML_SCHEMA_CONTENT_UNKNOWN) {
+ /*
+ * The base type might be not "type fixed" yet,
+ * so do it now. */
+ /*
+ * TODO: Is a check for circular derivation already
+ * done?
+ */
+ xmlSchemaTypeFixup(baseType, ctxt, NULL);
}
typeDecl->baseType = baseType;
}
@@ -4891,6 +6375,7 @@
return;
}
if (typeDecl->recurse) {
+ /* TODO: The word "recursive" should be changed to "circular" here. */
xmlSchemaPErr(ctxt, typeDecl->node,
XML_SCHEMAP_UNKNOWN_BASE_TYPE,
"Schemas: extension type %s is recursive\n",
@@ -4923,20 +6408,35 @@
typeDecl->contentType =
XML_SCHEMA_CONTENT_MIXED;
} else {
- if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
+ if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
typeDecl->contentType =
XML_SCHEMA_CONTENT_MIXED;
- else {
+ } else {
xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
NULL);
if (typeDecl->subtypes != NULL)
typeDecl->contentType =
typeDecl->subtypes->contentType;
}
- if (typeDecl->attributes == NULL)
- typeDecl->attributes =
- typeDecl->subtypes->attributes;
+ /* Evaluate the derivation method. */
+ if ((typeDecl->subtypes != NULL) &&
+ ((typeDecl->subtypes->type ==
+ XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
+ (typeDecl->subtypes->type ==
+ XML_SCHEMA_TYPE_SIMPLE_CONTENT)) &&
+ (typeDecl->subtypes->subtypes != NULL)) {
+ if (typeDecl->subtypes->subtypes->type ==
+ XML_SCHEMA_TYPE_EXTENSION) {
+ typeDecl->flags |=
+ XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
+ } else if (typeDecl->subtypes->subtypes->type ==
+ XML_SCHEMA_TYPE_RESTRICTION) {
+ typeDecl->flags |=
+ XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
}
+ }
+ }
+ xmlSchemaBuildAttributeValidation(ctxt, typeDecl);
break;
}
case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
@@ -4946,19 +6446,24 @@
typeDecl->contentType =
XML_SCHEMA_CONTENT_MIXED;
} else {
- if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
+ if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
typeDecl->contentType =
XML_SCHEMA_CONTENT_MIXED;
- else {
+ } else {
xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
NULL);
if (typeDecl->subtypes != NULL)
typeDecl->contentType =
typeDecl->subtypes->contentType;
}
+ /*
+ * Removed due to implementation of the build of attribute uses.
+ */
+ /*
if (typeDecl->attributes == NULL)
typeDecl->attributes =
typeDecl->subtypes->attributes;
+ */
}
break;
}
@@ -4968,6 +6473,13 @@
case XML_SCHEMA_TYPE_CHOICE:
typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
break;
+ case XML_SCHEMA_TYPE_LIST:
+ xmlSchemaParseListRefFixup(typeDecl, ctxt);
+ /* no break on purpose */
+ case XML_SCHEMA_TYPE_UNION:
+ if (typeDecl->type == XML_SCHEMA_TYPE_UNION)
+ xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
+ /* no break on purpose */
case XML_SCHEMA_TYPE_BASIC:
case XML_SCHEMA_TYPE_ANY:
case XML_SCHEMA_TYPE_FACET:
@@ -4978,10 +6490,6 @@
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
case XML_SCHEMA_TYPE_NOTATION:
- case XML_SCHEMA_TYPE_LIST:
- xmlSchemaParseListRefFixup(typeDecl, ctxt);
- case XML_SCHEMA_TYPE_UNION:
- xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
case XML_SCHEMA_FACET_MININCLUSIVE:
case XML_SCHEMA_FACET_MINEXCLUSIVE:
case XML_SCHEMA_FACET_MAXINCLUSIVE:
@@ -5209,32 +6717,39 @@
* Fixes finish doing the computations on the attributes definitions
*/
static void
-xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
+xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
{
if (name == NULL)
- name = attrgrpDecl->name;
- if (attrgrpDecl->attributes != NULL)
+ name = attrgrp->name;
+ if (attrgrp->attributes != NULL)
return;
- if (attrgrpDecl->ref != NULL) {
+ if (attrgrp->ref != NULL) {
xmlSchemaAttributeGroupPtr ref;
- ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
- attrgrpDecl->refNs);
+ ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref, attrgrp->refNs);
if (ref == NULL) {
- xmlSchemaPErr(ctxt, attrgrpDecl->node,
+ xmlSchemaPErr(ctxt, attrgrp->node,
XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
"Schemas: attribute group %s reference %s not found\n",
- name, attrgrpDecl->ref);
+ name, attrgrp->ref);
return;
}
xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
- attrgrpDecl->attributes = ref->attributes;
- } else {
- xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
- "Schemas: attribute %s has no attributes nor reference\n",
+ attrgrp->attributes = ref->attributes;
+ attrgrp->attributeWildcard = ref->attributeWildcard;
+ }
+ /*
+ * Removed, since a global attribute group does not need to hold any
+ * attributes or wildcard
+ */
+ /*
+ else {
+ xmlSchemaPErr(ctxt, attrgrp->node, XML_SCHEMAP_NOATTR_NOREF,
+ "Schemas: attribute group %s has no attributes nor reference\n",
name, NULL);
}
+ */
}
/**
@@ -5267,8 +6782,7 @@
} else if (attrDecl->ref != NULL) {
xmlSchemaAttributePtr ref;
- ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
- attrDecl->refNs);
+ ref = xmlSchemaGetAttribute(ctxt->schema, attrDecl->ref, attrDecl->refNs);
if (ref == NULL) {
xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
"Schemas: attribute %s reference %s not found\n",
@@ -5277,7 +6791,7 @@
}
xmlSchemaAttrFixup(ref, ctxt, NULL);
attrDecl->subtypes = ref->subtypes;
- } else if (attrDecl->type != XML_SCHEMA_TYPE_ANY_ATTRIBUTE) {
+ } else {
xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
"Schemas: attribute %s has no type nor reference\n",
name, NULL);
@@ -5785,12 +7299,31 @@
xmlNodePtr node);
static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
xmlNodePtr elem,
- xmlSchemaAttributePtr attributes);
+ xmlSchemaTypePtr type);
static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
xmlNodePtr elem,
xmlSchemaElementPtr elemDecl,
xmlSchemaTypePtr type);
+
+/**
+ * xmlSchemaFreeAttrStates:
+ * @state: a list of attribute states
+ *
+ * Free the given list of attribute states
+ *
+ */
+static void
+xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
+{
+ xmlSchemaAttrStatePtr tmp;
+ while (state != NULL) {
+ tmp = state;
+ state = state->next;
+ xmlFree(tmp);
+ }
+}
+
/**
* xmlSchemaRegisterAttributes:
* @ctxt: a schema validation context
@@ -5803,29 +7336,30 @@
static int
xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
{
+ xmlSchemaAttrStatePtr tmp;
+
+ ctxt->attr = NULL;
+ ctxt->attrTop = NULL;
while (attrs != NULL) {
if ((attrs->ns != NULL) &&
(xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
attrs = attrs->next;
continue;
}
- if (ctxt->attrNr >= ctxt->attrMax) {
- xmlSchemaAttrStatePtr tmp;
-
- ctxt->attrMax *= 2;
tmp = (xmlSchemaAttrStatePtr)
- xmlRealloc(ctxt->attr, ctxt->attrMax *
- sizeof(xmlSchemaAttrState));
+ xmlMalloc(sizeof(xmlSchemaAttrState));
if (tmp == NULL) {
xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
- ctxt->attrMax /= 2;
return (-1);
}
+ tmp->attr = attrs;
+ tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
+ tmp->next = NULL;
+ if (ctxt->attr == NULL)
ctxt->attr = tmp;
- }
- ctxt->attr[ctxt->attrNr].attr = attrs;
- ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
- ctxt->attrNr++;
+ else
+ ctxt->attrTop->next = tmp;
+ ctxt->attrTop = tmp;
attrs = attrs->next;
}
return (0);
@@ -5845,18 +7379,38 @@
xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
{
int ret = 0;
- int i;
+ xmlSchemaAttrStatePtr cur;
- for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
- if (ctxt->attr[i].attr == NULL)
- break;
- if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
+ cur = ctxt->attr;
+ while ((cur != NULL) && (cur != ctxt->attrTop->next)) {
+ if (cur->state != XML_SCHEMAS_ATTR_CHECKED) {
ret = 1;
+ if (cur->state == XML_SCHEMAS_ATTR_UNKNOWN)
xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
"Attribute %s on %s is unknown\n",
- ctxt->attr[i].attr->name, node->name);
+ cur->attr->name, node->name);
+ else if (cur->state == XML_SCHEMAS_ATTR_PROHIBITED)
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
+ "Attribute %s on %s is prohibited\n",
+ cur->attr->name, node->name);
+ else if (cur->state == XML_SCHEMAS_ATTR_INVALID_VALUE)
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRINVALID,
+ "Attribute %s on %s does not match type\n",
+ cur->attr->name, node->name);
+ else if (cur->state == XML_SCHEMAS_ATTR_MISSING) {
+ if (cur->decl->ref != NULL)
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
+ "Attribute %s on %s is required but missing\n",
+ cur->decl->ref, node->name);
+ else
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
+ "Attribute %s on %s is required but missing\n",
+ cur->decl->name, node->name);
}
}
+ cur = cur->next;
+ }
+
return (ret);
}
@@ -5903,10 +7457,16 @@
ret =
xmlSchemaValidateFacets(ctxt, base, facet, value);
}
- if ((ret == 0) && (type->attributes != NULL)) {
+ /*
+ * This should attempt to validate the attributes even
+ * when validation of the value failed.
+ */
+ /*
+ if (type->attributes != NULL) {
ret = xmlSchemaValidateAttributes(ctxt, node,
type->attributes);
}
+ */
break;
}
case XML_SCHEMA_TYPE_EXTENSION:{
@@ -6159,10 +7719,12 @@
ret =
xmlSchemaValidateFacets(ctxt, base, facet, value);
}
+ /* Removed due to changes of attribute validation:
if ((ret == 0) && (variety->attributes != NULL)) {
ret = xmlSchemaValidateAttributes(ctxt, node,
variety->attributes);
}
+ */
break;
}
case XML_SCHEMA_TYPE_LIST:
@@ -6207,7 +7769,17 @@
xmlSchemaTypePtr type;
xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
xmlSchemaElementPtr decl;
- int ret, attrBase;
+ int ret;
+ xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
+
+ /*
+ * TODO: Look into "xmlSchemaValidateElement" for missing parts, which should
+ * go in here as well.
+ */
+
+ /* TODO: Is this one called always with an element declaration as the
+ * context's type?
+ */
oldregexp = ctxt->regexp;
@@ -6241,10 +7813,18 @@
/*
* Verify the attributes
*/
- attrBase = ctxt->attrBase;
- ctxt->attrBase = ctxt->attrNr;
+
+ attrs = ctxt->attr;
+ attrTop = ctxt->attrTop;
+
xmlSchemaRegisterAttributes(ctxt, child->properties);
- xmlSchemaValidateAttributes(ctxt, child, type->attributes);
+
+ /*
+ * An element declaration does not hold any information about
+ * attributes; thus, the following was removed.
+ */
+ /* xmlSchemaValidateAttributes(ctxt, child, type->attributes); */
+
/*
* Verify the element content recursively
*/
@@ -6289,11 +7869,11 @@
* Verify that all attributes were Schemas-validated
*/
xmlSchemaCheckAttributes(ctxt, node);
- ctxt->attrNr = ctxt->attrBase;
- ctxt->attrBase = attrBase;
-
+ if (ctxt->attr != NULL)
+ xmlSchemaFreeAttributeStates(ctxt->attr);
+ ctxt->attr = attrs;
+ ctxt->attrTop = attrTop;
ctxt->regexp = oldregexp;
-
ctxt->node = child;
ctxt->type = type;
return (ctxt->err);
@@ -6407,6 +7987,8 @@
xmlSchemaTypePtr type, subtype;
int ret;
+ /* TODO: Handle xsd:restriction & xsd:extension */
+
child = ctxt->node;
type = ctxt->type;
ctxt->cur = node;
@@ -6419,9 +8001,11 @@
"Element %s is supposed to be empty\n",
node->name, NULL);
}
+ /* Removed due to changes of attribute validation:
if (type->attributes != NULL) {
xmlSchemaValidateAttributes(ctxt, node, type->attributes);
}
+ */
subtype = type->subtypes;
while (subtype != NULL) {
ctxt->type = subtype;
@@ -6435,6 +8019,8 @@
/*
* Skip ignorable nodes in that context
*/
+ /* ComplexType, ComplexContent */
+ if (child != NULL) {
child = xmlSchemaSkipIgnored(ctxt, type, child);
while (child != NULL) {
if (child->type == XML_ELEMENT_NODE) {
@@ -6455,16 +8041,19 @@
*/
child = xmlSchemaSkipIgnored(ctxt, type, child);
}
+ }
+
if (((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
(type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS)) &&
(type->subtypes != NULL)) {
TODO
}
-
+ /* Removed due to changes of attribute validation:
if (type->attributes != NULL) {
xmlSchemaValidateAttributes(ctxt, node, type->attributes);
}
+ */
break;
case XML_SCHEMA_CONTENT_BASIC:{
if (type->subtypes != NULL) {
@@ -6477,18 +8066,20 @@
xmlSchemaValidateBasicType(ctxt, node);
else if (type->baseType->type == XML_SCHEMA_TYPE_COMPLEX)
xmlSchemaValidateComplexType(ctxt, node);
+ /* TODO: This might be incorrect. */
else if (type->baseType->type == XML_SCHEMA_TYPE_SIMPLE)
xmlSchemaValidateSimpleType(ctxt, node);
else
xmlGenericError(xmlGenericErrorContext,
"unexpected content type of base: %d\n",
type->contentType);
-
}
+ /* Removed due to changes of attribute validation:
if (type->attributes != NULL) {
xmlSchemaValidateAttributes(ctxt, node,
type->attributes);
}
+ */
ctxt->type = type;
break;
}
@@ -6501,10 +8092,12 @@
ctxt->type = type->baseType;
xmlSchemaValidateComplexType(ctxt, node);
}
+ /* Removed due to changes of attribute validation:
if (type->attributes != NULL) {
xmlSchemaValidateAttributes(ctxt, node,
type->attributes);
}
+ */
ctxt->type = type;
break;
}
@@ -6513,6 +8106,8 @@
"unimplemented content type %d\n",
type->contentType);
}
+ if (type->type == XML_SCHEMA_TYPE_COMPLEX)
+ xmlSchemaValidateAttributes(ctxt, node, type);
return (ctxt->err);
}
@@ -6537,7 +8132,10 @@
type = ctxt->type;
ctxt->cur = node;
- xmlSchemaValidateAttributes(ctxt, node, type->attributes);
+ /*
+ * Removed, since redundant.
+ */
+ /* xmlSchemaValidateAttributes(ctxt, node, type->attributes); */
ctxt->cur = node;
switch (type->type) {
@@ -6633,7 +8231,10 @@
case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
TODO break;
}
- xmlSchemaValidateAttributes(ctxt, node, type->attributes);
+ /*
+ * Removed, since redundant.
+ */
+ /* xmlSchemaValidateAttributes(ctxt, node, type->attributes); */
if (ctxt->node == NULL)
return (ctxt->err);
@@ -6662,6 +8263,10 @@
if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
return (0);
+ /* This one is called by "xmlSchemaValidateElementType" and
+ * "xmlSchemaValidateElement".
+ */
+
/*
* 3.3.4 : 2
*/
@@ -6711,7 +8316,9 @@
ctxt->type = elemDecl->subtypes;
ctxt->node = elem->children;
xmlSchemaValidateContent(ctxt, elem);
- xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
+ /* Removed, since an element declaration does not hold any attribute
+ * declarations */
+ /* xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes); */
return (ctxt->err);
}
@@ -6721,7 +8328,7 @@
* xmlSchemaValidateAttributes:
* @ctxt: a schema validation context
* @elem: an element
- * @attributes: the list of attribute declarations
+ * @type: the complexType holding the attribute uses
*
* Validate the attributes of an element.
*
@@ -6729,44 +8336,68 @@
* number otherwise and -1 in case of internal or API error.
*/
static int
-xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
- xmlSchemaAttributePtr attributes)
+xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
{
- int i, ret;
- xmlAttrPtr attr;
+ int ret;
+ xmlAttrPtr attr; /* An attribute on the element. */
xmlChar *value;
- xmlSchemaAttributeGroupPtr group = NULL;
+ xmlSchemaAttributeLinkPtr attrUse;
+ xmlSchemaAttributePtr attrDecl;
int found;
+ xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop;
+#ifdef DEBUG_ATTR_VALIDATION
+ int redundant = 0;
+#endif
+ if (type->type != XML_SCHEMA_TYPE_COMPLEX) {
+ xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateAttributes: "
+ "given type \"%s\"is not a complexType\n",
+ type->name, NULL);
+ return(-1);
+ }
- if (attributes == NULL)
+ if ((type->attributeUses == NULL) && (type->attributeWildcard == NULL))
return (0);
- while (attributes != NULL) {
+
+ attrUse = type->attributeUses;
+
+ while (attrUse != NULL) {
found = 0;
- /*
- * Handle attribute groups
- */
- if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
- group = (xmlSchemaAttributeGroupPtr) attributes;
- xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
- attributes = group->next;
- continue;
+ attrDecl = attrUse->attr;
+#ifdef DEBUG_ATTR_VALIDATION
+ printf("attr use - name: %s\n", xmlSchemaGetOnymousAttrName(attrDecl));
+ printf("attr use - use: %d\n", attrDecl->occurs);
+#endif
+ for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
+
+ if (curState->decl == attrUse->attr) {
+#ifdef DEBUG_ATTR_VALIDATION
+ redundant = 1;
+#endif
}
- for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
- attr = ctxt->attr[i].attr;
+ attr = curState->attr;
+#ifdef DEBUG_ATTR_VALIDATION
+ printf("attr - name: %s\n", attr->name);
+ if (attr->ns != NULL)
+ printf("attr - ns: %s\n", attr->ns->href);
+ else
+ printf("attr - ns: none\n");
+#endif
+ /* TODO: Can this ever happen? */
if (attr == NULL)
continue;
- if (attributes->ref != NULL) {
- if (!xmlStrEqual(attr->name, attributes->ref))
+ if (attrDecl->ref != NULL) {
+ if (!xmlStrEqual(attr->name, attrDecl->ref))
continue;
if (attr->ns != NULL) {
- if ((attributes->refNs == NULL) ||
- (!xmlStrEqual(attr->ns->href, attributes->refNs)))
+ if ((attrDecl->refNs == NULL) ||
+ (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
continue;
- } else if (attributes->refNs != NULL) {
+ } else if (attrDecl->refNs != NULL) {
continue;
}
} else {
- if (!xmlStrEqual(attr->name, attributes->name))
+ if (!xmlStrEqual(attr->name, attrDecl->name))
continue;
/*
* handle the namespaces checks here
@@ -6776,7 +8407,7 @@
* accept an unqualified attribute only if the target
* namespace of the declaration is absent.
*/
- if (attributes->targetNamespace != NULL)
+ if (attrDecl->targetNamespace != NULL)
/*
* This check was removed, since the target namespace
* was evaluated during parsing and already took
@@ -6785,57 +8416,139 @@
/* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
continue;
} else {
- if (attributes->targetNamespace == NULL)
+ if (attrDecl->targetNamespace == NULL)
continue;
- if (!xmlStrEqual(attributes->targetNamespace,
+ if (!xmlStrEqual(attrDecl->targetNamespace,
attr->ns->href))
continue;
}
}
+#ifdef DEBUG_ATTR_VALIDATION
+ printf("found\n");
+#endif
found = 1;
- ctxt->cur = (xmlNodePtr) attributes;
+ ctxt->cur = (xmlNodePtr) attrDecl;
- if (attributes->subtypes == NULL) {
+ if (attrDecl->subtypes == NULL) {
+ curState->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
+ curState->decl = attrDecl;
+ /*
+ * This could be put into "xmlSchemaCheckAttributes" as well, but
+ * since it reports an internal error, it better stays here to ease
+ * debugging.
+ */
xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL,
"Internal error: attribute %s type not resolved\n",
attr->name, NULL);
continue;
}
-
- if (attributes->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
- xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INVALIDATTR,
- "attribute %s on %s is prohibited\n",
- attributes->name, elem->name);
- /* Setting the state to XML_SCHEMAS_ATTR_CHECKED seems
- * not very logical but it suppresses the
- * "attribute is unknown" error report. Please change
- * this if you know better */
- ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
- break;
- }
-
value = xmlNodeListGetString(elem->doc, attr->children, 1);
- ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
+ ret = xmlSchemaValidateSimpleValue(ctxt, attrDecl->subtypes,
value);
- if (ret != 0) {
- xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
- XML_SCHEMAS_ERR_ATTRINVALID,
- "attribute %s on %s does not match type\n",
- attr->name, elem->name);
- } else {
- ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
- }
+ if (ret != 0)
+ curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
+ else
+ curState->state = XML_SCHEMAS_ATTR_CHECKED;
+ curState->decl = attrDecl;
if (value != NULL) {
xmlFree(value);
+ }
+ }
+ if ((!found) && (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
+ xmlSchemaAttrStatePtr tmp;
+
+#ifdef DEBUG_ATTR_VALIDATION
+ printf("required attr not found\n");
+#endif
+ /*
+ * Add a new dummy attribute state.
+ */
+ tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
+ if (tmp == NULL) {
+ xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
+ return (-1);
+ }
+ tmp->attr = NULL;
+ tmp->state = XML_SCHEMAS_ATTR_MISSING;
+ tmp->decl = attrDecl;
+ tmp->next = NULL;
+
+ if (reqAttrStates == NULL) {
+ reqAttrStates = tmp;
+ reqAttrStatesTop = tmp;
+ } else {
+ reqAttrStatesTop->next = tmp;
+ reqAttrStatesTop = tmp;
}
- }
- if ((!found) && (attributes->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
- xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_MISSING,
- "required attribute %s on %s is missing\n",
- attributes->name, elem->name);
- }
- attributes = attributes->next;
+
+ }
+ attrUse = attrUse->next;
}
+ /*
+ * Add required attributes to the attribute states of the context.
+ */
+ if (reqAttrStates != NULL) {
+ if (ctxt->attr == NULL) {
+ ctxt->attr = reqAttrStates;
+ } else {
+ ctxt->attrTop->next = reqAttrStates;
+ }
+ ctxt->attrTop = reqAttrStatesTop;
+ }
+ /*
+ * Process wildcards.
+ */
+ if (type->attributeWildcard != NULL) {
+#ifdef DEBUG_ATTR_VALIDATION
+ xmlSchemaWildcardNsPtr ns;
+ printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
+ if (type->attributeWildcard->any)
+ printf("type: any\n");
+ else if (type->attributeWildcard->negNsSet != NULL) {
+ printf("type: negated\n");
+ if (type->attributeWildcard->negNsSet->value == NULL)
+ printf("ns: (absent)\n");
+ else
+ printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
+ } else if (type->attributeWildcard->nsSet != NULL) {
+ printf("type: set\n");
+ ns = type->attributeWildcard->nsSet;
+ while (ns != NULL) {
+ if (ns->value == NULL)
+ printf("ns: (absent)\n");
+ else
+ printf("ns: %s\n", ns->value);
+ ns = ns->next;
+ }
+ } else
+ printf("empty\n");
+
+#endif
+ /*
+ * TODO: Implement processContents.
+ */
+ curState = ctxt->attr;
+ while (curState != NULL) {
+ if ((curState->state == XML_SCHEMAS_ATTR_UNKNOWN) &&
+ (curState->attr != NULL)) {
+ if (curState->attr->ns != NULL) {
+ if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
+ curState->attr->ns->href))
+ curState->state = XML_SCHEMAS_ATTR_CHECKED;
+ } else if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
+ NULL))
+ curState->state = XML_SCHEMAS_ATTR_CHECKED;
+ }
+ curState = curState->next;
+ }
+ }
+
+#ifdef DEBUG_ATTR_VALIDATION
+ if (redundant)
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlSchemaValidateAttributes: redundant call by type: %s\n",
+ type->name);
+#endif
return (ctxt->err);
}
@@ -6853,7 +8566,8 @@
xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
{
xmlSchemaElementPtr elemDecl;
- int ret, attrBase;
+ int ret;
+ xmlSchemaAttrStatePtr attrs, attrTop;
if (elem->ns != NULL) {
elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
@@ -6895,10 +8609,9 @@
/*
* Verify the attributes
*/
- attrBase = ctxt->attrBase;
- ctxt->attrBase = ctxt->attrNr;
+ attrs = ctxt->attr;
+ attrTop = ctxt->attrTop;
xmlSchemaRegisterAttributes(ctxt, elem->properties);
- xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
/*
* Verify the element content recursively
*/
@@ -6939,8 +8652,10 @@
* Verify that all attributes were Schemas-validated
*/
xmlSchemaCheckAttributes(ctxt, elem);
- ctxt->attrNr = ctxt->attrBase;
- ctxt->attrBase = attrBase;
+ if (ctxt->attr != NULL)
+ xmlSchemaFreeAttributeStates(ctxt->attr);
+ ctxt->attr = attrs;
+ ctxt->attrTop = attrTop;
return (ctxt->err);
}
@@ -6974,22 +8689,27 @@
else
elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
root->name, NULL, NULL);
+
/*
* special case whe elementFormDefault is unqualified for top-level elem.
*/
+ /* Removed, since elementFormDefault does not apply to top level
+ * elements */
+ /*
if ((elemDecl == NULL) && (root->ns != NULL) &&
(xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
root->name, NULL, NULL);
}
+ */
if (elemDecl == NULL) {
xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM,
"Element %s not declared\n", root->name, NULL);
- } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
+ } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
- "Root element %s not toplevel\n", root->name, NULL);
+ "Root element %s not global\n", root->name, NULL);
}
/*
* Okay, start the recursive validation
@@ -7031,8 +8751,17 @@
}
memset(ret, 0, sizeof(xmlSchemaValidCtxt));
ret->schema = schema;
- ret->attrNr = 0;
- ret->attrMax = 10;
+ /*
+ * Removed due to changes of the attribute state list.
+ /*
+ /* ret->attrNr = 0; */
+ /* ret->attrMax = 10; */
+ /* ret->attrBase = NULL; */
+ ret->attrTop = NULL;
+ ret->attr = NULL;
+ /*
+ * Removed due to changes of the attribute state list.
+ /*
ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
sizeof
(xmlSchemaAttrState));
@@ -7042,6 +8771,8 @@
return (NULL);
}
memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
+ */
+
return (ret);
}
@@ -7057,7 +8788,7 @@
if (ctxt == NULL)
return;
if (ctxt->attr != NULL)
- xmlFree(ctxt->attr);
+ xmlSchemaFreeAttributeStates(ctxt->attr);
if (ctxt->value != NULL)
xmlSchemaFreeValue(ctxt->value);
xmlFree(ctxt);