summaryrefslogtreecommitdiff
path: root/xmlschemas.c
diff options
context:
space:
mode:
authorMike Hommey <mh@glandium.org>2004-07-06 12:57:17 +0000
committerMike Hommey <mh@glandium.org>2004-07-06 12:57:17 +0000
commitc14c53a3645d81281058d4bb4cff24fa8d6faf33 (patch)
tree29bccc2e7499af078a3d1cdcfb517a1dee891be5 /xmlschemas.c
parentd4e028c96af89ade493b440d4f2de6b684c03a06 (diff)
downloadlibxml2-c14c53a3645d81281058d4bb4cff24fa8d6faf33.tar.gz
Load /tmp/tmp.DIvcnD/libxml2-2.6.11 intoupstream/2.6.11
packages/libxml2/branches/upstream/current.
Diffstat (limited to 'xmlschemas.c')
-rw-r--r--xmlschemas.c5723
1 files changed, 4961 insertions, 762 deletions
diff --git a/xmlschemas.c b/xmlschemas.c
index e9dfadb..59cfee0 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -12,6 +12,9 @@
* - when types are redefined in includes, check that all
* types in the redef list are equal
* -> need a type equality operation.
+ * - if we don't intend to use the schema for schemas, we
+ * need to validate all schema attributes (ref, type, name)
+ * against their types.
*/
#define IN_LIBXML
#include "libxml.h"
@@ -42,6 +45,8 @@
/* #define DEBUG_AUTOMATA 1 */
+/* #define DEBUG_ATTR_VALIDATION 1 */
+
#define UNBOUNDED (1 << 30)
#define TODO \
xmlGenericError(xmlGenericErrorContext, \
@@ -100,17 +105,25 @@ struct _xmlSchemaParserCtxt {
xmlDictPtr dict; /* dictionnary for interned string names */
int includes; /* the inclusion level, 0 for root or imports */
+ xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
+ xmlSchemaTypePtr parentItem; /* The current parent schema item */
};
#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 +156,9 @@ struct _xmlSchemaValidCtxt {
xmlRegExecCtxtPtr regexp;
xmlSchemaValPtr value;
- int attrNr;
- int attrBase;
- int attrMax;
+ xmlSchemaAttrStatePtr attrTop;
+ /* xmlSchemaAttrStatePtr attrBase; */
+ /* int attrMax; */
xmlSchemaAttrStatePtr attr;
};
@@ -176,18 +189,32 @@ struct _xmlSchemaInclude {
* Some predeclarations *
* *
************************************************************************/
+#if 0 /* Not currently used. */
static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
xmlSchemaTypePtr type,
const xmlChar * value);
+#endif
static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaPtr schema,
xmlNodePtr node);
+#if 0
static int
xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
xmlSchemaTypePtr type,
const xmlChar * value,
int fireErrors);
+#endif /* Not currently used. */
+static void
+xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
+ xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
+static const char *
+xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
+static int
+xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
+ const xmlChar *value,
+ int fireErrors,
+ int applyFacets);
/************************************************************************
* *
@@ -266,6 +293,50 @@ xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
}
+
+/**
+ * xmlSchemaPErrExt:
+ * @ctxt: the parsing context
+ * @node: the context node
+ * @error: the error code
+ * @strData1: extra data
+ * @strData2: extra data
+ * @strData3: extra data
+ * @msg: the message
+ * @str1: extra parameter for the message display
+ * @str2: extra parameter for the message display
+ * @str3: extra parameter for the message display
+ * @str4: extra parameter for the message display
+ * @str5: extra parameter for the message display
+ *
+ * Handle a parser error
+ */
+static void
+xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
+ const xmlChar * strData1, const xmlChar * strData2,
+ const xmlChar * strData3, const char *msg, const xmlChar * str1,
+ const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
+ const xmlChar * str5)
+{
+
+ xmlGenericErrorFunc channel = NULL;
+ xmlStructuredErrorFunc schannel = NULL;
+ void *data = NULL;
+
+ if (ctxt != NULL) {
+ ctxt->nberrors++;
+ channel = ctxt->error;
+ data = ctxt->userData;
+ schannel = ctxt->serror;
+ }
+ __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
+ error, XML_ERR_ERROR, NULL, 0,
+ (const char *) strData1, (const char *) strData2,
+ (const char *) strData3, 0, 0, msg, str1, str2,
+ str3, str4, str5);
+}
+
+
/**
* xmlSchemaVTypeErrMemory:
* @node: a context node
@@ -524,6 +595,44 @@ xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
}
/**
+ * xmlSchemaFreeWildcardNsSet:
+ * set: a schema wildcard namespace
+ *
+ * Deallocates a list of wildcard constraint structures.
+ */
+static void
+xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
+{
+ xmlSchemaWildcardNsPtr next;
+
+ while (set != NULL) {
+ next = set->next;
+ xmlFree(set);
+ set = next;
+ }
+}
+
+/**
+ * xmlSchemaFreeWildcard:
+ * @wildcard: a wildcard structure
+ *
+ * Deallocates a wildcard structure.
+ */
+void
+xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
+{
+ if (wildcard == NULL)
+ return;
+ if (wildcard->annot != NULL)
+ xmlSchemaFreeAnnot(wildcard->annot);
+ if (wildcard->nsSet != NULL)
+ xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
+ if (wildcard->negNsSet != NULL)
+ xmlFree(wildcard->negNsSet);
+ xmlFree(wildcard);
+}
+
+/**
* xmlSchemaFreeAttributeGroup:
* @schema: a schema attribute group structure
*
@@ -534,10 +643,52 @@ xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
{
if (attr == NULL)
return;
+ if (attr->annot != NULL)
+ xmlSchemaFreeAnnot(attr->annot);
+ if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
+ (attr->attributeWildcard != NULL))
+ xmlSchemaFreeWildcard(attr->attributeWildcard);
+
xmlFree(attr);
}
/**
+ * xmlSchemaFreeAttributeUseList:
+ * @attrUse: an attribute link
+ *
+ * Deallocate a list of schema attribute uses.
+ */
+static void
+xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
+{
+ xmlSchemaAttributeLinkPtr next;
+
+ while (attrUse != NULL) {
+ next = attrUse->next;
+ xmlFree(attrUse);
+ attrUse = next;
+ }
+}
+
+/**
+ * xmlSchemaFreeTypeLinkList:
+ * @alink: a type link
+ *
+ * Deallocate a list of types.
+ */
+static void
+xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
+{
+ xmlSchemaTypeLinkPtr next;
+
+ while (link != NULL) {
+ next = link->next;
+ xmlFree(link);
+ link = next;
+ }
+}
+
+/**
* xmlSchemaFreeElement:
* @schema: a schema element structure
*
@@ -598,6 +749,29 @@ xmlSchemaFreeType(xmlSchemaTypePtr type)
facet = next;
}
}
+ if (type->type != XML_SCHEMA_TYPE_BASIC) {
+ if (type->attributeUses != NULL)
+ xmlSchemaFreeAttributeUseList(type->attributeUses);
+ /* TODO: There must be a way more simple than this. */
+ 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);
+ }
+ }
+ if (type->memberTypes != NULL)
+ xmlSchemaFreeTypeLinkList(type->memberTypes);
+ if (type->facetSet != NULL) {
+ xmlSchemaFacetLinkPtr next, link;
+
+ link = type->facetSet;
+ do {
+ next = link->next;
+ xmlFree(link);
+ link = next;
+ } while (link != NULL);
+ }
xmlFree(type);
}
@@ -689,16 +863,14 @@ xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
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)
@@ -830,7 +1002,7 @@ xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
fprintf(output, "mixed ");
break;
case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
- fprintf(output, "mixed_or_elems ");
+ /* not used. */
break;
case XML_SCHEMA_CONTENT_BASIC:
fprintf(output, "basic ");
@@ -909,6 +1081,36 @@ xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
* *
************************************************************************/
+static xmlAttrPtr
+xmlSchemaGetPropNode(xmlNodePtr node, const xmlChar *name)
+{
+ xmlAttrPtr prop;
+
+ if ((node == NULL) || (name == NULL)) return(NULL);
+ prop = node->properties;
+ while (prop != NULL) {
+ if ((xmlStrEqual(prop->name, name)) &&
+ (prop->ns == NULL))
+ return(prop);
+ prop = prop->next;
+ }
+ return (NULL);
+}
+
+static const xmlChar *
+xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlChar *val;
+ const xmlChar *ret;
+
+ val = xmlNodeGetContent(node);
+ if (val == NULL)
+ return(NULL);
+ ret = xmlDictLookup(ctxt->dict, val, -1);
+ xmlFree(val);
+ return(ret);
+}
+
/**
* xmlSchemaGetProp:
* @ctxt: the parser context
@@ -1040,12 +1242,13 @@ xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
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 +1265,19 @@ xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
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 +1311,23 @@ xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
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 +1340,153 @@ xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
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 *
@@ -1368,12 +1728,12 @@ xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
/**
* xmlSchemaAddType:
- * @ctxt: a schema validation context
+ * @ctxt: a schema parser context
* @schema: the schema being built
* @name: the item name
* @namespace: the namespace
*
- * Add an XML schema Simple Type definition
+ * Add an XML schema item
* *WARNING* this interface is highly subject to change
*
* Returns the new struture or NULL in case of error
@@ -1434,6 +1794,8 @@ xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
}
ret->minOccurs = 1;
ret->maxOccurs = 1;
+ ret->attributeUses = NULL;
+ ret->attributeWildcard = NULL;
return (ret);
}
@@ -1487,6 +1849,60 @@ xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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 *
@@ -1536,7 +1952,7 @@ xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
ns = xmlSearchNs(node->doc, node, prefix);
if (ns == NULL) {
xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
- "Attribute %s: the QName prefix %s is undefined\n",
+ "Attribute \"%s\": the QName prefix \"%s\" is undefined\n",
(const xmlChar *) name, prefix);
} else {
*namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
@@ -1661,16 +2077,17 @@ xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
************************************************************************/
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,
- xmlNodePtr node,
- int simple);
+ xmlNodePtr node);
static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaPtr schema,
xmlNodePtr node);
@@ -1684,18 +2101,113 @@ static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
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);
/**
+ * xmlSchemaParseSchemaAttrValue:
+ *
+ * @ctxt: a schema parser context
+ * @attr: the schema attribute being validated
+ * @type: the built-in type to be validated against
+ * @value: the value to be validated
+ *
+ * Validates a value against the given built-in type.
+ * This one is intended to be used internally for validation
+ * of schema attribute values during parsing of the schema.
+ *
+ * Returns 0 if the value is valid, a positive error code
+ * number otherwise and -1 in case of an internal or API error.
+ */
+static int
+xmlSchemaParseSchemaAttrValue(xmlSchemaParserCtxtPtr ctxt,
+ xmlAttrPtr attr,
+ xmlSchemaTypePtr type)
+{
+ const xmlChar *value;
+ int ret;
+
+ if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
+ return (-1);
+ value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
+ switch (type->builtInType) {
+ case XML_SCHEMAS_NCNAME:
+ ret = xmlValidateNCName(value, 1);
+ break;
+ case XML_SCHEMAS_QNAME:
+ ret = xmlValidateQName(value, 1);
+ if ((ret == 0) && (attr != NULL)) {
+ xmlChar *local = NULL;
+ xmlChar *prefix;
+
+ local = xmlSplitQName2(value, &prefix);
+ if (prefix != NULL) {
+ xmlNsPtr ns;
+
+ ns = xmlSearchNs(attr->doc, (xmlNodePtr) attr, prefix);
+ if (ns == NULL) {
+ xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
+ XML_SCHEMAP_PREFIX_UNDEFINED,
+ "Attribute \"%s\": the QName prefix "
+ "\"%s\" is undefined.\n",
+ attr->name, prefix);
+ ret = 1;
+ }
+ }
+ if (local != NULL)
+ xmlFree(local);
+ if (prefix != NULL)
+ xmlFree(prefix);
+ }
+ break;
+ default: {
+ xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
+ XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaParseSchemaAttrValue, validation "
+ "using this type in not implemented yet\"%s\".\n",
+ type->name, NULL);
+ return (-1);
+ }
+ }
+ if (ret > 0) {
+ if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
+ xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr,
+ XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
+ NULL, NULL, NULL,
+ "The schema attribute \"%s\" with the value \"%s\" is not "
+ "of built-in list simple type \"%s\".\n",
+ attr->name, value, type->name, NULL, NULL);
+ } else {
+ if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) {
+ xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr,
+ XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
+ NULL, NULL, NULL,
+ "The schema attribute \"%s\" with the value \"%s\" is not "
+ "of built-in primitive type \"%s\".\n",
+ attr->name, value, type->name, NULL, NULL);
+ } else {
+ xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr,
+ XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
+ NULL, NULL, NULL,
+ "The schema attribute \"%s\" with the value \"%s\" is not "
+ "of built-in atomic simple type \"%s\".\n",
+ attr->name, value, type->name, NULL, NULL);
+ }
+ }
+ }
+ return (ret);
+}
+
+/**
* xmlSchemaParseAttrDecls:
* @ctxt: a schema validation context
* @schema: the schema being built
@@ -1720,10 +2232,13 @@ xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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 +2249,14 @@ xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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;
}
@@ -1841,6 +2355,17 @@ xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
}
facet->id = xmlSchemaGetProp(ctxt, node, "id");
facet->value = value;
+ if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
+ (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
+ const xmlChar *fixed;
+
+ fixed = xmlSchemaGetProp(ctxt, node, "fixed");
+ if (fixed != NULL) {
+ if (xmlStrEqual(fixed, BAD_CAST "true"))
+ facet->fixed = 1;
+ }
+ }
+
child = node->children;
if (IS_SCHEMA(child, "annotation")) {
@@ -1955,28 +2480,20 @@ xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
*
* 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 +2502,88 @@ xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
processContents = xmlSchemaGetProp(ctxt, node, "processContents");
if ((processContents == NULL)
|| (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
- ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
+ ret->processContents = XML_SCHEMAS_ANY_STRICT;
} else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
- ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
+ ret->processContents = XML_SCHEMAS_ANY_SKIP;
} else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
- ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
+ ret->processContents = XML_SCHEMAS_ANY_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_ANY_STRICT;
+ }
+ /*
+ * Build the namespace constraints.
+ */
+ nsConstraint = xmlSchemaGetProp(ctxt, node, "namespace");
+ if ((nsConstraint == NULL) || (xmlStrEqual(nsConstraint, BAD_CAST "##any")))
+ ret->any = 1;
+ else if (xmlStrEqual(nsConstraint, BAD_CAST "##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, BAD_CAST "##other")) ||
+ (xmlStrEqual(member, BAD_CAST "##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, BAD_CAST "##targetNamespace")) {
+ dictMember = schema->targetNamespace;
+ } else if (xmlStrEqual(member, BAD_CAST "##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 +2594,8 @@ xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
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 +2680,8 @@ xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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 +2699,8 @@ xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
}
}
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 +2722,8 @@ xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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 +2800,7 @@ xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
"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 +2825,11 @@ xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
*/
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;
xmlNodePtr child = NULL;
const xmlChar *oldcontainer;
char buf[100];
@@ -2249,7 +2839,6 @@ xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
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 +2861,8 @@ xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
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 +2870,9 @@ xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
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 +2880,7 @@ xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
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 +2897,7 @@ xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
TODO
child = child->next;
}
+ */
if (child != NULL) {
xmlSchemaPErr2(ctxt, node, child,
XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
@@ -2326,7 +2921,7 @@ xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
*/
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 +2939,6 @@ xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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 +2946,10 @@ xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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 +2958,7 @@ xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
/* 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 +2974,7 @@ xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
/* 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 +2993,7 @@ xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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 +3011,14 @@ xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
}
}
- 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 +3027,7 @@ xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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 +3061,7 @@ xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
child = child->next;
}
+
if (ref != NULL) {
/* 3.3.3 (2.2) */
while (child != NULL) {
@@ -2496,7 +3094,7 @@ xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
"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 +3108,7 @@ xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
"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;
}
@@ -2556,10 +3154,10 @@ xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
type = xmlSchemaAddType(ctxt, schema, name, NULL);
if (type == NULL)
return (NULL);
- type->node = node;
type->type = XML_SCHEMA_TYPE_UNION;
+ type->node = node;
type->id = xmlSchemaGetProp(ctxt, node, "id");
- type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
+ type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
child = node->children;
if (IS_SCHEMA(child, "annotation")) {
@@ -2568,7 +3166,7 @@ xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
}
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;
@@ -2608,6 +3206,7 @@ xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
xmlSchemaTypePtr type, subtype;
xmlNodePtr child = NULL;
xmlChar name[30];
+ xmlAttrPtr attr;
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
return (NULL);
@@ -2619,20 +3218,33 @@ xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
type->node = node;
type->type = XML_SCHEMA_TYPE_LIST;
type->id = xmlSchemaGetProp(ctxt, node, "id");
- type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
child = node->children;
if (IS_SCHEMA(child, "annotation")) {
type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
child = child->next;
}
-
+ /*
+ * Check type of "itemType".
+ */
+ attr = xmlSchemaGetPropNode(node, BAD_CAST "itemType");
+ if (attr != NULL) {
+ type->base = xmlGetQNameProp(ctxt, node, "itemType", &(type->baseNs));
+ xmlSchemaParseSchemaAttrValue(ctxt, attr,
+ xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
+
+ }
subtype = NULL;
- if (IS_SCHEMA(child, "simpleType")) {
- subtype = (xmlSchemaTypePtr)
- xmlSchemaParseSimpleType(ctxt, schema, child);
- child = child->next;
- type->subtypes = subtype;
+ if (IS_SCHEMA(child, "simpleType")) {
+ subtype = (xmlSchemaTypePtr)
+ xmlSchemaParseSimpleType(ctxt, schema, child, 0);
+ type->subtypes = subtype;
+ /*
+ * This is a hack to save the information that a local
+ * simple type was defined.
+ */
+ type->baseType = subtype;
+ child = child->next;
}
if (child != NULL) {
xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
@@ -2656,41 +3268,102 @@ xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
*/
static xmlSchemaTypePtr
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
- xmlNodePtr node)
+ xmlNodePtr node, int topLevel)
{
- xmlSchemaTypePtr type, subtype;
+ xmlSchemaTypePtr type, subtype, ctxtType;
xmlNodePtr child = NULL;
- const xmlChar *name;
+ const xmlChar *propVal;
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
return (NULL);
-
- name = xmlSchemaGetProp(ctxt, node, "name");
- if (name == NULL) {
+ ctxtType = ctxt->ctxtType;
+ propVal = xmlSchemaGetProp(ctxt, node, "name");
+ if (propVal == NULL) {
char buf[100];
snprintf(buf, 99, "simpleType %d", ctxt->counter++ + 1);
type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
} else {
- /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
- type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
+ if (!topLevel) {
+ xmlSchemaPErr(ctxt, node,
+ XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
+ "The attribute \"name\" is not allowed on a local "
+ "simpleType definition\n",
+ propVal, NULL);
+ return (NULL);
+ }
+ /*
+ * "name" has to be of type NCName.
+ * TODO: Actually this should be validated by the schema for schemas.
+ */
+ if (xmlSchemaParseSchemaAttrValue(ctxt,
+ xmlSchemaGetPropNode(node, BAD_CAST "name"),
+ xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME)) != 0)
+ return (NULL);
+ type = xmlSchemaAddType(ctxt, schema, propVal, schema->targetNamespace);
}
if (type == NULL)
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");
-
+ propVal = xmlSchemaGetProp(ctxt, node, "final");
+ if (propVal == NULL) {
+ type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
+ } else {
+ if (xmlStrEqual(propVal, BAD_CAST "#all")) {
+ type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
+ type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
+ type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
+ } else {
+ const xmlChar *end, *cur = propVal;
+ xmlChar *item;
+
+ do {
+ while (IS_BLANK_CH(*cur))
+ cur++;
+ end = cur;
+ while ((*end != 0) && (!(IS_BLANK_CH(*end))))
+ end++;
+ if (end == cur)
+ break;
+ item = xmlStrndup(cur, end - cur);
+ if (xmlStrEqual(item, BAD_CAST "restriction")) {
+ if ((type->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) == 0)
+ type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
+ } else if (xmlStrEqual(item, BAD_CAST "list")) {
+ if ((type->flags & XML_SCHEMAS_TYPE_FINAL_LIST) == 0)
+ type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
+ } else if (xmlStrEqual(item, BAD_CAST "union")) {
+ if ((type->flags & XML_SCHEMAS_TYPE_FINAL_UNION) == 0)
+ type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
+ } else {
+ xmlSchemaPErr(ctxt, node,
+ XML_SCHEMAS_ERR_INTERNAL,
+ "The attribute \"final\" of type \"%s\" "
+ "has an invalid value\n",
+ type->name, NULL);
+ }
+ if (item != NULL)
+ xmlFree(item);
+ cur = end;
+ } while (*cur != 0);
+ }
+ }
child = node->children;
if (IS_SCHEMA(child, "annotation")) {
type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
child = child->next;
}
subtype = NULL;
+ ctxt->ctxtType = type;
+ ctxt->parentItem = type;
if (IS_SCHEMA(child, "restriction")) {
subtype = (xmlSchemaTypePtr)
- xmlSchemaParseRestriction(ctxt, schema, child, 1);
+ xmlSchemaParseRestriction(ctxt, schema, child);
child = child->next;
} else if (IS_SCHEMA(child, "list")) {
subtype = (xmlSchemaTypePtr)
@@ -2702,19 +3375,23 @@ xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
child = child->next;
}
type->subtypes = subtype;
- if (subtype == NULL) {
- xmlSchemaPErr2(ctxt, node, child,
- XML_SCHEMAP_MISSING_SIMPLETYPE_CHILD,
- "SimpleType %s does not define a variety\n",
- type->name, NULL);
- }
if (child != NULL) {
xmlSchemaPErr2(ctxt, node, child,
- XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
- "SimpleType %s has unexpected content\n",
+ XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
+ "SimpleType \"%s\" has unexpected content\n",
type->name, NULL);
+ } else {
+ if (subtype == NULL) {
+ xmlSchemaPErr2(ctxt, node, child,
+ XML_SCHEMAP_S4S_ELEM_MISSING,
+ "SimpleType \"%s\" must have one of <restriction> or "
+ "<list> or <union> as a child\n",
+ type->name, NULL);
+ }
}
+ ctxt->ctxtType = ctxtType;
+
return (type);
}
@@ -2733,7 +3410,7 @@ xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
*/
static xmlSchemaTypePtr
xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
- xmlNodePtr node)
+ xmlNodePtr node, int topLevel)
{
xmlSchemaTypePtr type, subtype;
xmlNodePtr child = NULL;
@@ -2747,7 +3424,6 @@ xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
name = xmlSchemaGetProp(ctxt, node, "name");
if (name == NULL) {
-
ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
if (ref == NULL) {
xmlSchemaPErr2(ctxt, node, child,
@@ -2763,9 +3439,10 @@ xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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 +3575,7 @@ xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
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 +3743,39 @@ xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
if (import == NULL) {
return (-1);
}
+ if (!xmlStrEqual(import->schema->targetNamespace, namespace)) {
+ if (namespace == NULL) {
+ if (import->schema->targetNamespace != NULL) {
+ xmlSchemaPErr(ctxt, node, XML_SCHEMAP_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_SCHEMAP_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_SCHEMAP_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 +3913,10 @@ xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
}
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 +3925,10 @@ xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
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);
@@ -3241,6 +3949,8 @@ xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
child = child->next;
}
}
+ ctxt->parentItem = NULL;
+ ctxt->ctxtType = NULL;
}
/**
@@ -3355,7 +4065,7 @@ xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
if (!IS_SCHEMA(root, "schema")) {
xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
XML_SCHEMAP_NOT_SCHEMA,
- "File %s is not a schemas", schemaLocation, NULL);
+ "File %s is not a schema", schemaLocation, NULL);
xmlFreeDoc(doc);
return (-1);
}
@@ -3435,7 +4145,7 @@ xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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 +4223,7 @@ xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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")) {
@@ -3548,7 +4258,6 @@ xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
* @ctxt: a schema validation context
* @schema: the schema being built
* @node: a subtree containing XML Schema informations
- * @simple: is that part of a simple type.
*
* parse a XML schema Restriction definition
* *WARNING* this interface is highly subject to change
@@ -3557,10 +4266,9 @@ xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
*/
static xmlSchemaTypePtr
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
- xmlNodePtr node, int simple)
+ xmlNodePtr node)
{
- xmlSchemaTypePtr type, subtype;
- xmlSchemaFacetPtr facet, lastfacet = NULL;
+ xmlSchemaTypePtr type, subtype;
xmlNodePtr child = NULL;
xmlChar name[30];
const xmlChar *oldcontainer;
@@ -3574,14 +4282,16 @@ xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
type = xmlSchemaAddType(ctxt, schema, name, NULL);
if (type == NULL)
return (NULL);
- type->node = node;
type->type = XML_SCHEMA_TYPE_RESTRICTION;
+ type->node = node;
type->id = xmlSchemaGetProp(ctxt, node, "id");
type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
- if ((!simple) && (type->base == NULL)) {
+ if ((type->base == NULL) &&
+ (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
xmlSchemaPErr2(ctxt, node, child,
- XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
- "Restriction %s has no base\n", type->name, NULL);
+ XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
+ "Restriction \"%s\" must have a \"base\" attribute.\n",
+ type->name, NULL);
}
ctxt->container = name;
@@ -3592,68 +4302,107 @@ xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
}
subtype = NULL;
- if (IS_SCHEMA(child, "all")) {
- subtype = (xmlSchemaTypePtr)
- xmlSchemaParseAll(ctxt, schema, child);
- child = child->next;
- type->subtypes = subtype;
- } else if (IS_SCHEMA(child, "choice")) {
- subtype = xmlSchemaParseChoice(ctxt, schema, child);
- child = child->next;
- type->subtypes = subtype;
- } else if (IS_SCHEMA(child, "sequence")) {
- subtype = (xmlSchemaTypePtr)
- xmlSchemaParseSequence(ctxt, schema, child);
- child = child->next;
- type->subtypes = subtype;
- } else if (IS_SCHEMA(child, "group")) {
- subtype = (xmlSchemaTypePtr)
- xmlSchemaParseGroup(ctxt, schema, child);
- child = child->next;
- type->subtypes = subtype;
- } else {
- if (IS_SCHEMA(child, "simpleType")) {
- subtype = (xmlSchemaTypePtr)
- xmlSchemaParseSimpleType(ctxt, schema, child);
- child = child->next;
- type->baseType = subtype;
- }
- /*
- * Facets
- */
- while ((IS_SCHEMA(child, "minInclusive")) ||
- (IS_SCHEMA(child, "minExclusive")) ||
- (IS_SCHEMA(child, "maxInclusive")) ||
- (IS_SCHEMA(child, "maxExclusive")) ||
- (IS_SCHEMA(child, "totalDigits")) ||
- (IS_SCHEMA(child, "fractionDigits")) ||
- (IS_SCHEMA(child, "pattern")) ||
- (IS_SCHEMA(child, "enumeration")) ||
- (IS_SCHEMA(child, "whiteSpace")) ||
- (IS_SCHEMA(child, "length")) ||
- (IS_SCHEMA(child, "maxLength")) ||
- (IS_SCHEMA(child, "minLength"))) {
- facet = xmlSchemaParseFacet(ctxt, schema, child);
- if (facet != NULL) {
- if (lastfacet == NULL) {
- type->facets = facet;
- lastfacet = facet;
- } else {
- lastfacet->next = facet;
- lastfacet = facet;
- }
- lastfacet->next = NULL;
- }
- child = child->next;
- }
- }
- child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
+ if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
+ if (IS_SCHEMA(child, "all")) {
+ subtype = (xmlSchemaTypePtr)
+ xmlSchemaParseAll(ctxt, schema, child);
+ child = child->next;
+ type->subtypes = subtype;
+ } else if (IS_SCHEMA(child, "choice")) {
+ subtype = xmlSchemaParseChoice(ctxt, schema, child);
+ child = child->next;
+ type->subtypes = subtype;
+ } else if (IS_SCHEMA(child, "sequence")) {
+ subtype = (xmlSchemaTypePtr)
+ xmlSchemaParseSequence(ctxt, schema, child);
+ child = child->next;
+ type->subtypes = subtype;
+ } else if (IS_SCHEMA(child, "group")) {
+ subtype = (xmlSchemaTypePtr)
+ xmlSchemaParseGroup(ctxt, schema, child, 0);
+ child = child->next;
+ type->subtypes = subtype;
+ }
+ } else if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
+ (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
+ xmlSchemaFacetPtr facet, lastfacet = NULL;
+
+ if (IS_SCHEMA(child, "simpleType")) {
+ subtype = (xmlSchemaTypePtr)
+ xmlSchemaParseSimpleType(ctxt, schema, child, 0);
+ /*
+ * For the simple type this serves as the base type.
+ */
+ type->baseType = subtype;
+ /*
+ * For the complex type this serves as information for the
+ * definition of the content type.
+ * Additionally this is a hack for the simple type, to save
+ * the information that a local simple type was defined; thus
+ * allowing to check: src-restriction-base-or-simpleType.
+ */
+ type->subtypes = subtype;
+ child = child->next;
+ }
+ /*
+ * Add the facets to the parent simpleType/complexType.
+ */
+ while ((IS_SCHEMA(child, "minInclusive")) ||
+ (IS_SCHEMA(child, "minExclusive")) ||
+ (IS_SCHEMA(child, "maxInclusive")) ||
+ (IS_SCHEMA(child, "maxExclusive")) ||
+ (IS_SCHEMA(child, "totalDigits")) ||
+ (IS_SCHEMA(child, "fractionDigits")) ||
+ (IS_SCHEMA(child, "pattern")) ||
+ (IS_SCHEMA(child, "enumeration")) ||
+ (IS_SCHEMA(child, "whiteSpace")) ||
+ (IS_SCHEMA(child, "length")) ||
+ (IS_SCHEMA(child, "maxLength")) ||
+ (IS_SCHEMA(child, "minLength"))) {
+ facet = xmlSchemaParseFacet(ctxt, schema, child);
+ if (facet != NULL) {
+ if (lastfacet == NULL)
+ ctxt->ctxtType->facets = facet;
+ else
+ lastfacet->next = facet;
+ lastfacet = facet;
+ lastfacet->next = NULL;
+ }
+ child = child->next;
+ }
+ /*
+ * Create links for derivation and validation.
+ */
+ if (lastfacet != NULL) {
+ xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
+
+ facet = ctxt->ctxtType->facets;
+ do {
+ facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
+ if (facetLink == NULL) {
+ xmlSchemaPErrMemory(ctxt, "allocation a facet link", NULL);
+ xmlFree(facetLink);
+ return (NULL);
+ }
+ facetLink->facet = facet;
+ facetLink->next = NULL;
+ if (lastFacetLink == NULL)
+ ctxt->ctxtType->facetSet = facetLink;
+ else
+ lastFacetLink->next = facetLink;
+ lastFacetLink = facetLink;
+ facet = facet->next;
+ } while (facet != NULL);
+ }
+ }
+ if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)
+ child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
if (child != NULL) {
- xmlSchemaPErr2(ctxt, node, child,
- XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
- "Restriction %s has unexpected content\n",
- type->name, NULL);
- }
+ xmlSchemaPErr2(ctxt, node, child,
+ XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
+ "Restriction \"%s\" has unexpected content.\n",
+ type->name, NULL);
+ }
ctxt->container = oldcontainer;
return (type);
}
@@ -3684,11 +4433,11 @@ xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
oldcontainer = ctxt->container;
snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
- type = xmlSchemaAddType(ctxt, schema, name, NULL);
+ type = xmlSchemaAddType(ctxt, schema, name, NULL);
if (type == NULL)
return (NULL);
- type->node = node;
type->type = XML_SCHEMA_TYPE_EXTENSION;
+ type->node = node;
type->id = xmlSchemaGetProp(ctxt, node, "id");
ctxt->container = name;
@@ -3714,7 +4463,7 @@ xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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,13 +4501,12 @@ xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
return (NULL);
-
snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
- type = xmlSchemaAddType(ctxt, schema, name, NULL);
+ type = xmlSchemaAddType(ctxt, schema, name, NULL);
if (type == NULL)
return (NULL);
- type->node = node;
type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
+ type->node = node;
type->id = xmlSchemaGetProp(ctxt, node, "id");
child = node->children;
@@ -3766,10 +4514,11 @@ xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
child = child->next;
}
- subtype = NULL;
+ ctxt->parentItem = type;
+ subtype = NULL;
if (IS_SCHEMA(child, "restriction")) {
subtype = (xmlSchemaTypePtr)
- xmlSchemaParseRestriction(ctxt, schema, child, 0);
+ xmlSchemaParseRestriction(ctxt, schema, child);
child = child->next;
} else if (IS_SCHEMA(child, "extension")) {
subtype = (xmlSchemaTypePtr)
@@ -3808,13 +4557,12 @@ xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
return (NULL);
-
snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
type = xmlSchemaAddType(ctxt, schema, name, NULL);
if (type == NULL)
return (NULL);
- type->node = node;
type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
+ type->node = node;
type->id = xmlSchemaGetProp(ctxt, node, "id");
child = node->children;
@@ -3822,10 +4570,11 @@ xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
child = child->next;
}
+ ctxt->parentItem = type;
subtype = NULL;
if (IS_SCHEMA(child, "restriction")) {
subtype = (xmlSchemaTypePtr)
- xmlSchemaParseRestriction(ctxt, schema, child, 0);
+ xmlSchemaParseRestriction(ctxt, schema, child);
child = child->next;
} else if (IS_SCHEMA(child, "extension")) {
subtype = (xmlSchemaTypePtr)
@@ -3855,9 +4604,9 @@ xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
*/
static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
- xmlNodePtr node)
+ xmlNodePtr node, int topLevel)
{
- xmlSchemaTypePtr type, subtype;
+ xmlSchemaTypePtr type, subtype, ctxtType;
xmlNodePtr child = NULL;
const xmlChar *name;
const xmlChar *oldcontainer;
@@ -3866,10 +4615,11 @@ xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
return (NULL);
+ ctxtType = ctxt->ctxtType;
+
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 +4631,13 @@ xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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;
@@ -3895,6 +4646,7 @@ xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
child = child->next;
}
+ ctxt->ctxtType = type;
if (IS_SCHEMA(child, "simpleContent")) {
/* 3.4.3 : 2.2
* Specifying mixed='true' when the <simpleContent>
@@ -3920,7 +4672,7 @@ xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
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,7 +4685,10 @@ xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
"ComplexType %s has unexpected content\n",
type->name, NULL);
}
+ if (type->attributeWildcard != NULL)
+ type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
ctxt->container = oldcontainer;
+ ctxt->ctxtType = ctxtType;
return (type);
}
@@ -3984,7 +4739,10 @@ xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
val, NULL);
}
} else {
- schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
+ /* Removed, since the default value for elementFormDefault
+ * is "unqualified".
+ */
+ /* schema->flags |= XML_SCHEMAS_QUALIF_ELEM; */
}
val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
if (val != NULL) {
@@ -3998,6 +4756,51 @@ xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
}
}
+ val = xmlSchemaGetProp(ctxt, node, "finalDefault");
+ if (val != NULL) {
+ if (xmlStrEqual(val, BAD_CAST "#all")) {
+ schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
+ schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
+ schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_LIST;
+ schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_UNION;
+ } else {
+ const xmlChar *end, *cur = val;
+ xmlChar *item;
+
+ do {
+ while (IS_BLANK_CH(*cur))
+ cur++;
+ end = cur;
+ while ((*end != 0) && (!(IS_BLANK_CH(*end))))
+ end++;
+ if (end == cur)
+ break;
+ item = xmlStrndup(cur, end - cur);
+ if (xmlStrEqual(item, BAD_CAST "extension")) {
+ if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) == 0)
+ schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
+ } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
+ if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) == 0)
+ schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
+ } else if (xmlStrEqual(item, BAD_CAST "list")) {
+ if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST) == 0)
+ schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_LIST;
+ } else if (xmlStrEqual(item, BAD_CAST "union")) {
+ if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION) == 0)
+ schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_UNION;
+ } else {
+ xmlSchemaPErr(ctxt, node,
+ XML_SCHEMAS_ERR_INTERNAL,
+ "Invalid value for the attribute \"finalDefault\".\n",
+ NULL, NULL);
+ }
+ if (item != NULL)
+ xmlFree(item);
+ cur = end;
+ } while (*cur != 0);
+ }
+ }
+
xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
} else {
xmlDocPtr doc;
@@ -4027,7 +4830,6 @@ xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParse() failed\n");
#endif
-
return (schema);
}
@@ -4182,6 +4984,7 @@ xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
case XML_SCHEMA_TYPE_ANY:
/* TODO : handle the namespace too */
/* TODO : make that a specific transition type */
+ /* Daniel says: use xmlAutomataNewTransition2 */
TODO ctxt->state =
xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
BAD_CAST "*", NULL);
@@ -4464,7 +5267,11 @@ xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
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 +5338,7 @@ xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
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,22 +5441,26 @@ xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
{
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;
}
elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
if (elemDecl == NULL) {
- xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
- "Schemas: element %s ref to %s not found\n",
- name, elem->ref);
+ xmlSchemaPErr(ctxt, elem->node,
+ XML_SCHEMAP_SRC_RESOLVE,
+ "Element \"%s\": the QName \"%s\" of the attribute "
+ "\"ref\" does not resolve to a schema "
+ "component.\n",
+ name, elem->ref);
return;
}
elem->refDecl = elemDecl;
@@ -4658,7 +5469,7 @@ xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
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;
}
@@ -4666,9 +5477,11 @@ xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
elem->namedTypeNs);
if (typeDecl == NULL) {
- xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
- "Schemas: element %s type %s not found\n", name,
- elem->namedType);
+ xmlSchemaPErr(ctxt, elem->node,
+ XML_SCHEMAP_SRC_RESOLVE,
+ "Element \"%s\": the QName \"%s\" of the attribute "
+ "\"type\" does not resolve to a schema "
+ "component.\n", name, elem->namedType);
return;
}
elem->subtypes = typeDecl;
@@ -4684,29 +5497,38 @@ xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
*/
static void
xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
-{
- const xmlChar *itemType, *namespace;
- xmlSchemaTypePtr subtype;
-
- /* Handle the "itemType" attribute. */
- itemType = xmlGetQNameProp(ctxt, type->node, "itemType", &namespace);
- if (itemType != NULL) {
- /* Do not allow more that one item type. */
- if (type->subtypes != NULL) {
- xmlSchemaPErr(ctxt, type->node,
- XML_SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE,
- "List %s has more than one item type defined\n",
- type->name, NULL);
- }
- subtype = xmlSchemaGetType(ctxt->schema, itemType, namespace);
- if (subtype == NULL) {
+{
+ /*
+ * src-list-itemType-or-simpleType
+ * Either the itemType [attribute] or the <simpleType> [child] of
+ * the <list> element must be present, but not both.
+ */
+ if (((type->base == NULL) &&
+ (type->subtypes == NULL)) ||
+ ((type->base != NULL) &&
+ (type->subtypes != NULL))) {
+ /*
+ * src-restriction-base-or-simpleType
+ * Either the base [attribute] or the simpleType [child] of the
+ * <restriction> element must be present, but not both.
+ */
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
+ "List \"%s\": "
+ "Either the \"base\" attribute or the <simpleType> child "
+ "must be present, but not both.\n",
+ type->name, NULL);
+ } else if (type->base!= NULL) {
+ type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
+ if (type->subtypes == NULL) {
xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_TYPE,
- "List %s references an unknown item type: %s\n",
- type->name, xmlSchemaGetProp(ctxt, type->node,
- "itemType"));
- } else
- type->subtypes = subtype;
- }
+ "List \"%s\" references an unknown item type: \"%s\"\n",
+ type->name, type->base);
+ }
+ }
+ if ((type->subtypes != NULL) &&
+ (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
+ xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
}
/**
@@ -4714,60 +5536,2303 @@ xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
* @typeDecl: the schema type definition
* @ctxt: the schema parser context
*
- * Checks the memberTypes references of the union type.
+ * Checks and builds the memberTypes of the union type.
+ * Returns -1 in case of an internal error, 0 otherwise.
*/
-static void
+static int
xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
xmlSchemaParserCtxtPtr ctxt)
{
const xmlChar *cur, *end, *prefix, *ncName, *namespace;
xmlChar *tmp;
- xmlSchemaTypePtr subtype;
+ xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
+ xmlSchemaTypePtr memberType, ctxtType;
xmlNsPtr ns;
int len;
- if ((type->type != XML_SCHEMA_TYPE_UNION) || (type->ref == NULL))
- return;
+ /* 1 If the <union> alternative is chosen, then [Definition:]
+ * define the explicit members as the type definitions ·resolved·
+ * to by the items in the ·actual value· of the memberTypes [attribute],
+ * if any, followed by the type definitions corresponding to the
+ * <simpleType>s among the [children] of <union>, if any.
+ */
- cur = type->ref;
- do {
- while (IS_BLANK_CH(*cur))
- cur++;
- end = cur;
- while ((*end != 0) && (!(IS_BLANK_CH(*end))))
- end++;
- if (end == cur)
- break;
- tmp = xmlStrndup(cur, end - cur);
- ncName = xmlSplitQName3(tmp, &len);
- if (ncName != NULL) {
- prefix = xmlDictLookup(ctxt->dict, tmp, len);
- } else {
- prefix = NULL;
- ncName = tmp;
- }
- ns = xmlSearchNs(type->node->doc, type->node, prefix);
- if (ns == NULL) {
- if (prefix != NULL) {
- xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_PREFIX_UNDEFINED,
- "Union %s: the namespace prefix of member type "
- "%s is undefined\n",
- type->name, (const xmlChar *) tmp);
- }
- namespace = NULL;
- } else {
- namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
- }
- /* Lookup the referenced type */
- subtype = xmlSchemaGetType(ctxt->schema, ncName, namespace);
- if (subtype == NULL) {
- xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
- "Union %s references an unknown member type %s\n",
- type->name, (const xmlChar *) tmp);
- }
- xmlFree(tmp);
- cur = end;
- } while (*cur != 0);
+ if (type->type != XML_SCHEMA_TYPE_UNION)
+ return (-1);
+ if (ctxt->ctxtType == NULL) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
+ "available", NULL, NULL);
+ return (-1);
+ }
+ /*
+ * src-union-memberTypes-or-simpleTypes
+ * Either the memberTypes [attribute] of the <union> element must
+ * be non-empty or there must be at least one simpleType [child].
+ */
+ if ((type->base == NULL) &&
+ (type->subtypes == NULL)) {
+ /*
+ * src-restriction-base-or-simpleType
+ * Either the base [attribute] or the simpleType [child] of the
+ * <restriction> element must be present, but not both.
+ */
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
+ "Union \"%s\": "
+ "Either the \"memberTypes\" attribute must be non-empty "
+ "or there must be at least one <simpleType> child.\n",
+ type->name, NULL);
+ }
+
+ ctxtType = ctxt->ctxtType;
+ if (type->base != NULL) {
+ cur = type->base;
+ do {
+ while (IS_BLANK_CH(*cur))
+ cur++;
+ end = cur;
+ while ((*end != 0) && (!(IS_BLANK_CH(*end))))
+ end++;
+ if (end == cur)
+ break;
+ tmp = xmlStrndup(cur, end - cur);
+ ncName = xmlSplitQName3(tmp, &len);
+ if (ncName != NULL) {
+ prefix = xmlDictLookup(ctxt->dict, tmp, len);
+ } else {
+ prefix = NULL;
+ ncName = tmp;
+ }
+ ns = xmlSearchNs(type->node->doc, type->node, prefix);
+ if (ns == NULL) {
+ if (prefix != NULL) {
+ xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_PREFIX_UNDEFINED,
+ "Union \"%s\": the namespace prefix of member type "
+ "\"%s\" is undefined\n",
+ type->name, (const xmlChar *) tmp);
+ }
+ namespace = NULL;
+ } else {
+ namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
+ }
+ memberType = xmlSchemaGetType(ctxt->schema, ncName, namespace);
+ if (memberType == NULL) {
+ xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
+ "Union \"%s\" references an unknown member type \"%s\".\n",
+ type->name, (const xmlChar *) tmp);
+ } else {
+ if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
+ xmlSchemaTypeFixup(memberType, ctxt, NULL);
+ link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
+ if (link == NULL) {
+ xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
+ return (-1);
+ }
+ link->type = memberType;
+ link->next = NULL;
+ if (lastLink == NULL)
+ ctxtType->memberTypes = link;
+ else
+ lastLink->next = link;
+ lastLink = link;
+ }
+ xmlFree(tmp);
+ cur = end;
+ } while (*cur != 0);
+ }
+ /*
+ * Add local simple types,
+ */
+ memberType = type->subtypes;
+ while (memberType != NULL) {
+ if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
+ xmlSchemaTypeFixup(memberType, ctxt, NULL);
+ link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
+ if (link == NULL) {
+ xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
+ return (-1);
+ }
+ link->type = memberType;
+ link->next = NULL;
+ if (lastLink == NULL)
+ ctxtType->memberTypes = link;
+ else
+ lastLink->next = link;
+ lastLink = link;
+ memberType = memberType->next;
+ }
+ /*
+ * The actual value is then formed by replacing any union type
+ * definition in the ·explicit members· with the members of their
+ * {member type definitions}, in order.
+ */
+ link = ctxtType->memberTypes;
+ while (link != NULL) {
+ if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
+ subLink = link->type->memberTypes;
+ if (subLink != NULL) {
+ link->type = subLink->type;
+ if (subLink->next != NULL) {
+ lastLink = link->next;
+ subLink = subLink->next;
+ prevLink = link;
+ while (subLink != NULL) {
+ newLink = (xmlSchemaTypeLinkPtr)
+ xmlMalloc(sizeof(xmlSchemaTypeLink));
+ if (newLink == NULL) {
+ xmlSchemaPErrMemory(ctxt, "allocating a type link",
+ NULL);
+ return (-1);
+ }
+ newLink->type = memberType;
+ prevLink->next = newLink;
+ prevLink = newLink;
+ newLink->next = lastLink;
+
+ subLink = subLink->next;
+ }
+ }
+ }
+ }
+ link = link->next;
+ }
+
+ return (0);
+}
+
+/**
+ * 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.
+ */
+static 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->builtInType == 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);
+}
+
+/**
+ * xmlSchemaIsDerivedFromBuiltInType:
+ * @type: the simpleType definition
+ *
+ * Returns the primitive type of the given type or
+ * NULL in case of error.
+ */
+static xmlSchemaTypePtr
+xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
+{
+ while (type != NULL) {
+ if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
+ return (type);
+ type = type->baseType;
+ }
+
+ return (NULL);
+}
+
+
+/**
+ * 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);
+}
+
+/**
+ * xmlSchemaCloneWildcardNsConstraints:
+ * @ctxt: the schema parser context
+ * @dest: the destination wildcard
+ * @source: the source wildcard
+ *
+ * Clones the namespace constraints of source
+ * and assignes them to dest.
+ * Returns -1 on internal error, 0 otherwise.
+ */
+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);
+}
+
+/**
+ * xmlSchemaUnionWildcards:
+ * @ctxt: the schema parser context
+ * @completeWild: the first wildcard
+ * @curWild: the second wildcard
+ *
+ * Unions the namespace constraints of the given wildcards.
+ * @completeWild will hold the resulting union.
+ * Returns a positive error code on failure, -1 in case of an
+ * internal error, 0 otherwise.
+ */
+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 = 0;
+
+ /*
+ * 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) {
+ 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;
+ }
+ }
+ return (0);
+ }
+ /*
+ * 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;
+
+ return(0);
+ }
+ /*
+ * 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(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
+ } 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);
+
+}
+
+/**
+ * xmlSchemaIntersectWildcards:
+ * @ctxt: the schema parser context
+ * @completeWild: the first wildcard
+ * @curWild: the second wildcard
+ *
+ * Intersects the namespace constraints of the given wildcards.
+ * @completeWild will hold the resulting intersection.
+ * Returns a positive error code on failure, -1 in case of an
+ * internal error, 0 otherwise.
+ */
+static int
+xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
+ xmlSchemaWildcardPtr completeWild,
+ xmlSchemaWildcardPtr curWild)
+{
+ xmlSchemaWildcardNsPtr cur, curB, prev, 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 = 0;
+
+ /*
+ * 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(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
+ }
+ /*
+ * 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);
+}
+
+/**
+ * xmlSchemaIsWildcardNsConstraintSubset:
+ * @ctxt: the schema parser context
+ * @wildA: the first wildcard
+ * @wildB: the second wildcard
+ *
+ * Returns 1 if the namespace constraint of @wildA is an intensional
+ * subset of @wildB, 0 otherwise.
+ */
+static int
+xmlSchemaIsWildcardNsConstraintSubset(
+ xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
+ xmlSchemaWildcardPtr wildA,
+ xmlSchemaWildcardPtr wildB)
+{
+
+ /*
+ * Schema Component Constraint: Wildcard Subset
+ */
+ /*
+ * 1 super must be any.
+ */
+ if (wildB->any)
+ return (1);
+ /*
+ * 2.1 sub must be a pair of not and a namespace name or ·absent·.
+ * 2.2 super must be a pair of not and the same value.
+ */
+ if ((wildA->negNsSet != NULL) &&
+ (wildB->negNsSet != NULL) &&
+ (wildA->negNsSet->value == wildA->negNsSet->value))
+ return (1);
+ /*
+ * 3.1 sub must be a set whose members are either namespace names or ·absent·.
+ */
+ if (wildA->nsSet != NULL) {
+ /*
+ * 3.2.1 super must be the same set or a superset thereof.
+ */
+ if (wildB->nsSet != NULL) {
+ xmlSchemaWildcardNsPtr cur, curB;
+ int found = 0;
+
+ cur = wildA->nsSet;
+ while (cur != NULL) {
+ found = 0;
+ curB = wildB->nsSet;
+ while (curB != NULL) {
+ if (cur->value == curB->value) {
+ found = 1;
+ break;
+ }
+ curB = curB->next;
+ }
+ if (!found)
+ return (0);
+ cur = cur->next;
+ }
+ if (found)
+ return (1);
+ } else if (wildB->negNsSet != NULL) {
+ xmlSchemaWildcardNsPtr cur;
+ /*
+ * 3.2.2 super must be a pair of not and a namespace name or
+ * ·absent· and that value must not be in sub's set.
+ */
+ cur = wildA->nsSet;
+ while (cur != NULL) {
+ if (cur->value == wildB->negNsSet->value)
+ return (0);
+ cur = cur->next;
+ }
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/**
+ * xmlSchemaBuildCompleteAttributeWildcard:
+ * @ctxt: the schema parser context
+ * @attrs: the attribute list
+ * @completeWild: the resulting complete wildcard
+ *
+ * Returns -1 in case of an internal error, 0 otherwise.
+ */
+static int
+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 (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
+ group->attributes, &group->attributeWildcard) == -1)
+ return (-1);
+ }
+ 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) == -1)
+ return (-1);
+ (*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;
+
+ } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
+ xmlSchemaFreeWildcard(*completeWild);
+ return (-1);
+ }
+ }
+ }
+ attrs = attrs->next;
+ }
+
+ return (0);
+}
+
+/**
+ * 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 = NULL;
+ xmlSchemaAttributePtr attrs;
+ xmlSchemaTypePtr anyType;
+ int baseIsAnyType = 0;
+
+ anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
+ /*
+ * Complex Type Definition with complex content Schema Component.
+ *
+ * Attribute uses.
+ */
+ if (type->attributeUses != NULL) {
+ xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaBuildAttributeValidation: "
+ "attribute uses already builded.\n",
+ NULL, NULL);
+ return (-1);
+ }
+ if (type->baseType == NULL) {
+ xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaBuildAttributeValidation: "
+ "complex type \"%s\" has no base type.\n",
+ type->name, NULL);
+ return (-1);
+ }
+
+ baseType = type->baseType;
+ if (baseType == NULL) {
+ xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaBuildAttributeValidation: "
+ "type has no base type.\n",
+ NULL, NULL);
+ return (-1);
+ }
+
+ if (baseType == anyType)
+ baseIsAnyType = 1;
+ /*
+ * Inherit the attribute uses of the base type.
+ */
+ /*
+ * NOTE: It is allowed to "extend" the anyType complex type.
+ */
+ 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;
+ }
+ }
+ }
+ if ((type->subtypes != NULL) &&
+ ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
+ (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
+ attrs = type->subtypes->subtypes->attributes;
+ type->attributeWildcard = type->subtypes->subtypes->attributeWildcard;
+ } else {
+ /* Short hand form of the complexType. */
+ attrs = type->attributes;
+ }
+ /*
+ * Handle attribute wildcards.
+ */
+ if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
+ attrs, &type->attributeWildcard) == -1) {
+ if ((type->attributeWildcard != NULL) &&
+ /* Either we used the short hand form... */
+ ((type->subtypes == NULL) ||
+ /* Or complexType -> restriction/extension */
+ (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
+ type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
+ return (-1);
+ }
+ /*
+ * TODO: This "onwed_attr_wildcard" is quite sensless: we should
+ * create the wildcard right from the start on the complexType,
+ * rather than on the <restriction>/<extension>.
+ */
+ if ((type->attributeWildcard != NULL) &&
+ /* Either we used the short hand form... */
+ ((type->subtypes == NULL) ||
+ /* Or complexType -> restriction/extension */
+ (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
+ type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
+
+ if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
+ ((baseIsAnyType) ||
+ ((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;
+ }
+ }
+
+ if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
+ if (type->attributeWildcard != NULL) {
+ /*
+ * Derivation Valid (Restriction, Complex)
+ * 4.1 The {base type definition} must also have one.
+ */
+ if (baseType->attributeWildcard == NULL) {
+ xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
+ "The derived type \"%s\" has an attribute wildcard, "
+ "but the base type \"%s\" does not have one.\n",
+ type->name, baseType->name);
+ return (1);
+ } else if (xmlSchemaIsWildcardNsConstraintSubset(ctxt,
+ type->attributeWildcard, baseType->attributeWildcard) == 0) {
+ /* 4.2 */
+ xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
+ "The wildcard in the derived type \"%s\" is not a valid "
+ "subset of the one in the base type \"%s\".\n",
+ type->name, baseType->name);
+ return (1);
+ }
+ /* 4.3 Unless the {base type definition} is the ·ur-type
+ * definition·, the complex type definition's {attribute
+ * wildcard}'s {process contents} must be identical to or
+ * stronger than the {base type definition}'s {attribute
+ * wildcard}'s {process contents}, where strict is stronger
+ * than lax is stronger than skip.
+ */
+ if ((type->baseType != anyType) &&
+ (type->attributeWildcard->processContents <
+ baseType->attributeWildcard->processContents)) {
+ xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
+ "The process contents of the wildcard in the "
+ "derived type \"%s\" is weaker than "
+ "that in the base type \"%s\".\n",
+ type->name, baseType->name);
+ return (1);
+ }
+ }
+ } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
+ /*
+ * Derivation Valid (Extension)
+ * At this point the type and the base have both, either
+ * no wildcard or a wildcard.
+ */
+ if ((baseType->attributeWildcard != NULL) &&
+ (baseType->attributeWildcard != type->attributeWildcard)) {
+ /* 1.3 */
+ if (xmlSchemaIsWildcardNsConstraintSubset(ctxt,
+ baseType->attributeWildcard, type->attributeWildcard) == 0) {
+ xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_COS_CT_EXTENDS_1_3,
+ "The wildcard in the derived type \"%s\" is not a valid "
+ "superset of the one in the base type \"%s\".\n",
+ type->name, baseType->name);
+ return (1);
+ }
+ }
+ }
+
+ /*
+ * 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)
+ * TODO: derivation-ok-restriction 2.1.3
+ */
+ 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) &&
+ (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
+ 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: xmlSchemaBuildAttributeValidation: "
+ "attribute uses not builded on base type \"%s\".\n",
+ baseType->name, NULL);
+ }
+ return (0);
+}
+
+/**
+ * xmlSchemaTypeFinalContains:
+ * @schema: the schema
+ * @type: the type definition
+ * @final: the final
+ *
+ * Evaluates if a type definition contains the given "final".
+ * This does take "finalDefault" into account as well.
+ *
+ * Returns 1 if the type does containt the given "final",
+ * 0 otherwise.
+ */
+static int
+xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
+{
+ int tfinal = final, tflags = type->flags;
+
+ if (type == NULL)
+ return (0);
+ if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
+ switch (final) {
+ case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
+ tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
+ break;
+ case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
+ tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
+ break;
+ case XML_SCHEMAS_TYPE_FINAL_LIST:
+ tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
+ break;
+ case XML_SCHEMAS_TYPE_FINAL_UNION:
+ tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
+ break;
+ }
+ tflags = schema->flags;
+ }
+ if (tflags & tfinal)
+ return (1);
+ else
+ return (0);
+
+}
+
+/**
+ * xmlSchemaGetUnionSimpleTypeMemberTypes:
+ * @type: the Union Simple Type
+ *
+ * Returns a list of member types of @type if existing,
+ * returns NULL otherwise.
+ */
+static xmlSchemaTypeLinkPtr
+xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
+{
+ while (type != NULL) {
+ if (type->memberTypes != NULL)
+ return (type->memberTypes);
+ else
+ type = type->baseType;
+ }
+ return (NULL);
+}
+
+/**
+ * xmlSchemaGetListSimpleTypeItemType:
+ * @type: the simple type definition
+ *
+ * Returns the item type definition of the list simple type.
+ */
+static xmlSchemaTypePtr
+xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
+{
+ if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
+ return (NULL);
+ /*
+ * Note: In libxml2, the built-in types do not reflect
+ * the datatype hierarchy (yet?) - we have to treat them
+ * in a special way.
+ */
+ if (type->type == XML_SCHEMA_TYPE_BASIC)
+ return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
+ if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
+ /* 1 If the <list> alternative is chosen, then the type
+ * definition ·resolved· to by the ·actual value· of the
+ * itemType [attribute] of <list>, if present, otherwise
+ * the type definition corresponding to the <simpleType>
+ * among the [children] of <list>.
+ */
+ return (type->subtypes->subtypes);
+ else {
+ /* 2 If the <restriction> option is chosen, then the
+ * {item type definition} of the {base type definition}.
+ */
+ return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
+ }
+}
+
+/**
+ * xmlSchemaCheckCOSSTDerivedOK:
+ * @type: the derived simple type definition
+ * @baseType: the base type definition
+ *
+ * Checks wheter @type can be validly
+ * derived from @baseType.
+ *
+ * Returns 0 on success, an positive error code otherwise.
+ */
+static int
+xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
+ xmlSchemaTypePtr type,
+ xmlSchemaTypePtr baseType,
+ int subset)
+{
+ /*
+ * Schema Component Constraint: Type Derivation OK (Simple)
+ *
+ *
+ * 1 They are the same type definition.
+ * TODO: The identy check might have to be more complex than this.
+ */
+ if (type == baseType)
+ return (0);
+ /*
+ * 2.1 restriction is not in the subset, or in the {final}
+ * of its own {base type definition};
+ */
+ if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
+ (xmlSchemaTypeFinalContains(schema,
+ type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
+ return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
+ }
+ /* 2.2 */
+ if (type->baseType == baseType) {
+ /*
+ * 2.2.1 D's ·base type definition· is B.
+ */
+ return (0);
+ }
+ /*
+ * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
+ * and is validly derived from B given the subset, as defined by this
+ * constraint.
+ */
+ if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
+ (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
+ return (0);
+ }
+ /*
+ * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
+ * definition·.
+ */
+ if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
+ (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
+ (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
+ return (0);
+ }
+ /*
+ * 2.2.4 B's {variety} is union and D is validly derived from a type
+ * definition in B's {member type definitions} given the subset, as
+ * defined by this constraint.
+ *
+ * NOTE: This seems not to involve built-in types, since there is no
+ * built-in Union Simple Type.
+ */
+ if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
+ xmlSchemaTypeLinkPtr cur;
+
+ cur = baseType->memberTypes;
+ while (cur != NULL) {
+ if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
+ cur->type, subset) == 0)
+ return (0);
+ cur = cur->next;
+ }
+ }
+
+ return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
+}
+
+
+/**
+ * xmlSchemaCheckSTPropsCorrect:
+ * @ctxt: the schema parser context
+ * @type: the simple type definition
+ *
+ * Checks st-props-correct.
+ *
+ * Returns 0 if the properties are correct,
+ * if not, a positive error code and -1 on internal
+ * errors.
+ */
+static int
+xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
+ xmlSchemaTypePtr type)
+{
+ xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
+ anyType;
+
+ /*
+ * Schema Component Constraint: Simple Type Definition Properties Correct
+ *
+ * NOTE: This is somehow redundant, since we actually built a simple type
+ * to have all the needed information; this acts as an self test.
+ */
+ anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
+ anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
+ /*
+ * TODO: 1 The values of the properties of a simple type definition must be as
+ * described in the property tableau in Datatype definition, modulo the
+ * impact of Missing Sub-components (§5.3).
+ */
+ /* Base type: If the datatype has been ·derived· by ·restriction·
+ * then the Simple Type Definition component from which it is ·derived·,
+ * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
+ */
+ if (baseType == NULL) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_ST_PROPS_CORRECT_1,
+ "Simple type \"%s\" does not have a base type.\n",
+ type->name, NULL);
+ return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
+ }
+ if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
+ ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
+ (baseType == anyType))) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_ST_PROPS_CORRECT_1,
+ "Simple type \"%s\": its base type \"%s\" is not a simple "
+ "type.\n",
+ type->name, baseType->name);
+ return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
+ }
+ if ((baseType != anySimpleType) &&
+ (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_ST_PROPS_CORRECT_1,
+ "Simple type \"%s\" (not derived by restriction) must have"
+ "the simple ur-type definition as base type, not \"%s\".\n",
+ type->name, NULL);
+ return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
+ }
+ /*
+ * Variety: One of {atomic, list, union}.
+ */
+ if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
+ ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
+ ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_ST_PROPS_CORRECT_1,
+ "Simple type \"%s\" has an absent variety.\n",
+ type->name, NULL);
+ return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
+ }
+ /* TODO: Finish this. */
+
+ /*
+ * 2 All simple type definitions must be derived ultimately from the ·simple
+ * ur-type definition (so· circular definitions are disallowed). That is, it
+ * must be possible to reach a built-in primitive datatype or the ·simple
+ * ur-type definition· by repeatedly following the {base type definition}.
+ */
+ baseType = type->baseType;
+ while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
+ if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
+ xmlSchemaTypeFixup(baseType, ctxt, NULL);
+ if (baseType == anySimpleType)
+ break;
+ else if (baseType == type) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_ST_PROPS_CORRECT_2,
+ "Simple type \"%s\" is not derived from the simple "
+ "ur-type definition (circular definitions are disallowed).\n",
+ type->name, NULL);
+ return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
+ }
+ baseType = baseType->baseType;
+ }
+ /*
+ * 3 The {final} of the {base type definition} must not contain restriction.
+ */
+ if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
+ XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_ST_PROPS_CORRECT_3,
+ "Simple type \"%s\": the \"final\" of its base type "
+ "\"%s\" must not contain \"restriction\".\n",
+ type->name, baseType->name);
+ return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
+ }
+ return (0);
+}
+
+/**
+ * xmlSchemaCheckDerivationValidSimpleRestriction:
+ * @ctxt: the schema parser context
+ * @type: the simple type definition
+ *
+ * Checks if the given @type (simpleType) is derived
+ * validly by restriction.
+ *
+ * Returns -1 on internal errors, 0 if the type is validly derived,
+ * a positive error code otherwise.
+ */
+static int
+xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
+ xmlSchemaTypePtr type)
+{
+
+ if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_ERR_INTERNAL_ERROR,
+ "xmlSchemaCheckDerivationValidSimpleRestriction: the given "
+ "type \"%s\" is not a user-derived simpleType.\n",
+ type->name, NULL);
+ return (-1);
+ }
+
+ if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
+ xmlSchemaTypePtr primitive;
+ /*
+ * 1.1 The {base type definition} must be an atomic simple
+ * type definition or a built-in primitive datatype.
+ */
+ if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
+ "Atomic simple type \"%s\": "
+ "its base type \"%s\" is not an atomic simple type.\n",
+ type->name, NULL);
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
+ }
+ /* 1.2 The {final} of the {base type definition} must not contain
+ * restriction.
+ */
+ /* OPTIMIZE: This is already done in xmlSchemaCheckStPropsCorrect */
+ if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
+ XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
+ "Atomic simple type \"%s\": the \"final\" of its base type "
+ "\"%s\" must not contain \"restriction\".\n",
+ type->name, type->baseType->name);
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
+ }
+
+ /*
+ * 1.3.1 DF must be an allowed constraining facet for the {primitive
+ * type definition}, as specified in the appropriate subsection of 3.2
+ * Primitive datatypes.
+ */
+ if (type->facets != NULL) {
+ xmlSchemaFacetPtr facet;
+ int ok = 1;
+
+ primitive = xmlSchemaGetPrimitiveType(type);
+ if (primitive == NULL) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_ERR_INTERNAL_ERROR,
+ "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
+ "to get primitive type of type \"%s\".\n",
+ type->name, NULL);
+ return (-1);
+ }
+ facet = type->facets;
+ do {
+ if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
+ xmlSchemaPErrExt(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
+ NULL, NULL, NULL,
+ "Atomic simple type \"%s\": the facet \"%s\" "
+ "is not allowed on primitive type \"%s\".\n",
+ type->name,
+ (const xmlChar *)
+ xmlSchemaFacetTypeToString(facet->type),
+ BAD_CAST primitive->name, NULL, NULL);
+
+ ok = 0;
+ }
+ facet = facet->next;
+ } while (facet != NULL);
+ if (ok == 0)
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
+
+ }
+ /*
+ * TODO: 1.3.2 (facet derivation)
+ */
+ } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
+ xmlSchemaTypePtr itemType = NULL;
+
+ itemType = xmlSchemaGetListSimpleTypeItemType(type);
+ if (itemType == NULL) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_ERR_INTERNAL_ERROR,
+ "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
+ "failed to evaluate the item type of type \"%s\".\n",
+ type->name, NULL);
+ return (-1);
+ }
+ /*
+ * 2.1 The {item type definition} must have a {variety} of atomic or
+ * union (in which case all the {member type definitions}
+ * must be atomic).
+ */
+ if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
+ ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
+ "List simple type \"%s\": its item type \"%s\" "
+ "is not an atomic or union simple type.\n",
+ type->name, itemType->name);
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
+ } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
+ xmlSchemaTypeLinkPtr member;
+
+ member = itemType->memberTypes;
+ while (member != NULL) {
+ if ((member->type->flags &
+ XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
+ "List simple type \"%s\": its item type "
+ "is a union simple type, but the member type "
+ "\"%s\" of this item type is not an \"atomic\" "
+ "simple type.\n",
+ type->name, member->type->name);
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
+ }
+ member = member->next;
+ }
+ }
+
+ if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
+ xmlSchemaFacetPtr facet;
+ /*
+ * This is the case if we have: <simpleType><list ..
+ */
+ /*
+ * 2.3.1
+ * 2.3.1.1 The {final} of the {item type definition} must not
+ * contain list.
+ */
+ if (xmlSchemaTypeFinalContains(ctxt->schema,
+ itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
+ "List simple type \"%s\": the \"final\" of its item type "
+ "\"%s\" must not contain \"list\".\n",
+ type->name, itemType->name);
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
+ }
+ /*
+ * 2.3.1.2 The {facets} must only contain the whiteSpace
+ * facet component.
+ */
+ if (type->facets != NULL) {
+ facet = type->facets;
+ do {
+ if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
+ "List simple type \"%s\": the facet \"%s\" "
+ "is not allowed.\n",
+ type->name,
+ BAD_CAST xmlSchemaFacetTypeToString(facet->type));
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
+ }
+ facet = facet->next;
+ } while (facet != NULL);
+ }
+ /*
+ * TODO: Datatypes states:
+ * A ·list· datatype can be ·derived· from an ·atomic· datatype
+ * whose ·lexical space· allows space (such as string or anyURI)or
+ * a ·union· datatype any of whose {member type definitions}'s
+ * ·lexical space· allows space.
+ */
+ } else {
+ /*
+ * This is the case if we have: <simpleType><restriction ...
+ */
+ /*
+ * 2.3.2
+ * 2.3.2.1 The {base type definition} must have a {variety} of list.
+ */
+ if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
+ "List simple type \"%s\": its base type \"%s\" must "
+ "have a variety of list.\n",
+ type->name, type->baseType->name);
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
+ }
+ /*
+ * 2.3.2.2 The {final} of the {base type definition} must not
+ * contain restriction.
+ */
+ if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
+ XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
+ "List simple type \"%s\": its base type \"%s\" must not "
+ "have a \"final\" containing \"restriction\".\n",
+ type->name, type->baseType->name);
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
+ }
+ /*
+ * 2.3.2.3 The {item type definition} must be validly derived
+ * from the {base type definition}'s {item type definition} given
+ * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
+ */
+ {
+ xmlSchemaTypePtr baseItemType;
+
+ baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
+ if (baseItemType == NULL) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_ERR_INTERNAL_ERROR,
+ "xmlSchemaCheckDerivationValidSimpleRestriction: "
+ "List simple type \"%s\": failed to "
+ "evaluate the item type of its base type \"%s\".\n",
+ type->name, type->baseType->name);
+ return (-1);
+ }
+ if ((itemType != baseItemType) &&
+ (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
+ baseItemType, 0) != 0)) {
+ xmlSchemaPErrExt(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3, NULL, NULL, NULL,
+ "List simple type \"%s\": its item type \"%s\" is not "
+ "validly derived from the item type \"%s\" of the "
+ "base type \"%s\" as defined in Type Derivation OK "
+ "(Simple).\n",
+ type->name, itemType->name, baseItemType->name,
+ type->baseType->name, NULL);
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
+ }
+ }
+
+ if (type->facets != NULL) {
+ xmlSchemaFacetPtr facet;
+ int ok = 1;
+ /*
+ * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
+ * and enumeration facet components are allowed among the {facets}.
+ */
+ facet = type->facets;
+ do {
+ switch (facet->type) {
+ case XML_SCHEMA_FACET_LENGTH:
+ case XML_SCHEMA_FACET_MINLENGTH:
+ case XML_SCHEMA_FACET_MAXLENGTH:
+ case XML_SCHEMA_FACET_WHITESPACE:
+ /*
+ * TODO: 2.5.1.2 List datatypes
+ * The value of ·whiteSpace· is fixed to the value collapse.
+ */
+ case XML_SCHEMA_FACET_PATTERN:
+ case XML_SCHEMA_FACET_ENUMERATION:
+ break;
+ default: {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
+ "List simple type \"%s\": the facet \"%s\" "
+ "is not allowed.\n",
+ type->name,
+ BAD_CAST xmlSchemaFacetTypeToString(facet->type));
+ /*
+ * We could return, but it's nicer to report all
+ * invalid facets.
+ */
+ ok = 0;
+ }
+ }
+ facet = facet->next;
+ } while (facet != NULL);
+ if (ok == 0)
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
+ /*
+ * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
+ * is a facet of the same kind in the {facets} of the {base type
+ * definition} (call this BF),then the DF's {value} must be a valid
+ * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
+ */
+ }
+
+
+ }
+ } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
+ /*
+ * 3.1 The {member type definitions} must all have {variety} of
+ * atomic or list.
+ */
+ xmlSchemaTypeLinkPtr member;
+
+ member = type->memberTypes;
+ while (member != NULL) {
+ if (((member->type->flags &
+ XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
+ ((member->type->flags &
+ XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
+ "Union simple type \"%s\": the member type "
+ "\"%s\" is not an \"atomic\" simple type.\n",
+ type->name, member->type->name);
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
+ }
+ member = member->next;
+ }
+ /*
+ * 3.3.1 If the {base type definition} is the ·simple ur-type
+ * definition·
+ */
+ if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
+ /*
+ * 3.3.1.1 All of the {member type definitions} must have a
+ * {final} which does not contain union.
+ */
+ member = type->memberTypes;
+ while (member != NULL) {
+ if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
+ XML_SCHEMAS_TYPE_FINAL_UNION)) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
+ "Union simple type \"%s\": the \"final\" of member type "
+ "\"%s\" contains \"union\".\n",
+ type->name, member->type->name);
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
+ }
+ member = member->next;
+ }
+ /*
+ * 3.3.1.2 The {facets} must be empty.
+ */
+ if (type->facetSet != NULL) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
+ "Union simple type \"%s\": the facets must be empty.\n",
+ type->name, NULL);
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
+ }
+ } else {
+ /*
+ * 3.3.2.1 The {base type definition} must have a {variety} of union.
+ */
+ if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
+ "Union simple type \"%s\": its base type \"%s\" has not a "
+ "variety of union.\n",
+ type->name, type->baseType->name);
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
+ }
+ /*
+ * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
+ */
+ if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
+ XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
+ "Union simple type \"%s\": the \"final\" of its base "
+ "type \"%s\" must not contain \"restriction\".\n",
+ type->name, type->baseType->name);
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
+ }
+ /*
+ * 3.3.2.3 The {member type definitions}, in order, must be validly
+ * derived from the corresponding type definitions in the {base
+ * type definition}'s {member type definitions} given the empty set,
+ * as defined in Type Derivation OK (Simple) (§3.14.6).
+ */
+ {
+ xmlSchemaTypeLinkPtr baseMember;
+
+ /*
+ * OPTIMIZE: if the type is restricting, it has no local defined
+ * member types and inherits the member types of the base type;
+ * thus a check for equality can be skipped.
+ */
+ /*
+ * TODO: Even worse: I cannot see a scenario where a restricting
+ * union simple type can have other member types as the member
+ * types of it's base type. This check seems not necessary with
+ * respect to the derivation process in libxml2.
+ */
+ if (type->memberTypes != NULL) {
+ member = type->memberTypes;
+ baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
+ if ((member == NULL) && (baseMember != NULL)) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: "
+ "xmlSchemaCheckDerivationValidSimpleRestriction "
+ "(3.3.2.3), union simple type \"%s\", unequal number "
+ "of member types in the base type\n",
+ type->name, NULL);
+ }
+ while (member != NULL) {
+ if (baseMember == NULL) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: "
+ "xmlSchemaCheckDerivationValidSimpleRestriction "
+ "(3.3.2.3), union simple type \"%s\", unequal number "
+ "of member types in the base type\n",
+ type->name, NULL);
+ }
+ if ((member->type != baseMember->type) &&
+ (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
+ member->type, baseMember->type, 0) != 0)) {
+ xmlSchemaPErrExt(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3, NULL,
+ NULL, NULL,
+ "Union simple type \"%s\": its member type "
+ "\"%s\" is not validly derived from its "
+ "corresponding member type \"%s\" of the base "
+ "type \"%s\" as defined in Type Derivation OK "
+ "(Simple).\n",
+ type->name, member->type->name,
+ baseMember->type->name,
+ type->baseType->name, NULL);
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
+ }
+ member = member->next;
+ baseMember = baseMember->next;
+ }
+ }
+ }
+ /*
+ * 3.3.2.4 Only pattern and enumeration facet components are
+ * allowed among the {facets}.
+ */
+ if (type->facets != NULL) {
+ xmlSchemaFacetPtr facet;
+ int ok = 1;
+
+ facet = type->facets;
+ do {
+ if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
+ (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
+ "Union simple type \"%s\": the facet \"%s\" "
+ "is not allowed.\n",
+ type->name,
+ BAD_CAST xmlSchemaFacetTypeToString(facet->type));
+ ok = 0;
+ }
+ facet = facet->next;
+ } while (facet != NULL);
+ if (ok == 0)
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
+
+ }
+ /*
+ * TODO: 3.3.2.5 (facet derivation)
+ */
+ }
+ }
+
+ return (0);
+}
+
+/**
+ * xmlSchemaCheckSRCSimpleType:
+ * @ctxt: the schema parser context
+ * @type: the simple type definition
+ *
+ * Checks crc-simple-type constraints.
+ *
+ * Returns 0 if the constraints are satisfied,
+ * if not a positive error code and -1 on internal
+ * errors.
+ */
+static int
+xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
+ xmlSchemaTypePtr type)
+{
+ /*
+ * NOTE: src-simple-type 2-4 are redundant, since the checks
+ * were are done for the corresponding <restriction>, <list> and <union>
+ * elements, but W3C wants a <simpleType> error as well, so it gets one.
+ * Maby this can be skipped in the future, if we get sure it's not needed.
+ */
+ if (type->subtypes == NULL) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaCheckSRCSimpleType, "
+ "no subtype on simple type \"%s\".\n",
+ type->name, NULL);
+ return (-1);
+ }
+ /*
+ * src-simple-type.1 The corresponding simple type definition, if any,
+ * must satisfy the conditions set out in Constraints on Simple Type
+ * Definition Schema Components (§3.14.6).
+ */
+ if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
+ (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
+ /*
+ * TODO: Removed this, since it got annoying to get an
+ * extra error report, if anything failed until now.
+ * Enable this if needed.
+ */
+ /*
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
+ "Simple type \"%s\" does not satisfy the constraints "
+ "on simple type definitions.\n",
+ type->name, NULL);
+ */
+ return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
+ }
+
+ if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
+ /*
+ * src-simple-type.2 If the <restriction> alternative is chosen,
+ * either it must have a base [attribute] or a <simpleType> among its
+ * [children], but not both.
+ */
+ if (((type->subtypes->base == NULL) &&
+ ((type->subtypes->subtypes == NULL) ||
+ (type->subtypes->subtypes->type != XML_SCHEMA_TYPE_SIMPLE))) ||
+ ((type->subtypes->base != NULL) &&
+ (type->subtypes->subtypes != NULL) &&
+ (type->subtypes->subtypes->type == XML_SCHEMA_TYPE_SIMPLE))) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_SRC_SIMPLE_TYPE_2,
+ "Simple type \"%s\": "
+ "The <restriction> alternative is chosen, thus either the "
+ "\"base\" attribute or the <simpleType> child "
+ "must be present, but not both.\n",
+ type->name, NULL);
+ return (XML_SCHEMAP_SRC_SIMPLE_TYPE_2);
+ }
+ } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
+ /* src-simple-type.3 If the <list> alternative is chosen, either it must have
+ * an itemType [attribute] or a <simpleType> among its [children],
+ * but not both.
+ * NOTE: baseType is set to the local simple type definiton,
+ * if existent, at parse time. This is a hack and not nice.
+ */
+ if (((type->subtypes->base == NULL) &&
+ (type->baseType == NULL)) ||
+ ((type->subtypes->base != NULL) &&
+ (type->subtypes->baseType != NULL))) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
+ "Simple type \"%s\": "
+ "The <list> alternative is chosen, thus either the "
+ "\"itemType\" attribute or the <simpleType> child "
+ "must be present, but not both.\n",
+ type->name, NULL);
+ return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
+ }
+
+
+ } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
+ xmlSchemaTypeLinkPtr member;
+ xmlSchemaTypePtr ancestor, anySimpleType;
+
+ anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
+
+ /* src-simple-type.4 Circular union type definition is disallowed. That is, if
+ * the <union> alternative is chosen, there must not be any entries
+ * in the memberTypes [attribute] at any depth which resolve to the
+ * component corresponding to the <simpleType>.
+ */
+ member = type->memberTypes;
+ while (member != NULL) {
+ ancestor = member->type;
+ while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
+ if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
+ xmlSchemaTypeFixup(ancestor, ctxt, NULL);
+ if (ancestor == anySimpleType)
+ break;
+ else if (ancestor == type) {
+ xmlSchemaPErr(ctxt, type->node,
+ XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
+ "Simple type \"%s\" is not derived from the simple "
+ "ur-type definition (circular definitions are disallowed).\n",
+ type->name, NULL);
+ return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
+ } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
+ /*
+ * TODO: Although a list simple type must not have a union ST
+ * type as item type, which in turn has a list ST as member
+ * type, we will assume this here as well, since this check
+ * was not yet performed.
+ */
+
+ }
+ ancestor = ancestor->baseType;
+ }
+ member = member->next;
+ }
+
+ }
+
+ return (0);
}
/**
@@ -4781,162 +7846,269 @@ static void
xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
{
+ xmlSchemaTypePtr ctxtType;
+
if (typeDecl == NULL)
return;
+ /*
+ * Do not allow the following types to be typefixed, prior to
+ * the corresponding simple/complex types.
+ */
+ if (ctxt->ctxtType == NULL) {
+ switch (typeDecl->type) {
+ case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
+ case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
+ case XML_SCHEMA_TYPE_UNION:
+ case XML_SCHEMA_TYPE_RESTRICTION:
+ case XML_SCHEMA_TYPE_EXTENSION:
+ return;
+ default:
+ break;
+ }
+ }
if (name == NULL)
name = typeDecl->name;
if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
switch (typeDecl->type) {
- case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
- xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
- if (typeDecl->subtypes != NULL)
+ case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
+ if (typeDecl->subtypes != NULL) {
+ if (typeDecl->subtypes->contentType ==
+ XML_SCHEMA_CONTENT_UNKNOWN) {
+ xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
+ NULL);
+ }
typeDecl->contentType =
typeDecl->subtypes->contentType;
+ }
break;
}
case XML_SCHEMA_TYPE_RESTRICTION:{
+ xmlSchemaTypePtr base = NULL;
+
+ ctxt->ctxtType->flags |=
+ XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
if (typeDecl->subtypes != NULL)
xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
if (typeDecl->base != NULL) {
- xmlSchemaTypePtr baseType;
-
- baseType =
+ base =
xmlSchemaGetType(ctxt->schema, typeDecl->base,
typeDecl->baseNs);
- if (baseType == NULL) {
+ if (base == NULL) {
xmlSchemaPErr(ctxt, typeDecl->node,
- XML_SCHEMAP_UNKNOWN_BASE_TYPE,
- "Schemas: type %s base type %s not found\n",
- name, typeDecl->base);
- }
- typeDecl->baseType = baseType;
- }
- if (typeDecl->subtypes == NULL)
- if (typeDecl->baseType != NULL) {
- /* The base type might be not "type fixed" yet,
+ XML_SCHEMAP_SRC_RESOLVE,
+ "Restriction \"%s\": the QName \"%s\" of the "
+ "attribute \"base\" does not resolve to a schema "
+ "component.\n",
+ name, typeDecl->base);
+ } else if (base->contentType ==
+ XML_SCHEMA_CONTENT_UNKNOWN) {
+ /*
+ * 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);
+ /*
+ * TODO: Is a check for circular derivation already
+ * done?
+ */
+ xmlSchemaTypeFixup(base, ctxt, NULL);
+ }
+ }
+ if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
+ /*
+ * ComplexType restriction.
+ */
+ /*
+ * Base type: The type definition ·resolved· to by the ·actual
+ * value· of the base [attribute]
+ */
+ ctxt->ctxtType->baseType = base;
+ /*
+ * Content type.
+ */
+ if (typeDecl->subtypes == NULL)
+ /* 1.1.1 */
+ typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
+ else if ((typeDecl->subtypes->subtypes == NULL) &&
+ ((typeDecl->subtypes->type ==
+ XML_SCHEMA_TYPE_ALL)
+ || (typeDecl->subtypes->type ==
+ XML_SCHEMA_TYPE_SEQUENCE)))
+ /* 1.1.2 */
+ typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
+ else if ((typeDecl->subtypes->type ==
+ XML_SCHEMA_TYPE_CHOICE)
+ && (typeDecl->subtypes->subtypes == NULL))
+ /* 1.1.3 */
+ typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
+ else {
+ /* 1.2 and 2.X are applied at the other layer */
typeDecl->contentType =
- typeDecl->baseType->contentType;
+ XML_SCHEMA_CONTENT_ELEMENTS;
+ }
+ } else {
+ /*
+ * SimpleType restriction.
+ */
+ /* Base type:
+ * The Simple Type Definition component resolved to by
+ * the actual value of the base [attribute] or the
+ * <simpleType> [children], whichever is present.
+ */
+ if ((base == NULL) && (typeDecl->subtypes != NULL)) {
+ base = typeDecl->subtypes;
+ ctxt->ctxtType->baseType = base;
+ if (base->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
+ xmlSchemaTypeFixup(base, ctxt, NULL);
} else
- /* 1.1.1 */
- typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
- else if ((typeDecl->subtypes->subtypes == NULL) &&
- ((typeDecl->subtypes->type ==
- XML_SCHEMA_TYPE_ALL)
- || (typeDecl->subtypes->type ==
- XML_SCHEMA_TYPE_SEQUENCE)))
- /* 1.1.2 */
- typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
- else if ((typeDecl->subtypes->type ==
- XML_SCHEMA_TYPE_CHOICE)
- && (typeDecl->subtypes->subtypes == NULL))
- /* 1.1.3 */
- typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
- else {
- /* 1.2 and 2.X are applied at the other layer */
- typeDecl->contentType =
- XML_SCHEMA_CONTENT_ELEMENTS;
- }
+ ctxt->ctxtType->baseType = base;
+
+ if (((typeDecl->base == NULL) &&
+ ((typeDecl->subtypes == NULL) ||
+ (typeDecl->subtypes->type != XML_SCHEMA_TYPE_SIMPLE))) ||
+ ((typeDecl->base != NULL) &&
+ (typeDecl->subtypes != NULL) &&
+ (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SIMPLE))) {
+ /*
+ * src-restriction-base-or-simpleType
+ * Either the base [attribute] or the simpleType [child] of the
+ * <restriction> element must be present, but not both.
+ */
+ xmlSchemaPErr(ctxt, typeDecl->node,
+ XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
+ "Restriction \"%s\": "
+ "Either the \"base\" attribute or the <simpleType> child "
+ "must be present, but not both.\n",
+ typeDecl->name, NULL);
+ }
+ }
break;
}
case XML_SCHEMA_TYPE_EXTENSION:{
- xmlSchemaContentType explicitContentType;
- xmlSchemaTypePtr base;
-
- if (typeDecl->base != NULL) {
- xmlSchemaTypePtr baseType;
-
- baseType =
- xmlSchemaGetType(ctxt->schema, typeDecl->base,
- typeDecl->baseNs);
- if (baseType == NULL) {
- xmlSchemaPErr(ctxt, typeDecl->node,
- XML_SCHEMAP_UNKNOWN_BASE_TYPE,
- "Schemas: type %s base type %s not found\n",
- name, typeDecl->base);
- }
- typeDecl->baseType = baseType;
- }
- if (typeDecl->subtypes != NULL)
- xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
-
- explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
- if (typeDecl->subtypes == NULL)
- /* 1.1.1 */
- explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
- else if ((typeDecl->subtypes->subtypes == NULL) &&
- ((typeDecl->subtypes->type ==
- XML_SCHEMA_TYPE_ALL)
- || (typeDecl->subtypes->type ==
- XML_SCHEMA_TYPE_SEQUENCE)))
- /* 1.1.2 */
- explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
- else if ((typeDecl->subtypes->type ==
- XML_SCHEMA_TYPE_CHOICE)
- && (typeDecl->subtypes->subtypes == NULL))
- /* 1.1.3 */
- explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
-
- base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
- typeDecl->baseNs);
- if (base == NULL) {
- xmlSchemaPErr(ctxt, typeDecl->node,
- XML_SCHEMAP_UNKNOWN_BASE_TYPE,
- "Schemas: base type %s of type %s not found\n",
- typeDecl->base, name);
- return;
- }
- if (typeDecl->recurse) {
+ xmlSchemaTypePtr base = NULL;
+ xmlSchemaContentType explicitContentType;
+
+ /*
+ * An extension does exist on a complexType only.
+ */
+ ctxt->ctxtType->flags |=
+ XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
+ 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",
name, NULL);
return;
}
- typeDecl->recurse = 1;
- xmlSchemaTypeFixup(base, ctxt, NULL);
- typeDecl->recurse = 0;
- if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
- /* 2.1 */
- typeDecl->contentType = base->contentType;
- } else if (base->contentType ==
- XML_SCHEMA_CONTENT_EMPTY) {
- /* 2.2 imbitable ! */
- typeDecl->contentType =
- XML_SCHEMA_CONTENT_ELEMENTS;
- } else {
- /* 2.3 imbitable pareil ! */
- typeDecl->contentType =
- XML_SCHEMA_CONTENT_ELEMENTS;
+ if (typeDecl->base != NULL) {
+ base =
+ xmlSchemaGetType(ctxt->schema, typeDecl->base,
+ typeDecl->baseNs);
+ if (base == NULL) {
+ xmlSchemaPErr(ctxt, typeDecl->node,
+ XML_SCHEMAP_SRC_RESOLVE,
+ "Extension \"%s\": the QName \"%s\" of the "
+ "attribute \"base\" does not resolve to a schema "
+ "component.\n",
+ name, typeDecl->base);
+ } else if (base->contentType ==
+ XML_SCHEMA_CONTENT_UNKNOWN) {
+ typeDecl->recurse = 1;
+ xmlSchemaTypeFixup(base, ctxt, NULL);
+ typeDecl->recurse = 0;
+ }
+ /*
+ * The type definition ·resolved· to by the ·actual
+ * value· of the base [attribute]
+ */
+ ctxt->ctxtType->baseType = base;
+ /*
+ * TODO: This one is still needed for computation of
+ * the content model by xmlSchemaBuildAContentModel.
+ * Try to get rid of it.
+ */
+ typeDecl->baseType = base;
}
+ if ((typeDecl->subtypes != NULL) &&
+ (typeDecl->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
+ xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
+
+ explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
+ if (typeDecl->subtypes == NULL)
+ /* 1.1.1 */
+ explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
+ else if ((typeDecl->subtypes->subtypes == NULL) &&
+ ((typeDecl->subtypes->type ==
+ XML_SCHEMA_TYPE_ALL)
+ || (typeDecl->subtypes->type ==
+ XML_SCHEMA_TYPE_SEQUENCE)))
+ /* 1.1.2 */
+ explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
+ else if ((typeDecl->subtypes->type ==
+ XML_SCHEMA_TYPE_CHOICE)
+ && (typeDecl->subtypes->subtypes == NULL))
+ /* 1.1.3 */
+ explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
+ if (base != NULL) {
+ /* It will be reported later, if the base is missing. */
+ if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
+ /* 2.1 */
+ typeDecl->contentType = base->contentType;
+ } else if (base->contentType ==
+ XML_SCHEMA_CONTENT_EMPTY) {
+ /* 2.2 imbitable ! */
+ typeDecl->contentType =
+ XML_SCHEMA_CONTENT_ELEMENTS;
+ } else {
+ /* 2.3 imbitable pareil ! */
+ typeDecl->contentType =
+ XML_SCHEMA_CONTENT_ELEMENTS;
+ }
+ }
break;
}
case XML_SCHEMA_TYPE_COMPLEX:{
+ ctxtType = ctxt->ctxtType;
+ ctxt->ctxtType = typeDecl;
+ if ((typeDecl->subtypes == NULL) ||
+ ((typeDecl->subtypes->type !=
+ XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
+ (typeDecl->subtypes->type !=
+ XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
+ /*
+ * This case is understood as shorthand for complex
+ * content restricting the ur-type definition, and
+ * the details of the mappings should be modified as
+ * necessary.
+ */
+ typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
+ typeDecl->flags |=
+ XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
+ }
if (typeDecl->subtypes == NULL) {
- typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
-
+ typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
typeDecl->contentType =
- XML_SCHEMA_CONTENT_MIXED;
+ XML_SCHEMA_CONTENT_MIXED;
} else {
- if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
+ if ((typeDecl->subtypes != NULL) &&
+ (typeDecl->subtypes->contentType ==
+ XML_SCHEMA_CONTENT_UNKNOWN)) {
+ xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
+ NULL);
+ }
+ if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
typeDecl->contentType =
XML_SCHEMA_CONTENT_MIXED;
- else {
- xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
- NULL);
- if (typeDecl->subtypes != NULL)
+ } else {
+ if (typeDecl->subtypes != NULL) {
typeDecl->contentType =
typeDecl->subtypes->contentType;
- }
- if (typeDecl->attributes == NULL)
- typeDecl->attributes =
- typeDecl->subtypes->attributes;
+ }
+ }
}
+ xmlSchemaBuildAttributeValidation(ctxt, typeDecl);
+ ctxt->ctxtType = ctxtType;
break;
}
case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
@@ -4946,42 +8118,174 @@ xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
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;
}
+ case XML_SCHEMA_TYPE_SIMPLE:
+ /*
+ * Simple Type Definition Schema Component
+ *
+ */
+ ctxtType = ctxt->ctxtType;
+ typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
+ if (typeDecl->subtypes->contentType ==
+ XML_SCHEMA_CONTENT_UNKNOWN) {
+ ctxt->ctxtType = typeDecl;
+ xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
+ }
+ /* Fixup base type */
+ if ((typeDecl->baseType != NULL) &&
+ (typeDecl->baseType->contentType ==
+ XML_SCHEMA_CONTENT_UNKNOWN)) {
+ /* OPTIMIZE: Actually this one will never by hit, since
+ * the base type is already type-fixed in <restriction>.
+ */
+ ctxt->ctxtType = typeDecl;
+ xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
+ }
+ /* Base type:
+ * 2 If the <list> or <union> alternative is chosen,
+ * then the ·simple ur-type definition·.
+ */
+ if (typeDecl->subtypes->type ==
+ XML_SCHEMA_TYPE_LIST) {
+ typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
+ typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
+ } else if (typeDecl->subtypes->type ==
+ XML_SCHEMA_TYPE_UNION) {
+ typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
+ typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
+ } else if (typeDecl->subtypes->type ==
+ XML_SCHEMA_TYPE_RESTRICTION) {
+ xmlSchemaFacetLinkPtr facet, cur, last = NULL;
+
+ /*
+ * Variety
+ * If the <restriction> alternative is chosen, then the
+ * {variety} of the {base type definition}.
+ */
+ if (typeDecl->baseType != NULL) {
+ if (typeDecl->baseType->flags &
+ XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
+ typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
+ else if (typeDecl->baseType->flags &
+ XML_SCHEMAS_TYPE_VARIETY_LIST)
+ typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
+ else if (typeDecl->baseType->flags &
+ XML_SCHEMAS_TYPE_VARIETY_UNION)
+ typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
+ /*
+ * Schema Component Constraint: Simple Type Restriction
+ * (Facets)
+ * NOTE: Satisfaction of 1 and 2 arise from the fixup
+ * applied beforehand.
+ *
+ * 3 The {facets} of R are the union of S and the {facets}
+ * of B, eliminating duplicates. To eliminate duplicates,
+ * when a facet of the same kind occurs in both S and the
+ * {facets} of B, the one in the {facets} of B is not
+ * included, with the exception of enumeration and pattern
+ * facets, for which multiple occurrences with distinct values
+ * are allowed.
+ */
+ if (typeDecl->baseType->facetSet != NULL) {
+ last = typeDecl->facetSet;
+ if (last != NULL)
+ while (last->next != NULL)
+ last = last->next;
+ cur = typeDecl->baseType->facetSet;
+ for (; cur != NULL; cur = cur->next) {
+ /*
+ * Base patterns won't be add here:
+ * they are ORed in a type and
+ * ANDed in derived types. This will
+ * happed at validation level by
+ * walking the base axis of the type.
+ */
+ if (cur->facet->type ==
+ XML_SCHEMA_FACET_PATTERN)
+ continue;
+ facet = NULL;
+ if ((typeDecl->facetSet != NULL) &&
+ (cur->facet->type !=
+ XML_SCHEMA_FACET_PATTERN) &&
+ (cur->facet->type !=
+ XML_SCHEMA_FACET_ENUMERATION)) {
+ facet = typeDecl->facetSet;
+ do {
+ if (cur->facet->type ==
+ facet->facet->type)
+ break;
+ facet = facet->next;
+ } while (facet != NULL);
+ }
+ if (facet == NULL) {
+ facet = (xmlSchemaFacetLinkPtr)
+ xmlMalloc(sizeof(xmlSchemaFacetLink));
+ if (facet == NULL) {
+ xmlSchemaPErrMemory(ctxt,
+ "fixing simpleType", NULL);
+ return;
+ }
+ facet->facet = cur->facet;
+ facet->next = NULL;
+ if (last == NULL)
+ typeDecl->facetSet = facet;
+ else
+ last->next = facet;
+ last = facet;
+ }
+ }
+ }
+ }
+ }
+ /*
+ * Check constraints.
+ */
+ xmlSchemaCheckSRCSimpleType(ctxt, typeDecl);
+ ctxt->ctxtType = ctxtType;
+ break;
case XML_SCHEMA_TYPE_SEQUENCE:
case XML_SCHEMA_TYPE_GROUP:
case XML_SCHEMA_TYPE_ALL:
case XML_SCHEMA_TYPE_CHOICE:
typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
break;
+ case XML_SCHEMA_TYPE_LIST:
+ xmlSchemaParseListRefFixup(typeDecl, ctxt);
+ typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
+ break;
+ case XML_SCHEMA_TYPE_UNION:
+ xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
+ typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
+ break;
case XML_SCHEMA_TYPE_BASIC:
case XML_SCHEMA_TYPE_ANY:
case XML_SCHEMA_TYPE_FACET:
- case XML_SCHEMA_TYPE_SIMPLE:
case XML_SCHEMA_TYPE_UR:
case XML_SCHEMA_TYPE_ELEMENT:
case XML_SCHEMA_TYPE_ATTRIBUTE:
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:
@@ -5025,9 +8329,12 @@ xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
case XML_SCHEMA_CONTENT_MIXED:
xmlGenericError(xmlGenericErrorContext, "mixed\n");
break;
+ /* Removed, since not used. */
+ /*
case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
break;
+ */
case XML_SCHEMA_CONTENT_BASIC:
xmlGenericError(xmlGenericErrorContext, "basic\n");
break;
@@ -5060,72 +8367,150 @@ xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
if (nonNegativeIntegerType == NULL) {
nonNegativeIntegerType =
- xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
- xmlSchemaNs);
+ xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
}
switch (facet->type) {
case XML_SCHEMA_FACET_MININCLUSIVE:
case XML_SCHEMA_FACET_MINEXCLUSIVE:
case XML_SCHEMA_FACET_MAXINCLUSIVE:
- case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
+ case XML_SCHEMA_FACET_MAXEXCLUSIVE:
+ case XML_SCHEMA_FACET_ENUMERATION: {
/*
* Okay we need to validate the value
* at that point.
*/
xmlSchemaValidCtxtPtr vctxt;
-
+ xmlSchemaTypePtr base;
+
+ /* 4.3.5.5 Constraints on enumeration Schema Components
+ * Schema Component Constraint: enumeration valid restriction
+ * It is an ·error· if any member of {value} is not in the
+ * ·value space· of {base type definition}.
+ *
+ * minInclusive, maxInclusive, minExclusive, maxExclusive:
+ * The value ·must· be in the
+ * ·value space· of the ·base type·.
+ */
+ /*
+ * This function is intended to deliver a compiled value
+ * on the facet. In XML Schemas the type holding a facet,
+ * cannot be a built-in type. Thus to ensure that other API
+ * calls (relaxng) do work, if the given type is a built-in
+ * type, we will assume that the given built-in type *is
+ * already* the base type.
+ */
+ if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
+ base = typeDecl->baseType;
+ if (base == NULL) {
+ xmlSchemaPErr(ctxt, typeDecl->node,
+ XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaCheckFacet, "
+ "the type \"%s\" has no base type.\n",
+ typeDecl->name, NULL);
+ return (-1);
+ }
+ } else
+ base = typeDecl;
+ /*
+ * TODO: Try to avoid creating a new context.
+ */
vctxt = xmlSchemaNewValidCtxt(NULL);
- if (vctxt == NULL)
- break;
- xmlSchemaValidateSimpleValue(vctxt, typeDecl,
- facet->value);
- facet->val = vctxt->value;
- vctxt->value = NULL;
- if (facet->val == NULL) {
+ if (vctxt == NULL) {
+ xmlSchemaPErr(ctxt, typeDecl->node,
+ XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaCheckFacet, "
+ "creating a new validation context.\n",
+ typeDecl->name, NULL);
+ return (-1);
+ }
+ vctxt->type = base;
+ ret = xmlSchemaValidateSimpleTypeValue(vctxt, facet->value, 0, 1);
+ facet->val = vctxt->value;
+ vctxt->value = NULL;
+ if (ret > 0) {
/* error code */
if (ctxt != NULL) {
- xmlSchemaPErr(ctxt, facet->node,
- XML_SCHEMAP_INVALID_FACET,
- "Schemas: type %s facet value %s invalid\n",
- name, facet->value);
+ xmlSchemaPErrExt(ctxt, facet->node,
+ XML_SCHEMAP_INVALID_FACET,
+ NULL, NULL, NULL,
+ "Type \"%s\": the value \"%s\" of the "
+ "facet \"%s\" is invalid.\n",
+ name, facet->value,
+ BAD_CAST xmlSchemaFacetTypeToString(facet->type),
+ NULL, NULL);
}
ret = -1;
- }
- xmlSchemaFreeValidCtxt(vctxt);
+ } else if (ret < 0) {
+ xmlSchemaPErrExt(ctxt, facet->node,
+ XML_SCHEMAS_ERR_INTERNAL,
+ NULL, NULL, NULL,
+ "Internal error: xmlSchemaCheckFacet, "
+ "failed to validate the value \"%s\" name of the "
+ "facet \"%s\" against the base type \"%s\".\n",
+ facet->value,
+ BAD_CAST xmlSchemaFacetTypeToString(facet->type),
+ base->name, NULL, NULL);
+ ret = -1;
+ }
+ xmlSchemaFreeValidCtxt(vctxt);
break;
}
+ /*
+ * Removed, since added to the case above.
+ *
case XML_SCHEMA_FACET_ENUMERATION:{
- /*
+ *
* Okay we need to validate the value
* at that point.
- */
+ *
xmlSchemaValidCtxtPtr vctxt;
int tmp;
+ xmlSchemaTypePtr base;
+ * 4.3.5.5 Constraints on enumeration Schema Components
+ * Schema Component Constraint: enumeration valid restriction
+ * It is an ·error· if any member of {value} is not in the
+ * ·value space· of {base type definition}.
+ *
vctxt = xmlSchemaNewValidCtxt(NULL);
if (vctxt == NULL)
break;
- tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
+ base = typeDecl->baseType;
+ if (base == NULL) {
+ xmlSchemaPErr(ctxt, typeDecl->node,
+ XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaCheckFacet, "
+ "the type \"%s\" has no base type.\n",
+ typeDecl->name, NULL);
+ return (-1);
+ }
+ vctxt->type = base;
+ tmp = xmlSchemaValidateSimpleTypeValue(vctxt, facet->value, 0, 1);
+ * tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
facet->value);
+ *
if (tmp != 0) {
if (ctxt != NULL) {
xmlSchemaPErr(ctxt, facet->node,
- XML_SCHEMAP_INVALID_ENUM,
- "Schemas: type %s enumeration value %s invalid\n",
- name, facet->value);
+ XML_SCHEMAP_INVALID_ENUM,
+ "Type \"%s\": the value \"%s\" of the "
+ "facet \"enumeration\" is invalid.\n",
+ name, facet->value);
}
ret = -1;
}
xmlSchemaFreeValidCtxt(vctxt);
break;
}
+ */
case XML_SCHEMA_FACET_PATTERN:
facet->regexp = xmlRegexpCompile(facet->value);
if (facet->regexp == NULL) {
xmlSchemaPErr(ctxt, typeDecl->node,
- XML_SCHEMAP_REGEXP_INVALID,
- "Schemas: type %s facet regexp %s invalid\n",
- name, facet->value);
+ XML_SCHEMAP_REGEXP_INVALID,
+ "Type \"%s\": the value \"%s\" of the "
+ "facet \"pattern\" is invalid.\n",
+ name, facet->value);
ret = -1;
}
break;
@@ -5143,10 +8528,14 @@ xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
if (tmp != 0) {
/* error code */
if (ctxt != NULL) {
- xmlSchemaPErr(ctxt, facet->node,
- XML_SCHEMAP_INVALID_FACET_VALUE,
- "Schemas: type %s facet value %s invalid\n",
- name, facet->value);
+ xmlSchemaPErrExt(ctxt, facet->node,
+ XML_SCHEMAP_INVALID_FACET_VALUE,
+ NULL, NULL, NULL,
+ "Type \"%s\": the value \"%s\" of the "
+ "facet \"%s\" is invalid.\n",
+ name, facet->value,
+ BAD_CAST xmlSchemaFacetTypeToString(facet->type),
+ NULL, NULL);
}
ret = -1;
}
@@ -5162,9 +8551,10 @@ xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
} else {
if (ctxt != NULL) {
xmlSchemaPErr(ctxt, facet->node,
- XML_SCHEMAP_INVALID_WHITE_SPACE,
- "Schemas: type %s whiteSpace value %s invalid\n",
- name, facet->value);
+ XML_SCHEMAP_INVALID_WHITE_SPACE,
+ "Type \"%s\": the value \"%s\" of the "
+ "facet \"whiteSpace\" is invalid.\n",
+ name, facet->value);
}
ret = -1;
}
@@ -5187,17 +8577,19 @@ xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
{
if (name == NULL)
- name = typeDecl->name;
- if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
- if (typeDecl->facets != NULL) {
- xmlSchemaFacetPtr facet = typeDecl->facets;
-
- while (facet != NULL) {
- xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
- facet = facet->next;
- }
- }
- }
+ name = typeDecl->name;
+ /*
+ * NOTE: It is intended to use the facets list, instead
+ * of facetSet.
+ */
+ if (typeDecl->facets != NULL) {
+ xmlSchemaFacetPtr facet = typeDecl->facets;
+
+ while (facet != NULL) {
+ xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
+ facet = facet->next;
+ }
+ }
}
/**
@@ -5209,32 +8601,41 @@ xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
* 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,
- XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
- "Schemas: attribute group %s reference %s not found\n",
- name, attrgrpDecl->ref);
+ xmlSchemaPErr(ctxt, attrgrp->node,
+ XML_SCHEMAP_SRC_RESOLVE,
+ "Attribute group \"%s\": the QName \"%s\" of the attribute "
+ "\"ref\" does not resolve to a schema "
+ "component.\n",
+ 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);
}
+ */
}
/**
@@ -5249,6 +8650,12 @@ static void
xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
{
+ /*
+ * The simple type definition corresponding to the <simpleType> element
+ * information item in the [children], if present, otherwise the simple
+ * type definition ·resolved· to by the ·actual value· of the type
+ * [attribute], if present, otherwise the ·simple ur-type definition·.
+ */
if (name == NULL)
name = attrDecl->name;
if (attrDecl->subtypes != NULL)
@@ -5256,31 +8663,34 @@ xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
if (attrDecl->typeName != NULL) {
xmlSchemaTypePtr type;
- type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
- attrDecl->typeNs);
- if (type == NULL) {
- xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
- "Schemas: attribute %s type %s not found\n",
- name, attrDecl->typeName);
- }
+ type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
+ attrDecl->typeNs);
+ if (type == NULL) {
+ xmlSchemaPErr(ctxt, attrDecl->node,
+ XML_SCHEMAP_SRC_RESOLVE,
+ "Attribute \"%s\": the QName \"%s\" of the attribute "
+ "\"type\" does not resolve to a schema "
+ "component.\n",
+ name, attrDecl->typeName);
+ }
attrDecl->subtypes = type;
} 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",
- name, attrDecl->ref);
+ xmlSchemaPErr(ctxt, attrDecl->node,
+ XML_SCHEMAP_SRC_RESOLVE,
+ "Attribute \"%s\": the QName \"%s\" of the attribute "
+ "\"ref\" does not resolve to a schema "
+ "component.\n",
+ name, attrDecl->ref);
return;
}
xmlSchemaAttrFixup(ref, ctxt, NULL);
attrDecl->subtypes = ref->subtypes;
- } else if (attrDecl->type != XML_SCHEMA_TYPE_ANY_ATTRIBUTE) {
- xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
- "Schemas: attribute %s has no type nor reference\n",
- name, NULL);
+ } else {
+ attrDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
}
}
@@ -5403,6 +8813,8 @@ xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
/*
* Then fixup all types properties
*/
+ ctxt->ctxtType = NULL;
+ ctxt->parentItem = NULL;
xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
/*
@@ -5506,72 +8918,54 @@ xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
static int
xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
xmlSchemaTypePtr base,
- xmlSchemaFacetPtr facets,
+ xmlSchemaFacetLinkPtr facets,
const xmlChar * value, int fireErrors)
{
int ret = 0;
int tmp = 0;
xmlSchemaTypeType type;
- xmlSchemaFacetPtr facet = facets;
+ xmlSchemaFacetLinkPtr facetLink = facets;
- while (facet != NULL) {
- type = facet->type;
+ while (facetLink != NULL) {
+ type = facetLink->facet->type;
if (type == XML_SCHEMA_FACET_ENUMERATION) {
tmp = 1;
- while (facet != NULL) {
+ while (facetLink != NULL) {
tmp =
- xmlSchemaValidateFacet(base, facet, value,
+ xmlSchemaValidateFacet(base, facetLink->facet, value,
ctxt->value);
if (tmp == 0) {
return 0;
}
- facet = facet->next;
+ facetLink = facetLink->next;
}
} else
- tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
+ tmp = xmlSchemaValidateFacet(base, facetLink->facet, value,
+ ctxt->value);
if (tmp != 0) {
ret = tmp;
- if (fireErrors)
- xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_FACET,
- "Failed to validate type with facet %s\n",
- (const xmlChar *) xmlSchemaFacetTypeToString(type),
- NULL);
+ if (fireErrors) {
+ xmlSchemaVErr(ctxt, ctxt->cur, tmp,
+ "The value failed to validate against the facet \"%s\".\n",
+ (const xmlChar *) xmlSchemaFacetTypeToString(type),
+ NULL);
+
+ }
}
- if (facet != NULL)
- facet = facet->next;
+ if (facetLink != NULL)
+ facetLink = facetLink->next;
}
return (ret);
}
-/**
- * xmlSchemaValidateFacets:
- * @ctxt: a schema validation context
- * @base: the base type
- * @facets: the list of facets to check
- * @value: the lexical repr of the value to validate
- * @val: the precomputed value
- *
- * Check a value against all facet conditions
- *
- * Returns 0 if the element is schemas valid, a positive error code
- * number otherwise and -1 in case of internal or API error.
- */
-static int
-xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
- xmlSchemaTypePtr base,
- xmlSchemaFacetPtr facets, const xmlChar * value)
-{
- return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
-}
-
/************************************************************************
* *
* Simple type validation *
* *
************************************************************************/
-
+#if 0 /* Not currently used. */
/**
* xmlSchemaValidateSimpleValueUnion:
* @ctxt: a schema validation context
@@ -5703,7 +9097,6 @@ xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
}
} else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
xmlSchemaTypePtr base;
- xmlSchemaFacetPtr facet;
base = type->baseType;
if (base != NULL) {
@@ -5718,9 +9111,11 @@ xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
* building the Schemas
*/
if (ctxt->schema != NULL) {
- if (ret == 0) {
- facet = type->facets;
- ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet,
+ xmlSchemaFacetLinkPtr facetLink;
+
+ if ((ret == 0) && (type->facetSet != NULL)) {
+ facetLink = type->facetSet;
+ ret = xmlSchemaValidateFacetsInternal(ctxt, base, facetLink,
value, fireErrors);
}
}
@@ -5774,6 +9169,7 @@ xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
}
return (ret);
}
+#endif
/************************************************************************
* *
@@ -5785,12 +9181,31 @@ static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
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 +9218,30 @@ static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
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 +9261,41 @@ static int
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);
+ "Attribute \"%s\" is not allowed.\n",
+ cur->attr->name, NULL);
+ else if (cur->state == XML_SCHEMAS_ATTR_PROHIBITED)
+ /*
+ * TODO: This won't ever be touched so remove it.
+ */
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
+ "Attribute \"%s\" is prohibited.\n",
+ cur->attr->name, NULL);
+ else if (cur->state == XML_SCHEMAS_ATTR_INVALID_VALUE) {
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRINVALID,
+ "Attribute \"%s\": the value is not valid.\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\" is required but missing.\n",
+ cur->decl->ref, NULL);
+ else
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
+ "Attribute \"%s\" is required but missing.\n",
+ cur->decl->name, NULL);
}
}
+ cur = cur->next;
+ }
+
return (ret);
}
@@ -5903,10 +9342,16 @@ xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
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:{
@@ -5951,38 +9396,6 @@ xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
}
/**
- * xmlSchemaSkipIgnored:
- * @ctxt: a schema validation context
- * @type: the current type context
- * @node: the top node.
- *
- * Skip ignorable nodes in that context
- *
- * Returns the new sibling
- * number otherwise and -1 in case of internal or API error.
- */
-static xmlNodePtr
-xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
- xmlSchemaTypePtr type, xmlNodePtr node)
-{
- int mixed = 0;
-
- /*
- * TODO complete and handle entities
- */
- mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
- (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
- while ((node != NULL) &&
- ((node->type == XML_COMMENT_NODE) ||
- ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
- (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
- (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
- node = node->next;
- }
- return (node);
-}
-
-/**
* xmlSchemaValidateCallback:
* @ctxt: a schema validation context
* @name: the name of the element detected (might be NULL)
@@ -6047,7 +9460,7 @@ xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
ret = xmlSchemaValidateCheckNodeList(child);
if (ret < 0) {
xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
- "Internal error: xmlSchemaValidateSimpleType %s content\n",
+ "Internal error: xmlSchemaValidateSimpleRestrictionType %s content\n",
node->name, NULL);
return (-1);
} else if (ret == 0) {
@@ -6063,6 +9476,7 @@ xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
}
#endif
+#if 0 /* Not used any more */
/**
* xmlSchemaValidateSimpleType:
* @ctxt: a schema validation context
@@ -6147,22 +9561,18 @@ xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
value = xmlNodeGetContent(child);
switch (variety->type) {
case XML_SCHEMA_TYPE_RESTRICTION:{
- xmlSchemaFacetPtr facet;
-
base = variety->baseType;
if (base != NULL) {
ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
} else {
- TODO}
- if (ret == 0) {
- facet = variety->facets;
- ret =
- xmlSchemaValidateFacets(ctxt, base, facet, value);
- }
+ TODO}
+
+ /* 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:
@@ -6178,6 +9588,9 @@ xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
ret = ctxt->err;
}
}
+ if ((ret == 0) && (variety->facetSet != NULL)) {
+ ret = xmlSchemaValidateFacets(ctxt, base, variety->facetSet, value);
+ }
if (value != NULL)
xmlFree(value);
@@ -6188,6 +9601,496 @@ xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
ctxt->type = type;
return (ret);
}
+#endif
+
+/**
+ * xmlSchemaValidateSimpleTypeValue:
+ * @ctxt: a schema validation context
+ * @value: the value to be validated
+ * @fireErrors: shall errors be reported?
+ * @applyFacets: shall facets be applied?
+ *
+ * Validates a value by the given type (user derived or built-in).
+ *
+ * Returns 0 if the value is valid, a positive error code
+ * number otherwise and -1 in case of an internal or API error.
+ * Note on reported errors: Although it might be nice to report
+ * the name of the simple/complex type, used to validate the content
+ * of a node, it is quite unnecessary: for global defined types
+ * the local name of the element is equal to the NCName of the type,
+ * for local defined types it makes no sense to output the internal
+ * computed name of the type. TODO: Instead, one should attach the
+ * struct of the type involved to the error handler - this allows
+ * the report of any additional information by the user.
+ * TODO: Correct character normalization of union simple types.
+ */
+static int
+xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
+ const xmlChar *value,
+ int fireErrors,
+ int applyFacets)
+{
+ xmlSchemaTypePtr type;
+ int ret = 0;
+ type = ctxt->type;
+
+ if (type->type == XML_SCHEMA_TYPE_BASIC) {
+ xmlNodePtr child;
+
+ if (ctxt->value != NULL) {
+ xmlSchemaFreeValue(ctxt->value);
+ ctxt->value = NULL;
+ }
+ child = ctxt->node;
+ while (child != NULL) {
+ switch (child->type) {
+ case XML_TEXT_NODE:
+ case XML_CDATA_SECTION_NODE:
+ case XML_PI_NODE:
+ case XML_COMMENT_NODE:
+ case XML_XINCLUDE_START:
+ case XML_XINCLUDE_END:
+ break;
+ case XML_ENTITY_REF_NODE:
+ case XML_ENTITY_NODE:
+ TODO break;
+ case XML_ELEMENT_NODE:
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INVALIDELEM,
+ "Element \"%s\": child \"%s\" should not be present.\n",
+ ctxt->cur->name, child->name);
+ return (ctxt->err);
+ case XML_ATTRIBUTE_NODE:
+ case XML_DOCUMENT_NODE:
+ case XML_DOCUMENT_TYPE_NODE:
+ case XML_DOCUMENT_FRAG_NODE:
+ case XML_NOTATION_NODE:
+ case XML_HTML_DOCUMENT_NODE:
+ case XML_DTD_NODE:
+ case XML_ELEMENT_DECL:
+ case XML_ATTRIBUTE_DECL:
+ case XML_ENTITY_DECL:
+ case XML_NAMESPACE_DECL:
+#ifdef LIBXML_DOCB_ENABLED
+ case XML_DOCB_DOCUMENT_NODE:
+#endif
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INVALIDELEM,
+ "Element \"%s\": node type of node unexpected here.\n",
+ ctxt->cur->name, NULL);
+ return (ctxt->err);
+ }
+ child = child->next;
+ }
+ ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
+ ctxt->cur);
+ if (ret > 0) {
+ if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
+ ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
+ else
+ ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
+ if (fireErrors) {
+ if (ctxt->cur->type == XML_ATTRIBUTE_NODE)
+ xmlSchemaVErr(ctxt, ctxt->cur,
+ XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
+ "The value of attribute \"%s\" is not valid.\n",
+ ctxt->cur->name, NULL);
+ else
+ xmlSchemaVErr(ctxt, ctxt->cur,
+ XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
+ "The value is not valid.\n",
+ NULL, NULL);
+ }
+ } else if (ret < 0) {
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateSimpleTypeValue, "
+ "validating built-in type \"%s\"\n",
+ type->name, NULL);
+ }
+ } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
+ /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
+ * a literal in the ·lexical space· of {base type definition}
+ */
+ ctxt->type = type->baseType;
+ ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 0);
+ if (ret < 0) {
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateSimpleTypeValue, "
+ "validating atomic simple type \"%s\"\n",
+ type->name, NULL);
+ } else if (ret > 0) {
+ ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
+ if (fireErrors) {
+ xmlSchemaVErr(ctxt, ctxt->cur,
+ XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
+ "The value is not valid.\n",
+ NULL, NULL);
+ }
+
+ } else if ((applyFacets) &&
+ (type->facetSet != NULL)) {
+ xmlSchemaTypePtr builtIn;
+
+ /*
+ * Check facets. Be sure to pass the built-in type to
+ * xmlSchemaValidateFacetsInternal.
+ */
+ builtIn = type->baseType;
+ while (builtIn->type != XML_SCHEMA_TYPE_BASIC)
+ builtIn = builtIn->baseType;
+ ret = xmlSchemaValidateFacetsInternal(ctxt, builtIn,
+ type->facetSet, value, fireErrors);
+ if (ret < 0) {
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateSimpleTypeValue, "
+ "validating facets of atomic simple type \"%s\"\n",
+ type->name, NULL);
+ } else if (ret > 0) {
+ ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
+ if (fireErrors) {
+ xmlSchemaVErr(ctxt, ctxt->cur,
+ XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
+ "The value is not valid.\n",
+ NULL, NULL);
+ }
+ }
+ }
+ } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
+
+ xmlSchemaTypePtr tmpType;
+ const xmlChar *cur, *end;
+ xmlChar *tmp;
+ int len = 0;
+
+ /* 1.2.2 if {variety} is ·list· then the string must be a sequence
+ * of white space separated tokens, each of which ·match·es a literal
+ * in the ·lexical space· of {item type definition}
+ */
+
+ tmpType = xmlSchemaGetListSimpleTypeItemType(type);
+ cur = value;
+ do {
+ while (IS_BLANK_CH(*cur))
+ cur++;
+ end = cur;
+ while ((*end != 0) && (!(IS_BLANK_CH(*end))))
+ end++;
+ if (end == cur)
+ break;
+ tmp = xmlStrndup(cur, end - cur);
+ len++;
+ ctxt->type = tmpType;
+ ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmp, 0, 1);
+ xmlFree(tmp);
+ if (ret > 0) {
+ ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
+ if (fireErrors) {
+ xmlSchemaVErr(ctxt, ctxt->cur,
+ XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
+ "The value is not valid.\n",
+ NULL, NULL);
+ }
+ break;
+ } else if (ret < 0)
+ break;
+ cur = end;
+ } while (*cur != 0);
+ /*
+ * Check facets.
+ */
+ if (ret < 0) {
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateSimpleTypeValue, "
+ "validating list simple type \"%s\"\n",
+ type->name, NULL);
+ } else if ((ret == 0) && (applyFacets) &&
+ (type->facetSet != NULL)) {
+ int okFacet = 0, hasFacet = 0;
+ unsigned long expLen;
+ xmlSchemaFacetPtr facet;
+ xmlSchemaFacetLinkPtr facetLink;
+ xmlChar *collapsedValue = NULL;
+
+ /*
+ * The value of ·whiteSpace· is fixed to the value collapse.
+ */
+ collapsedValue = xmlSchemaCollapseString((const xmlChar *) value);
+ if (collapsedValue != NULL)
+ value = (const xmlChar *) collapsedValue;
+ facetLink = type->facetSet;
+ do {
+ facet = facetLink->facet;
+ /*
+ * List types need a special facet treatment.
+ * Skip whiteSpace, since it is fixed to "collapse".
+ */
+ if ((facet->type != XML_SCHEMA_FACET_WHITESPACE) &&
+ (facet->type != XML_SCHEMA_FACET_PATTERN)) {
+ ret = xmlSchemaValidateListSimpleTypeFacet(facet, value,
+ len, &expLen);
+ if (facet->type == XML_SCHEMA_FACET_ENUMERATION) {
+ hasFacet = 1;
+ if (ret == 0)
+ okFacet = 1;
+ } else if ((ret > 0) && (fireErrors)) {
+ char l[25], fl[25];
+ /* FIXME: What is the max expected string length of the
+ * length value?
+ */
+ snprintf(l, 24, "%d", len);
+ snprintf(fl, 24, "%lu", expLen);
+ if (ret == XML_SCHEMAV_CVC_LENGTH_VALID) {
+ xmlSchemaVErr(ctxt, ctxt->cur, ret,
+ "The value with length \"%s\" is not "
+ "facet-valid with respect to length = \"%s\".\n",
+ (const xmlChar *)l, (const xmlChar *)fl);
+ } else if (ret == XML_SCHEMAV_CVC_MINLENGTH_VALID) {
+ xmlSchemaVErr(ctxt, ctxt->cur, ret,
+ "The value with length \"%s\" is not "
+ "facet-valid with respect to minLength = \"%s\".\n",
+ (const xmlChar *)l, (const xmlChar *)fl);
+ } else if (ret == XML_SCHEMAV_CVC_MAXLENGTH_VALID) {
+ xmlSchemaVErr(ctxt, ctxt->cur, ret,
+ "The value with length \"%s\" is not "
+ "facet-valid with respect to maxLength = \"%s\".\n",
+ (const xmlChar *)l, (const xmlChar *)fl);
+ } else {
+ xmlSchemaVErr(ctxt, ctxt->cur, ret,
+ "The value is not valid with respect "
+ "to the facet \"%s\".\n",
+ (const xmlChar *)
+ xmlSchemaFacetTypeToString(facet->type),
+ NULL);
+ }
+ } else if (ret < 0) {
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateSimpleTypeValue, "
+ "validating facets of list simple type \"%s\"\n",
+ type->name, NULL);
+ break;
+ }
+ }
+ facetLink = facetLink->next;
+ } while (facetLink != NULL);
+ if (ret >= 0) {
+ if ((hasFacet) && (okFacet == 0)) {
+ ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
+ if (fireErrors) {
+ /*
+ * TODO: Try to create a report that outputs all the enumeration
+ * values in use.
+ */
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_CVC_ENUMERATION_VALID,
+ "The value is not valid with respect "
+ "to the \"enumeration\" facet(s).\n",
+ NULL, NULL);
+ }
+
+ }
+ /*
+ * Pattern facets are ORed at type level and ANDed
+ * if derived. Walk the base axis.
+ */
+ hasFacet = 0;
+ tmpType = type;
+ do {
+ okFacet = 0;
+ for (facetLink = tmpType->facetSet; facetLink != NULL;
+ facetLink = facetLink->next) {
+ if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
+ continue;
+ okFacet = xmlSchemaValidateListSimpleTypeFacet(
+ facetLink->facet, value, len, &expLen);
+ if (okFacet <= 0)
+ break;
+ }
+ if (okFacet != 0)
+ break;
+ tmpType = tmpType->baseType;
+ } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
+ if (okFacet < 0) {
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateSimpleTypeValue, "
+ "validating \"pattern\" facets of type \"%s\"\n",
+ type->name, NULL);
+ } else if (okFacet > 0) {
+ ret = XML_SCHEMAV_CVC_PATTERN_VALID;
+ if (fireErrors) {
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_CVC_ENUMERATION_VALID,
+ "The value is not valid with respect "
+ "to the \"pattern\" facet(s) of type "
+ "\"%s\".\n",
+ tmpType->name, NULL);
+ }
+ }
+ }
+
+ if (collapsedValue != NULL)
+ xmlFree(collapsedValue);
+ }
+ } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
+ xmlSchemaTypeLinkPtr memberLink;
+
+ /*
+ * TODO: For all datatypes ·derived· by ·union· whiteSpace does
+ * not apply directly; however, the normalization behavior of ·union·
+ * types is controlled by the value of whiteSpace on that one of the
+ * ·memberTypes· against which the ·union· is successfully validated.
+ *
+ * This means that the value is normalized by the first validating
+ * member type, then the facets of the union type are applied. This
+ * needs changing of the value!
+ */
+
+ /*
+ * 1.2.3 if {variety} is ·union· then the string must ·match· a
+ * literal in the ·lexical space· of at least one member of
+ * {member type definitions}
+ */
+ memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
+ if (memberLink == NULL) {
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateSimpleTypeValue, "
+ "union simple type \"%s\" has no member types\n",
+ type->name, NULL);
+ ret = -1;
+ }
+ if (ret == 0) {
+ while (memberLink != NULL) {
+ ctxt->type = memberLink->type;
+ ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 1);
+ if ((ret <= 0) || (ret == 0))
+ break;
+ memberLink = memberLink->next;
+ }
+ if (ret > 0) {
+ ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
+ if (fireErrors) {
+ xmlSchemaVErr(ctxt, ctxt->cur,
+ XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3,
+ "The value is not valid.\n",
+ NULL, NULL);
+ }
+ } else if (ret < 0) {
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateSimpleTypeValue, "
+ "validating members of union simple type \"%s\"\n",
+ type->name, NULL);
+ }
+ }
+ /*
+ * Apply facets (pattern, enumeration).
+ */
+ if ((ret == 0) && (applyFacets) &&
+ (type->facetSet != NULL)) {
+ xmlSchemaTypePtr anySimpleType;
+ /*
+ * Check facets. Be sure to pass the built-in type (the
+ * simple ur-type in this case) to xmlSchemaValidateFacetsInternal.
+ */
+ anySimpleType = type->baseType;
+ while (anySimpleType->type != XML_SCHEMA_TYPE_BASIC)
+ anySimpleType = anySimpleType->baseType;
+ ret = xmlSchemaValidateFacetsInternal(ctxt, anySimpleType,
+ type->facetSet, value, fireErrors);
+ if (ret < 0) {
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateSimpleTypeValue, "
+ "validating facets of union simple type \"%s\"\n",
+ type->name, NULL);
+ } else if (ret > 0) {
+ ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
+ if (fireErrors) {
+ xmlSchemaVErr(ctxt, ctxt->cur,
+ XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
+ "The value is not valid.\n",
+ NULL, NULL);
+ }
+ }
+ }
+ }
+ ctxt->type = type;
+ return (ret);
+}
+
+/**
+ * xmlSchemaValidateSimpleTypeElement:
+ * @ctxt: a schema validation context
+ * @node: the element node to be validated.
+ *
+ * Validate the element against a simple type.
+ *
+ * Returns 0 if the element is valid, a positive error code
+ * number otherwise and -1 in case of an internal or API error.
+ */
+static int
+xmlSchemaValidateSimpleTypeElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlNodePtr child;
+ xmlSchemaTypePtr type;
+ xmlAttrPtr attr;
+ int ret;
+ xmlChar *value;
+
+
+ child = ctxt->node;
+ type = ctxt->type;
+
+ if ((ctxt == NULL) || (type == NULL)) {
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateSimpleTypeElement %s\n",
+ node->name, NULL);
+ return (-1);
+ }
+
+ /*
+ * Only text and text based entities references shall be found there
+ */
+ ret = xmlSchemaValidateCheckNodeList(child);
+ if (ret < 0) {
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateSimpleTypeElement %s content\n",
+ node->name, NULL);
+ return (-1);
+ } else if (ret == 0) {
+ /* 3.1.2 The element information item must have no element
+ * information item [children].
+ */
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_TYPE_3_1_2,
+ "Element \"%s\" must have no element children.\n",
+ node->name, NULL);
+ return (-1);
+ }
+ /*
+ * Validation Rule: Element Locally Valid (Type): 3.1.1
+ */
+ attr = node->properties;
+ while (attr != NULL) {
+ if ((attr->ns == NULL) ||
+ (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
+ ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
+ (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
+ (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
+ (!xmlStrEqual
+ (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
+ xmlSchemaVErr(ctxt, node,
+ XML_SCHEMAV_CVC_TYPE_3_1_1,
+ "The attributes of element \"%s\" must be empty, excepting "
+ "those whose namespace name is identical to "
+ "http://www.w3.org/2001/XMLSchema-instance and whose local "
+ "name is one of type, nil, schemaLocation or "
+ "noNamespaceSchemaLocation.\n",
+ node->name, attr->name);
+ return (ctxt->err);
+ }
+ attr = attr->next;
+ }
+ value = xmlNodeGetContent(child);
+ ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1);
+ if (value != NULL)
+ xmlFree(value);
+
+ ctxt->type = type;
+ return (ret);
+}
/**
* xmlSchemaValidateElementType:
@@ -6207,7 +10110,18 @@ xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
xmlSchemaTypePtr type;
xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
xmlSchemaElementPtr decl;
- int ret, attrBase;
+ int ret;
+ xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
+
+ /* This one is called by xmlSchemaValidateContent only. */
+ /*
+ * 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 +10155,12 @@ xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
/*
* Verify the attributes
*/
- attrBase = ctxt->attrBase;
- ctxt->attrBase = ctxt->attrNr;
- xmlSchemaRegisterAttributes(ctxt, child->properties);
- xmlSchemaValidateAttributes(ctxt, child, type->attributes);
+
+ attrs = ctxt->attr;
+ attrTop = ctxt->attrTop;
+
+ xmlSchemaRegisterAttributes(ctxt, child->properties);
+
/*
* Verify the element content recursively
*/
@@ -6289,16 +10205,17 @@ xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
* 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);
}
+#if 0 /* Not currently used. */
/**
* xmlSchemaValidateBasicType:
* @ctxt: a schema validation context
@@ -6326,6 +10243,13 @@ xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
node->name, NULL);
return (-1);
}
+ if (type->type != XML_SCHEMA_TYPE_BASIC) {
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateBasicType, "
+ "the given type is not a built-in type.\n",
+ node->name, NULL);
+ return (-1);
+ }
/*
* First check the content model of the node.
*/
@@ -6377,9 +10301,11 @@ xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
xmlSchemaFreeValue(ctxt->value);
ctxt->value = NULL;
}
+
ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
+
if (value != NULL)
- xmlFree(value);
+ xmlFree(value);
if (ret != 0) {
xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE,
"Element %s: failed to validate basic type %s\n",
@@ -6387,6 +10313,7 @@ xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
}
return (ret);
}
+#endif
/**
* xmlSchemaValidateComplexType:
@@ -6398,101 +10325,221 @@ xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
* Validation Rule: Element Locally Valid (Complex Type)
*
* Returns 0 if the element is schemas valid, a positive error code
- * number otherwise and -1 in case of internal or API error.
+ * number otherwise and -1 in case of internal or API error.
+ * Note on reported errors: Although it might be nice to report
+ * the name of the simple/complex type, used to validate the content
+ * of a node, it is quite unnecessary: for global defined types
+ * the local name of the element is equal to the NCName of the type,
+ * for local defined types it makes no sense to output the internal
+ * computed name of the type. TODO: Instead, one should attach the
+ * struct of the type involved to the error handler - this allows
+ * the report of any additional information by the user.
*/
static int
xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
{
xmlNodePtr child;
- xmlSchemaTypePtr type, subtype;
- int ret;
+ xmlSchemaTypePtr type;
+ int ret = 0;
child = ctxt->node;
type = ctxt->type;
ctxt->cur = node;
switch (type->contentType) {
- case XML_SCHEMA_CONTENT_EMPTY:
- if (type->baseType != NULL) {
- } else if (child != NULL) {
- xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY,
- "Element %s is supposed to be empty\n",
- node->name, NULL);
- }
- if (type->attributes != NULL) {
- xmlSchemaValidateAttributes(ctxt, node, type->attributes);
- }
- subtype = type->subtypes;
- while (subtype != NULL) {
- ctxt->type = subtype;
- xmlSchemaValidateComplexType(ctxt, node);
- subtype = subtype->next;
- }
+ case XML_SCHEMA_CONTENT_EMPTY: {
+ /*
+ * 1 If the {content type} is empty, then the element information
+ * item has no character or element information item [children].
+ */
+ /* TODO: Hmm, Xerces reports nodes like Comment to be invalid
+ * content, but XSV does not.
+ */
+ /*
+ * TODO: Is the entity stuff correct?
+ */
+ while (child != NULL) {
+ if ((child->type == XML_ELEMENT_NODE) ||
+ /*
+ * TODO: Ask Daniel if this are all character nodes.
+ */
+ (child->type == XML_TEXT_NODE) ||
+ (child->type == XML_CDATA_SECTION_NODE) ||
+ (child->type == XML_ENTITY_REF_NODE) ||
+ (child->type == XML_ENTITY_NODE)) {
+ break;
+ }
+ child = child->next;
+ }
+ if (child != NULL) {
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
+ "Character or element children are not allowed, "
+ "because the content type is empty.\n",
+ NULL, NULL);
+ }
break;
+ }
case XML_SCHEMA_CONTENT_ELEMENTS:
- case XML_SCHEMA_CONTENT_MIXED:
- case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
- /*
- * Skip ignorable nodes in that context
- */
- child = xmlSchemaSkipIgnored(ctxt, type, child);
- while (child != NULL) {
- if (child->type == XML_ELEMENT_NODE) {
- ret = xmlRegExecPushString(ctxt->regexp,
- child->name, child);
+ case XML_SCHEMA_CONTENT_MIXED:
+ while (child != NULL) {
+ if (child->type == XML_ELEMENT_NODE) {
+ ret = xmlRegExecPushString(ctxt->regexp,
+ child->name, child);
#ifdef DEBUG_AUTOMATA
- if (ret < 0)
- xmlGenericError(xmlGenericErrorContext,
- " --> %s Error\n", child->name);
- else
- xmlGenericError(xmlGenericErrorContext,
- " --> %s\n", child->name);
+ if (ret < 0)
+ xmlGenericError(xmlGenericErrorContext,
+ " --> %s Error\n", child->name);
+ else
+ xmlGenericError(xmlGenericErrorContext,
+ " --> %s\n", child->name);
#endif
- }
- child = child->next;
- /*
- * Skip ignorable nodes in that context
- */
- child = xmlSchemaSkipIgnored(ctxt, type, child);
- }
- if (((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
- (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS)) &&
- (type->subtypes != NULL)) {
- TODO
- }
-
-
- if (type->attributes != NULL) {
- xmlSchemaValidateAttributes(ctxt, node, type->attributes);
- }
+ } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
+ /*
+ * TODO: Ask Daniel if this are all character nodes.
+ */
+ (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
+ (child->type == XML_ENTITY_NODE) ||
+ (child->type == XML_ENTITY_REF_NODE) ||
+ (child->type == XML_CDATA_SECTION_NODE))) {
+ /*
+ * 2.3 If the {content type} is element-only, then the
+ * element information item has no character information
+ * item [children] other than those whose [character
+ * code] is defined as a white space in [XML 1.0 (Second
+ * Edition)].
+ */
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
+ "Character children are not allowed, "
+ "because the content type is element-only.\n",
+ NULL, NULL);
+ break;
+ }
+ child = child->next;
+ }
break;
+ case XML_SCHEMA_CONTENT_SIMPLE:
case XML_SCHEMA_CONTENT_BASIC:{
- if (type->subtypes != NULL) {
- ctxt->type = type->subtypes;
- xmlSchemaValidateComplexType(ctxt, node);
- }
- if (type->baseType != NULL) {
- ctxt->type = type->baseType;
- if (type->baseType->type == XML_SCHEMA_TYPE_BASIC)
- xmlSchemaValidateBasicType(ctxt, node);
- else if (type->baseType->type == XML_SCHEMA_TYPE_COMPLEX)
- xmlSchemaValidateComplexType(ctxt, node);
- else if (type->baseType->type == XML_SCHEMA_TYPE_SIMPLE)
- xmlSchemaValidateSimpleType(ctxt, node);
- else
- xmlGenericError(xmlGenericErrorContext,
- "unexpected content type of base: %d\n",
- type->contentType);
-
- }
- if (type->attributes != NULL) {
- xmlSchemaValidateAttributes(ctxt, node,
- type->attributes);
- }
- ctxt->type = type;
- break;
- }
- case XML_SCHEMA_CONTENT_SIMPLE:{
+ xmlSchemaTypePtr base, anyType;
+ xmlChar *value = NULL;
+ /*
+ * We hit a complexType with a simpleContent resolving
+ * to a user derived or built-in simple type.
+ */
+ anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
+ /*
+ * Internal check for integrity of the base type.
+ */
+ base = type->baseType;
+ while ((base != NULL) &&
+ (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
+ (base->type != XML_SCHEMA_TYPE_BASIC) &&
+ (base != anyType)) {
+ base = base->baseType;
+ }
+ if ((base == NULL) ||
+ (((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) &&
+ (base->type != XML_SCHEMA_TYPE_SIMPLE)) ||
+ ((type->contentType == XML_SCHEMA_CONTENT_BASIC) &&
+ (base->type != XML_SCHEMA_TYPE_BASIC)))) {
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateComplexType, "
+ "Element \"%s\": the base type of the corresponding "
+ "complex type \"%s\" is not a user derived or a "
+ "built-in simple type.\n",
+ node->name, type->name);
+ return (-1);
+ }
+ /*
+ * 2.2 If the {content type} is a simple type definition,
+ * then the element information item has no element
+ * information item [children], and the ·normalized value·
+ * of the element information item is ·valid· with respect
+ * to that simple type definition as defined by String
+ * Valid (§3.14.4).
+ */
+ child = node->children;
+ while (child != NULL) {
+ if (child->type == XML_ELEMENT_NODE) {
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
+ "Element children are not allowed, because "
+ "the content type is a simple type.\n",
+ NULL, NULL);
+ ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
+ break;
+ }
+ child = child->next;
+ }
+ if (ret == 0) {
+ /*
+ * Validate the character content against a simple type.
+ */
+ if (ctxt->node == NULL)
+ value = NULL;
+ else
+ value = xmlNodeGetContent(node);
+ ctxt->type = base;
+ ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1);
+ ctxt->type = type;
+ if (ret > 0) {
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
+ "The character value "
+ "is not valid with respect to the simple type.\n",
+ NULL, NULL);
+ ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
+ } else if (ret < 0) {
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateComplexType, "
+ "Element \"%s\": error while validating character "
+ "content against complex type \"%s\".\n",
+ node->name, type->name);
+ return (-1);
+ }
+ }
+ if (ret == 0) {
+ /*
+ * Apply facets of the complexType. Be sure to pass the
+ * built-in type to xmlSchemaValidateFacetsInternal.
+ */
+ /* TODO: I don't know yet if the facets of the simple type
+ * are used, or if the facets, defined by this complex type,
+ * are to be used only. This here applies both facet sets.
+ */
+ while (base->type != XML_SCHEMA_TYPE_BASIC)
+ base = base->baseType;
+ if (base == NULL) {
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateComplexType, "
+ "Element \"%s\": error while validating character "
+ "content against complex type \"%s\"; failed to "
+ "compute the built-in simple type for facet "
+ "validation.\n",
+ node->name, type->name);
+ return (-1);
+ }
+ ret = xmlSchemaValidateFacetsInternal(ctxt, base,
+ type->facetSet, value, 1);
+ if (ret > 0) {
+ xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
+ "The character value "
+ "is not valid with respect to the simple type.\n",
+ NULL, NULL);
+ ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
+ } else if (ret < 0) {
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
+ "Internal error: xmlSchemaValidateComplexType, "
+ "Element \"%s\": error while validating character "
+ "content against complex type \"%s\"; failed to "
+ "apply facets.\n",
+ type->name, NULL);
+ }
+ }
+ if (value != NULL)
+ xmlFree(value);
+ /* TODO: facets */
+ break;
+ }
+ /*
+ case XML_SCHEMA_CONTENT_SIMPLE:{
if (type->subtypes != NULL) {
ctxt->type = type->subtypes;
xmlSchemaValidateComplexType(ctxt, node);
@@ -6501,18 +10548,25 @@ xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
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;
}
+ */
default:
TODO xmlGenericError(xmlGenericErrorContext,
"unimplemented content type %d\n",
type->contentType);
}
+ if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
+ xmlSchemaValidateAttributes(ctxt, node, type);
+ }
+ ctxt->cur = node;
return (ctxt->err);
}
@@ -6537,7 +10591,6 @@ xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
type = ctxt->type;
ctxt->cur = node;
- xmlSchemaValidateAttributes(ctxt, node, type->attributes);
ctxt->cur = node;
switch (type->type) {
@@ -6570,13 +10623,11 @@ xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
break;
}
case XML_SCHEMA_TYPE_BASIC:
- xmlSchemaValidateBasicType(ctxt, node);
+ case XML_SCHEMA_TYPE_SIMPLE:
+ xmlSchemaValidateSimpleTypeElement(ctxt, node);
break;
case XML_SCHEMA_TYPE_FACET:
- TODO break;
- case XML_SCHEMA_TYPE_SIMPLE:
- xmlSchemaValidateSimpleType(ctxt, node);
- break;
+ TODO break;
case XML_SCHEMA_TYPE_SEQUENCE:
TODO break;
case XML_SCHEMA_TYPE_CHOICE:
@@ -6633,7 +10684,6 @@ xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
TODO break;
}
- xmlSchemaValidateAttributes(ctxt, node, type->attributes);
if (ctxt->node == NULL)
return (ctxt->err);
@@ -6662,6 +10712,10 @@ xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
return (0);
+ /* This one is called by "xmlSchemaValidateElementType" and
+ * "xmlSchemaValidateElement".
+ */
+
/*
* 3.3.4 : 2
*/
@@ -6710,9 +10764,7 @@ xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
ctxt->type = elemDecl->subtypes;
ctxt->node = elem->children;
- xmlSchemaValidateContent(ctxt, elem);
- xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
-
+ xmlSchemaValidateContent(ctxt, elem);
return (ctxt->err);
}
@@ -6721,7 +10773,7 @@ xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
* 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 +10781,69 @@ xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
* 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;
+ const xmlChar *nsURI;
+ xmlSchemaAttributeLinkPtr attrUse;
+ xmlSchemaAttributePtr attrDecl;
int found;
+ xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
+#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 +10853,7 @@ xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
* 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 +10862,176 @@ xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
/* ((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;
-
- if (attributes->subtypes == NULL) {
+ ctxt->cur = (xmlNodePtr) attr;
+ ctxt->node = attr->children;
+
+ 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;
}
+ value = xmlNodeListGetString(elem->doc, attr->children, 1);
+ ctxt->type = attrDecl->subtypes;
+ ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 1);
+ ctxt->type = type;
+ 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;
- 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;
+#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;
- value = xmlNodeListGetString(elem->doc, attr->children, 1);
- ret = xmlSchemaValidateSimpleValue(ctxt, attributes->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);
+ if (reqAttrStates == NULL) {
+ reqAttrStates = tmp;
+ reqAttrStatesTop = tmp;
} else {
- ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
+ reqAttrStatesTop->next = tmp;
+ reqAttrStatesTop = tmp;
}
- if (value != NULL) {
- xmlFree(value);
+
+ }
+ 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->processContents ==
+ XML_SCHEMAS_ANY_LAX)
+ printf("processContents: lax\n");
+ else if (type->attributeWildcard->processContents ==
+ XML_SCHEMAS_ANY_STRICT)
+ printf("processContents: strict\n");
+ else
+ printf("processContents: skip\n");
+ 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
+ curState = ctxt->attr;
+ while (curState != NULL) {
+ if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
+ if (curState->attr->ns != NULL)
+ nsURI = curState->attr->ns->href;
+ else
+ nsURI = NULL;
+ if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
+ nsURI)) {
+ /*
+ * Handle processContents.
+ */
+ if ((type->attributeWildcard->processContents ==
+ XML_SCHEMAS_ANY_LAX) ||
+ (type->attributeWildcard->processContents ==
+ XML_SCHEMAS_ANY_STRICT)) {
+
+ attr = curState->attr;
+ attrDecl = xmlSchemaGetAttribute(ctxt->schema,
+ attr->name, nsURI);
+ if (attrDecl != NULL) {
+ value = xmlNodeListGetString(elem->doc, attr->children, 1);
+ ctxt->type = attrDecl->subtypes;
+ ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1);
+ ctxt->type = type;
+ 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);
+ }
+
+ } else if (type->attributeWildcard->processContents ==
+ XML_SCHEMAS_ANY_LAX) {
+ curState->state = XML_SCHEMAS_ATTR_CHECKED;
+ }
+ } else
+ curState->state = XML_SCHEMAS_ATTR_CHECKED;
+ }
+ }
+ curState = curState->next;
}
- 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;
}
+#ifdef DEBUG_ATTR_VALIDATION
+ if (redundant)
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlSchemaValidateAttributes: redundant call by type: %s\n",
+ type->name);
+#endif
return (ctxt->err);
}
@@ -6853,7 +11049,8 @@ static int
xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
{
xmlSchemaElementPtr elemDecl;
- int ret, attrBase;
+ int ret;
+ xmlSchemaAttrStatePtr attrs, attrTop;
if (elem->ns != NULL) {
elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
@@ -6862,22 +11059,7 @@ xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
elem->name, NULL, NULL);
}
- /*
- * special case whe elementFormDefault is unqualified for top-level elem.
- */
- /*
- * This was removed, since elementFormDefault does not apply to top-level
- * element declarations.
- */
- /*
- if ((elemDecl == NULL) && (elem->ns != NULL) &&
- (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
- (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
- ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
- elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
- elem->name, NULL, NULL);
- }
- */
+ /* This one is called by xmlSchemaValidateDocument only. */
/*
* 3.3.4 : 1
@@ -6895,10 +11077,9 @@ xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
/*
* 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 +11120,10 @@ xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
* 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);
}
@@ -6960,7 +11143,7 @@ xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
{
xmlNodePtr root;
xmlSchemaElementPtr elemDecl;
-
+
root = xmlDocGetRootElement(doc);
if (root == NULL) {
xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT,
@@ -6974,22 +11157,27 @@ xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
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 +11219,17 @@ xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
}
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 +11239,8 @@ xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
return (NULL);
}
memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
+ */
+
return (ret);
}
@@ -7057,7 +11256,7 @@ xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
if (ctxt == NULL)
return;
if (ctxt->attr != NULL)
- xmlFree(ctxt->attr);
+ xmlSchemaFreeAttributeStates(ctxt->attr);
if (ctxt->value != NULL)
xmlSchemaFreeValue(ctxt->value);
xmlFree(ctxt);