Index: xmlschemas.c =================================================================== RCS file: /cvs/gnome/libxml2/xmlschemas.c,v retrieving revision 1.60 diff -c -r1.60 xmlschemas.c *** a/xmlschemas.c 22 Apr 2004 07:15:40 -0000 1.60 --- b/xmlschemas.c 10 May 2004 15:34:02 -0000 *************** *** 944,949 **** --- 944,950 ---- * Find the namespace name for the given declaration. * * Returns the local name for that declaration, as well as the namespace name + * NOTE: This function is no longer used by now. */ static const xmlChar * xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, *************** *** 955,960 **** --- 956,968 ---- *namespace = NULL; + /* TODO: The following seems to be not correct here: + * 1. The name of a declaration is a NCName, not a QName. + * 2. The attribute "targetNamespace" is allowed for the Element Information Item only. + * 3. One cannot evaluate the target namespace, by the type of declaration, since it is dependant + * on the xxxFormDefault of and the form attribute of an or . + */ + if (xmlStrEqual(node->name, BAD_CAST "element") || xmlStrEqual(node->name, BAD_CAST "attribute") || xmlStrEqual(node->name, BAD_CAST "simpleType") || *************** *** 962,967 **** --- 970,976 ---- def = xmlSchemaGetProp(ctxt, node, "targetNamespace"); } + qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */ name = xmlSplitQName3(qname, &len); if (name == NULL) { *************** *** 981,986 **** --- 990,996 ---- } return(qname); } + name = xmlDictLookup(ctxt->dict, name, -1); prefix = xmlDictLookup(ctxt->dict, qname, len); if (def != NULL) { *************** *** 1032,1038 **** ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) { return (ret); } ! } else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) { if (xmlStrEqual(namespace, schema->targetNamespace)) ret = xmlHashLookup2(schema->elemDecl, name, NULL); else --- 1042,1054 ---- ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) { return (ret); } ! /* ! * This one was removed, since top level element declarations have ! * the target namespace specified in targetNamespace of the ! * information element, even if elementFormDefault is "unqualified". ! */ ! ! /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) { if (xmlStrEqual(namespace, schema->targetNamespace)) ret = xmlHashLookup2(schema->elemDecl, name, NULL); else *************** *** 1041,1046 **** --- 1057,1063 ---- ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) { return (ret); } + */ } else { ret = xmlHashLookup2(schema->elemDecl, name, namespace); if ((ret != NULL) && *************** *** 1659,1665 **** static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, ! xmlNodePtr node); static xmlSchemaAttributeGroupPtr xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, xmlNodePtr node); --- 1676,1683 ---- static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, ! xmlNodePtr node, ! int topLevel); static xmlSchemaAttributeGroupPtr xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, xmlNodePtr node); *************** *** 1695,1701 **** (IS_SCHEMA(child, "attributeGroup"))) { attr = NULL; if (IS_SCHEMA(child, "attribute")) { ! attr = xmlSchemaParseAttribute(ctxt, schema, child); } else if (IS_SCHEMA(child, "attributeGroup")) { attr = (xmlSchemaAttributePtr) xmlSchemaParseAttributeGroup(ctxt, schema, child); --- 1713,1719 ---- (IS_SCHEMA(child, "attributeGroup"))) { attr = NULL; if (IS_SCHEMA(child, "attribute")) { ! attr = xmlSchemaParseAttribute(ctxt, schema, child, 0); } else if (IS_SCHEMA(child, "attributeGroup")) { attr = (xmlSchemaAttributePtr) xmlSchemaParseAttributeGroup(ctxt, schema, child); *************** *** 1941,1958 **** xmlSchemaAttributePtr ret; xmlNodePtr child = NULL; char name[100]; - const xmlChar *local, *ns; 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); ! ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, ns); if (ret == NULL) { return (NULL); } ret->id = xmlSchemaGetProp(ctxt, node, "id"); processContents = xmlSchemaGetProp(ctxt, node, "processContents"); if ((processContents == NULL) --- 1959,1980 ---- xmlSchemaAttributePtr ret; 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); if (ret == NULL) { return (NULL); } + ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE; ret->id = xmlSchemaGetProp(ctxt, node, "id"); processContents = xmlSchemaGetProp(ctxt, node, "processContents"); if ((processContents == NULL) *************** *** 1995,2060 **** * parse a XML schema Attrribute declaration * *WARNING* this interface is highly subject to change * ! * Returns -1 in case of error, 0 if the declaration is inproper and ! * 1 in case of success. */ static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, ! xmlNodePtr node) { const xmlChar *name, *refNs = NULL, *ref = NULL, *attrVal; xmlSchemaAttributePtr ret; xmlNodePtr child = NULL; char buf[100]; if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) return (NULL); name = xmlSchemaGetProp(ctxt, node, "name"); if (name == NULL) { - ref = xmlGetQNameProp(ctxt, node, "ref", &refNs); ! if (ref == NULL) { ! xmlSchemaPErr2(ctxt, node, child, ! XML_SCHEMAP_ATTR_NONAME_NOREF, ! "Attribute has no name nor ref\n", NULL, NULL); return (NULL); } snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1); name = (const xmlChar *) buf; ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL); } else { ! const xmlChar *local, *ns; ! local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); ! ret = xmlSchemaAddAttribute(ctxt, schema, local, ns); } if (ret == NULL) { return (NULL); } ! /* Read the "use" attribute. */ ! attrVal = xmlSchemaGetProp(ctxt, node, "use"); ! if (attrVal != NULL) { ! if (xmlStrEqual(attrVal, BAD_CAST "optional")) ! ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL; ! else if (xmlStrEqual(attrVal, BAD_CAST "prohibited")) ! ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED; ! else if (xmlStrEqual(attrVal, BAD_CAST "required")) ! ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED; ! else ! xmlSchemaPErr(ctxt, node, ! XML_SCHEMAP_INVALID_ATTR_USE, ! "attribute %s has an invalid value for \"use\"\n", name, NULL); ! } else ! ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL; ret->ref = ref; ret->refNs = refNs; if ((ret->targetNamespace != NULL) && ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) && (xmlStrEqual(ret->targetNamespace, schema->targetNamespace))) ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT; ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs)); ret->node = node; child = node->children; if (IS_SCHEMA(child, "annotation")) { --- 2017,2174 ---- * parse a XML schema Attrribute declaration * *WARNING* this interface is highly subject to change * ! * Returns the attribute declaration. */ static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, ! xmlNodePtr node, int topLevel) { const xmlChar *name, *refNs = NULL, *ref = NULL, *attrVal; xmlSchemaAttributePtr ret; xmlNodePtr child = NULL; char buf[100]; + int hasRefType = 0; + int hasForm = 0; + + /* Note that the w3c spec assumes the schema to be validated with schema for schemas beforehand. */ + + /* 3.2.3 Constraints on XML Representations of Attribute Declarations */ + + /* TODO: Complete implementation of: + * 3.2.6 Schema Component Constraint: Attribute Declaration Properties Correct + */ if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) return (NULL); + name = xmlSchemaGetProp(ctxt, node, "name"); if (name == NULL) { ref = xmlGetQNameProp(ctxt, node, "ref", &refNs); ! /* 3.2.3 : 3.1 ! * One of ref or name must be present, but not both ! */ ! if (ref == NULL) { ! xmlSchemaPErr(ctxt, node, ! XML_SCHEMAP_ATTR_NONAME_NOREF, ! "Attribute declaration has no \"name\" nor \"ref\"\n", NULL, NULL); return (NULL); } + hasRefType = 1; snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1); name = (const xmlChar *) buf; ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL); + if (!topLevel) { + /* 3.2.3 : 3.2 + * If ref is present, then all of , form and type must be absent. + */ + if (xmlSchemaGetProp(ctxt, node, "form") != NULL) { + xmlSchemaPErr(ctxt, node, + XML_SCHEMAP_INVALID_ATTR_COMBINATION, + "Attribute declaration %s has \"ref\", thus \"form\" must be absent\n", name, NULL); + } + if (xmlSchemaGetProp(ctxt, node, "type") != NULL) { + xmlSchemaPErr(ctxt, node, + XML_SCHEMAP_INVALID_ATTR_COMBINATION, + "Attribute declaration %s has \"ref\", thus \"type\" must be absent\n", name, NULL); + } + } } else { ! const xmlChar *ns = NULL; ! /* 3.2.3 : 3.1 ! * One of ref or name must be present, but not both ! */ ! 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); ! } ! ! /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */ ! /* Evaluate the target namespace */ ! if (schema->targetNamespace != NULL) { ! if (topLevel) { ! ns = schema->targetNamespace; ! } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) { ! if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"), BAD_CAST "qualified")) { ! ns = schema->targetNamespace; ! } ! } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) { ! ns = schema->targetNamespace; ! } ! } ! ret = xmlSchemaAddAttribute(ctxt, schema, name, ns); ! /* 3.2.6 Schema Component Constraint: xmlns Not Allowed */ ! if (xmlStrEqual(name, BAD_CAST "xmlns")) { ! xmlSchemaPErr(ctxt, node, ! XML_SCHEMAP_INVALID_ATTR_NAME, ! "The name of an attribute declaration must not match \"xmlns\".\n", NULL, NULL); ! } ! ! /* 3.2.6 Schema Component Constraint: xsi: Not Allowed */ ! if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) { ! xmlSchemaPErr(ctxt, node, ! XML_SCHEMAP_INVALID_ATTR_NAME, ! "The target namespace of an attribute declaration, must not match \"http://www.w3.org/2001/XMLSchema-instance\"", NULL, NULL); ! } } if (ret == NULL) { return (NULL); } + ret->type = XML_SCHEMA_TYPE_ATTRIBUTE; + + /* Handle the "use" attribute. */ + attrVal = xmlSchemaGetProp(ctxt, node, "use"); + if (attrVal != NULL) { + if (xmlStrEqual(attrVal, BAD_CAST "optional")) + ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL; + else if (xmlStrEqual(attrVal, BAD_CAST "prohibited")) + ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED; + else if (xmlStrEqual(attrVal, BAD_CAST "required")) + ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED; + else + xmlSchemaPErr(ctxt, node, + XML_SCHEMAP_INVALID_ATTR_USE, + "Attribute declaration %s has an invalid value for \"use\"\n", name, NULL); + } else + ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL; ! ! if (xmlSchemaGetProp(ctxt, node, "default") != NULL) { ! /* 3.2.3 : 1 ! * default and fixed must not both be present. ! */ ! if (xmlSchemaGetProp(ctxt, node, "fixed") != NULL) { ! xmlSchemaPErr(ctxt, node, ! XML_SCHEMAP_INVALID_ATTR_COMBINATION, ! "Attribute declaration has both, \"default\" and \"fixed\"\n", NULL, NULL); ! } ! /* 3.2.3 : 2 ! * If default and use are both present, use must have the actual value optional. ! */ ! if (ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) { ! xmlSchemaPErr(ctxt, node, ! XML_SCHEMAP_INVALID_ATTR_COMBINATION, ! "Attribute declaration has \"default\" but \"use\" is not \"optional\"\n", NULL, NULL); ! } ! } ret->ref = ref; ret->refNs = refNs; + /* + * The setting of XML_SCHEMAS_ATTR_NSDEFAULT is not needed anymore, + * since the target namespace was already evaluated and took + * attributeFormDefault into account. + */ + /* if ((ret->targetNamespace != NULL) && ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) && (xmlStrEqual(ret->targetNamespace, schema->targetNamespace))) ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT; + */ ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs)); + if (ret->typeName != NULL) + hasRefType = 1; ret->node = node; child = node->children; if (IS_SCHEMA(child, "annotation")) { *************** *** 2062,2068 **** child = child->next; } if (IS_SCHEMA(child, "simpleType")) { ! ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child); child = child->next; } if (child != NULL) { --- 2176,2191 ---- child = child->next; } if (IS_SCHEMA(child, "simpleType")) { ! if (hasRefType) { ! /* 3.2.3 : 4 ! * type and must not both be present. ! */ ! /* TODO: XML_SCHEMAP_INVALID_ATTR_COMBINATION seems not to be a proper error type here. */ ! xmlSchemaPErr2(ctxt, node, child, ! XML_SCHEMAP_INVALID_ATTR_COMBINATION, ! "Attribute declaration %s has both (\"ref\" or \"type\") and \n", name, NULL); ! } else ! ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child); child = child->next; } if (child != NULL) { *************** *** 2135,2141 **** (IS_SCHEMA(child, "attributeGroup"))) { attr = NULL; if (IS_SCHEMA(child, "attribute")) { ! attr = xmlSchemaParseAttribute(ctxt, schema, child); } else if (IS_SCHEMA(child, "attributeGroup")) { attr = (xmlSchemaAttributePtr) xmlSchemaParseAttributeGroup(ctxt, schema, child); --- 2258,2264 ---- (IS_SCHEMA(child, "attributeGroup"))) { attr = NULL; if (IS_SCHEMA(child, "attribute")) { ! attr = xmlSchemaParseAttribute(ctxt, schema, child, 0); } else if (IS_SCHEMA(child, "attributeGroup")) { attr = (xmlSchemaAttributePtr) xmlSchemaParseAttributeGroup(ctxt, schema, child); *************** *** 2174,2181 **** * parse a XML schema Element declaration * *WARNING* this interface is highly subject to change * ! * Returns -1 in case of error, 0 if the declaration is inproper and ! * 1 in case of success. */ static xmlSchemaElementPtr xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, --- 2297,2303 ---- * parse a XML schema Element declaration * *WARNING* this interface is highly subject to change * ! * Returns the parsed element declaration. */ static xmlSchemaElementPtr xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, *************** *** 2187,2192 **** --- 2309,2318 ---- xmlNodePtr child = NULL; const xmlChar *oldcontainer; char buf[100]; + xmlAttrPtr attr; + + /* 3.3.3 Constraints on XML Representations of Element Declarations */ + /* TODO: Complete implementation of 3.3.6 */ if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) return (NULL); *************** *** 2195,2214 **** if (name == NULL) { ref = xmlGetQNameProp(ctxt, node, "ref", &refNs); if (ref == NULL) { ! xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_NONAME_NOREF, "Element 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); } else { ! const xmlChar *local, *ns; ! local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); ! ret = xmlSchemaAddElement(ctxt, schema, local, ns); } if (ret != NULL) ret->node = node; --- 2321,2363 ---- 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 + */ if (ref == NULL) { ! xmlSchemaPErr(ctxt, node, XML_SCHEMAP_ELEM_NONAME_NOREF, "Element 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); } else { ! const xmlChar *ns = NULL; ! /* Evaluate the target namespace */ ! if (schema->targetNamespace != NULL) { ! if (toplevel) { ! ns = schema->targetNamespace; ! } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) { ! if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"), BAD_CAST "qualified")) { ! ns = schema->targetNamespace; ! } ! } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) { ! ns = schema->targetNamespace; ! } ! } ! /*local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */ ! ret = xmlSchemaAddElement(ctxt, schema, name, ns); ! /* 3.3.3 : 2.1 ! * One of ref or name must be present, but not both ! */ ! if ((!toplevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) { ! xmlSchemaPErr(ctxt, node, ! XML_SCHEMAP_INVALID_ATTR_COMBINATION, ! "Element declaration has both, \"name\" and \"ref\"\n", NULL, NULL); ! } } if (ret != NULL) ret->node = node; *************** *** 2220,2225 **** --- 2369,2393 ---- ret->refNs = refNs; if (ref != NULL) ret->flags |= XML_SCHEMAS_ELEM_REF; + + /* 3.3.3 : 2.2 */ + if ((!toplevel) && (ref != NULL)) { + attr = node->properties; + while (attr != NULL) { + if ((attr->ns == NULL) && + (!xmlStrEqual(attr->name, BAD_CAST "ref")) && + (!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) && + (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) { + + xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION, + "Element declaration %s: only minOccurs, maxOccurs and id are allowed in addition to ref\n", + ret->name, NULL); + } + attr = attr->next; + } + } + if (toplevel) ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL; if (xmlGetBooleanProp(ctxt, node, "nillable", 0)) *************** *** 2230,2245 **** ret->id = xmlSchemaGetProp(ctxt, node, "id"); ret->namedType = ! xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs)); ret->substGroup = xmlGetQNameProp(ctxt, node, "substitutionGroup", &(ret->substGroupNs)); fixed = xmlSchemaGetProp(ctxt, node, "fixed"); ret->minOccurs = xmlGetMinOccurs(ctxt, node); ret->maxOccurs = xmlGetMaxOccurs(ctxt, node); ret->value = xmlSchemaGetProp(ctxt, node, "default"); if ((ret->value != NULL) && (fixed != NULL)) { xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED, "Element %s has both default and fixed\n", ret->name, NULL); --- 2398,2426 ---- ret->id = xmlSchemaGetProp(ctxt, node, "id"); ret->namedType = ! xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs)); ret->substGroup = xmlGetQNameProp(ctxt, node, "substitutionGroup", &(ret->substGroupNs)); + if ((ret->substGroup != NULL) && (!toplevel)) { + /* 3.3.6 : 3 */ + /* TODO: This seems to be redundant, since the schema for schemas already prohibits + * the use of the "substitutionGroup" attribute in local element declarations. + */ + xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION, + "Element declaration %s: substitutionGroup is allowed on top-level declarations only\n", + ret->name, NULL); + + } fixed = xmlSchemaGetProp(ctxt, node, "fixed"); ret->minOccurs = xmlGetMinOccurs(ctxt, node); ret->maxOccurs = xmlGetMaxOccurs(ctxt, node); ret->value = xmlSchemaGetProp(ctxt, node, "default"); if ((ret->value != NULL) && (fixed != NULL)) { + /* 3.3.3 : 1 + * default and fixed must not both be present. + */ xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED, "Element %s has both default and fixed\n", ret->name, NULL); *************** *** 2253,2272 **** ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child); child = child->next; } ! if (IS_SCHEMA(child, "complexType")) { ! ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child); ! child = child->next; ! } else if (IS_SCHEMA(child, "simpleType")) { ! ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child); ! child = child->next; ! } ! while ((IS_SCHEMA(child, "unique")) || ! (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) { ! TODO child = child->next; ! } ! if (child != NULL) { ! xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD, ! "element %s has unexpected content\n", name, NULL); } ctxt->container = oldcontainer; --- 2434,2490 ---- ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child); child = child->next; } ! if (ref != NULL) { ! /* 3.3.3 (2.2) */ ! while (child != NULL) { ! if ((IS_SCHEMA(child, "complexType")) || ! (IS_SCHEMA(child, "simpleType")) || ! (IS_SCHEMA(child, "unique")) || ! (IS_SCHEMA(child, "key")) || ! (IS_SCHEMA(child, "keyref"))) { ! ! xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_REF_AND_CONTENT, ! "Element declaration %s: only annotation is allowed as content in addition to ref\n", ! ret->name, NULL); ! } else { ! xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD, ! "element %s has unexpected content\n", name, NULL); ! } ! child = child->next; ! } ! } else { ! if (IS_SCHEMA(child, "complexType")) { ! /* 3.3.3 : 3 ! * type and either or are mutually exclusive ! */ ! if (ret->namedType != NULL) { ! xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION, ! "Element declaration %s has both \"type\" and an local complex type\n", ! ret->name, NULL); ! } else ! ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child); ! child = child->next; ! } else if (IS_SCHEMA(child, "simpleType")) { ! /* 3.3.3 : 3 ! * type and either or are mutually exclusive ! */ ! if (ret->namedType != NULL) { ! xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION, ! "Element declaration %s has both \"type\" and an local simple type\n", ! ret->name, NULL); ! } else ! ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child); ! child = child->next; ! } ! ! while ((IS_SCHEMA(child, "unique")) || ! (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) { ! TODO child = child->next; ! } ! if (child != NULL) { ! xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD, ! "element %s has unexpected content\n", name, NULL); ! } } ctxt->container = oldcontainer; *************** *** 2371,2376 **** --- 2589,2595 ---- type->annot = xmlSchemaParseAnnotation(ctxt, schema, child); child = child->next; } + subtype = NULL; if (IS_SCHEMA(child, "simpleType")) { subtype = (xmlSchemaTypePtr) *************** *** 2414,2426 **** if (name == NULL) { char buf[100]; ! snprintf(buf, 99, "simpletype %d", ctxt->counter++ + 1); type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL); ! } else { ! const xmlChar *local, *ns; ! ! local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); ! type = xmlSchemaAddType(ctxt, schema, local, ns); } if (type == NULL) return (NULL); --- 2633,2643 ---- if (name == 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 (type == NULL) return (NULL); *************** *** 2448,2453 **** --- 2665,2676 ---- 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, *************** *** 2952,2958 **** xmlSchemaParseElement(ctxt, schema, child, 1); child = child->next; } else if (IS_SCHEMA(child, "attribute")) { ! xmlSchemaParseAttribute(ctxt, schema, child); child = child->next; } else if (IS_SCHEMA(child, "attributeGroup")) { xmlSchemaParseAttributeGroup(ctxt, schema, child); --- 3175,3181 ---- xmlSchemaParseElement(ctxt, schema, child, 1); child = child->next; } else if (IS_SCHEMA(child, "attribute")) { ! xmlSchemaParseAttribute(ctxt, schema, child, 1); child = child->next; } else if (IS_SCHEMA(child, "attributeGroup")) { xmlSchemaParseAttributeGroup(ctxt, schema, child); *************** *** 3491,3497 **** return (NULL); ! snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1); type = xmlSchemaAddType(ctxt, schema, name, NULL); if (type == NULL) return (NULL); --- 3714,3720 ---- return (NULL); ! snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1); type = xmlSchemaAddType(ctxt, schema, name, NULL); if (type == NULL) return (NULL); *************** *** 3598,3605 **** xmlSchemaTypePtr type, subtype; xmlNodePtr child = NULL; const xmlChar *name; ! const xmlChar *oldcontainer; ! const xmlChar *mixed; char buf[100]; if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) --- 3821,3827 ---- xmlSchemaTypePtr type, subtype; xmlNodePtr child = NULL; const xmlChar *name; ! const xmlChar *oldcontainer; char buf[100]; if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) *************** *** 3609,3630 **** name = xmlSchemaGetProp(ctxt, node, "name"); if (name == NULL) { ! snprintf(buf, 99, "anontype %d", ctxt->counter++ + 1); name = (const xmlChar *)buf; type = xmlSchemaAddType(ctxt, schema, name, NULL); } else { - const xmlChar *local, *ns; ! local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); ! type = xmlSchemaAddType(ctxt, schema, local, ns); } if (type == NULL) { return (NULL); } ! mixed = xmlSchemaGetProp(ctxt, node, "mixed"); ! if (mixed != NULL) ! type->flags |= XML_SCHEMAS_TYPE_MIXED; type->node = node; type->type = XML_SCHEMA_TYPE_COMPLEX; --- 3831,3850 ---- 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); } else { ! /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */ ! type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace); } 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; *************** *** 3637,3642 **** --- 3857,3867 ---- child = child->next; } if (IS_SCHEMA(child, "simpleContent")) { + /* 3.4.3 : 2.2 + * Specifying mixed='true' when the alternative is chosen has no effect + */ + if (type->flags & XML_SCHEMAS_TYPE_MIXED) + type->flags ^= XML_SCHEMAS_TYPE_MIXED; type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child); child = child->next; } else if (IS_SCHEMA(child, "complexContent")) { *************** *** 3693,3699 **** if ((ctxt == NULL) || (node == NULL)) return (NULL); ! nberrors = ctxt->nberrors; ctxt->nberrors = 0; if (IS_SCHEMA(node, "schema")) { --- 3918,3924 ---- if ((ctxt == NULL) || (node == NULL)) return (NULL); ! nberrors = ctxt->nberrors; ctxt->nberrors = 0; if (IS_SCHEMA(node, "schema")) { *************** *** 4208,4215 **** start = ctxt->state; while (subtypes != NULL) { ctxt->state = start; ! elem = (xmlSchemaElementPtr) subtypes; ! /* TODO : handle the namespace too */ if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) { xmlAutomataNewOnceTrans(ctxt->am, ctxt->state, --- 4433,4439 ---- start = ctxt->state; while (subtypes != NULL) { ctxt->state = start; ! elem = (xmlSchemaElementPtr) subtypes; /* TODO : handle the namespace too */ if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) { xmlAutomataNewOnceTrans(ctxt->am, ctxt->state, *************** *** 4390,4397 **** } } static void ! xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr typeDecl, xmlSchemaParserCtxtPtr ctxt) { const xmlChar *cur, *end, *prefix, *ncName, *namespace; --- 4614,4660 ---- } } + /** + * xmlSchemaParseListRefFixup: + * @type: the schema type definition + * @ctxt: the schema parser context + * + * Fixup of the itemType reference of the list type. + */ + static void + xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt) + { + const xmlChar *itemType, *namespace; + xmlSchemaTypePtr subtype; + + /* Handle the "itemType" attribute. */ + itemType = xmlGetQNameProp(ctxt, type->node, BAD_CAST "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) { + xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_TYPE, + "List %s references an unknown item type: %s\n", + type->name, xmlSchemaGetProp(ctxt, type->node, BAD_CAST "itemType")); + } else + type->subtypes = subtype; + } + } + + /** + * xmlSchemaParseUnionRefCheck: + * @typeDecl: the schema type definition + * @ctxt: the schema parser context + * + * Checks the memberTypes references of the union type. + */ static void ! xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt) { const xmlChar *cur, *end, *prefix, *ncName, *namespace; *************** *** 4400,4409 **** xmlNsPtr ns; int len; ! if ((typeDecl->type != XML_SCHEMA_TYPE_UNION) || (typeDecl->ref == NULL)) return; ! cur = typeDecl->ref; do { while (IS_BLANK_CH(*cur)) cur++; --- 4663,4672 ---- xmlNsPtr ns; int len; ! if ((type->type != XML_SCHEMA_TYPE_UNION) || (type->ref == NULL)) return; ! cur = type->ref; do { while (IS_BLANK_CH(*cur)) cur++; *************** *** 4420,4445 **** prefix = NULL; ncName = tmp; } ! ns = xmlSearchNs(typeDecl->node->doc, typeDecl->node, prefix); if (ns == NULL) { ! xmlSchemaPErr(ctxt, typeDecl->node, XML_SCHEMAP_PREFIX_UNDEFINED, ! "Union %s: the namespace of member type %s is undefined\n", ! typeDecl->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, typeDecl->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE, ! "Union %s references an unknown member type >%s<\n", ! typeDecl->name, (const xmlChar *) tmp); } ! xmlFree(tmp); cur = end; ! } while (*cur != 0); ! } /** --- 4683,4709 ---- 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); } /** *************** *** 4485,4494 **** typeDecl->baseType = baseType; } if (typeDecl->subtypes == NULL) ! if (typeDecl->baseType != NULL) typeDecl->contentType = typeDecl->baseType->contentType; ! else /* 1.1.1 */ typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY; else if ((typeDecl->subtypes->subtypes == NULL) && --- 4749,4761 ---- typeDecl->baseType = baseType; } if (typeDecl->subtypes == NULL) ! if (typeDecl->baseType != NULL) { ! /* The base type might be not "type fixed" yet, so do it now. */ ! if (typeDecl->baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN) ! xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL); typeDecl->contentType = typeDecl->baseType->contentType; ! } else /* 1.1.1 */ typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY; else if ((typeDecl->subtypes->subtypes == NULL) && *************** *** 4645,4650 **** --- 4912,4918 ---- case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: 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: *************** *** 4942,4948 **** } xmlSchemaAttrFixup(ref, ctxt, NULL); attrDecl->subtypes = ref->subtypes; ! } else { xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF, "Schemas: attribute %s has no type nor reference\n", name, NULL); --- 5210,5216 ---- } 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); *************** *** 5588,5594 **** if ((nodelist->type != XML_TEXT_NODE) && (nodelist->type != XML_COMMENT_NODE) && (nodelist->type != XML_PI_NODE) && ! (nodelist->type != XML_PI_NODE)) { return (0); } nodelist = nodelist->next; --- 5856,5862 ---- if ((nodelist->type != XML_TEXT_NODE) && (nodelist->type != XML_COMMENT_NODE) && (nodelist->type != XML_PI_NODE) && ! (nodelist->type != XML_CDATA_SECTION_NODE)) { return (0); } nodelist = nodelist->next; *************** *** 5717,5725 **** xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) { xmlNodePtr child; ! xmlSchemaTypePtr type; xmlAttrPtr attr; int ret; child = ctxt->node; type = ctxt->type; --- 5985,5995 ---- xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) { xmlNodePtr child; ! xmlSchemaTypePtr type, base, variety; xmlAttrPtr attr; int ret; + xmlChar *value; + child = ctxt->node; type = ctxt->type; *************** *** 5741,5747 **** } /* * Validation Rule: Element Locally Valid (Type): 3.1.1 ! */ attr = node->properties; while (attr != NULL) { if ((attr->ns == NULL) || --- 6011,6018 ---- } /* * Validation Rule: Element Locally Valid (Type): 3.1.1 ! */ ! attr = node->properties; while (attr != NULL) { if ((attr->ns == NULL) || *************** *** 5755,5763 **** return (ctxt->err); } } ! ctxt->type = type->subtypes; ! ret = xmlSchemaValidateSimpleContent(ctxt, node); ctxt->type = type; return (ret); } --- 6026,6079 ---- return (ctxt->err); } } + /* TODO: + * If {variety} is ·atomic· then the {variety} of {base type definition} must be ·atomic·. + * If {variety} is ·list· then the {variety} of {item type definition} must be either ·atomic· or ·union·. + * If {variety} is ·union· then {member type definitions} must be a list of datatype definitions. + */ + if (type->subtypes == NULL) { + xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType; simple type %s does not define a variety\n", node->name, NULL); + return (ctxt->err); + } + /* Varieties: Restriction or List or Union. */ + variety = type->subtypes; + ctxt->type = variety; + 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); ! } ! if ((ret == 0) && (variety->attributes != NULL)) { ! ret = xmlSchemaValidateAttributes(ctxt, node, variety->attributes); ! } ! break; ! } ! case XML_SCHEMA_TYPE_LIST: ! case XML_SCHEMA_TYPE_UNION: { ! ret = xmlSchemaValidateSimpleValue(ctxt, variety, value); ! break; ! } ! default:{ ! xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType; simple type %s defines unknown content: %s\n", variety->name, NULL); ! ret = ctxt->err; ! } ! } ! if (value != NULL) ! xmlFree(value); ! ! /* This was removed, since a simple content is not a content of a simple type, but of a complex type. ! * ret = xmlSchemaValidateSimpleContent(ctxt, node); ! */ ctxt->type = type; return (ret); } *************** *** 6008,6013 **** --- 6324,6336 ---- */ 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); } *************** *** 6019,6025 **** } if (type->baseType != NULL) { ctxt->type = type->baseType; ! xmlSchemaValidateBasicType(ctxt, node); } if (type->attributes != NULL) { xmlSchemaValidateAttributes(ctxt, node, --- 6342,6358 ---- } 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, *************** *** 6098,6103 **** --- 6431,6437 ---- ctxt->type = (xmlSchemaTypePtr) decl->refDecl; decl = decl->refDecl; } + /* TODO: Should "xmlSchemaValidateElement" be called instead? */ xmlSchemaValidateElementType(ctxt, node); ctxt->type = type; break; *************** *** 6197,6203 **** * 3.3.4 : 2 */ if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) { ! xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL); return (ctxt->err); } /* --- 6531,6539 ---- * 3.3.4 : 2 */ if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) { ! xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element declaration %s is abstract\n", elemDecl->name, NULL); ! /* Changed, since the element declaration is abstract and not the element itself. */ ! /* xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL); */ return (ctxt->err); } /* *************** *** 6293,6303 **** */ if (attr->ns == NULL) { /* ! * accept an unqualified attribute only if the declaration ! * is unqualified or if the schemas allowed it. */ ! if ((attributes->targetNamespace != NULL) && ! ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) continue; } else { if (attributes->targetNamespace == NULL) --- 6629,6644 ---- */ if (attr->ns == NULL) { /* ! * accept an unqualified attribute only if the target namespace ! * of the declaration is absent. */ ! if (attributes->targetNamespace != NULL) ! /* ! * This check was removed, since the target namespace was ! * evaluated during parsing and already took "attributeFormDefault" ! * into account. ! */ ! /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */ continue; } else { if (attributes->targetNamespace == NULL) *************** *** 6369,6374 **** --- 6710,6720 ---- /* * 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)) && *************** *** 6376,6381 **** --- 6722,6728 ---- elemDecl = xmlHashLookup3(ctxt->schema->elemDecl, elem->name, NULL, NULL); } + */ /* * 3.3.4 : 1 *************** *** 6452,6463 **** --- 6799,6812 ---- { xmlNodePtr root; xmlSchemaElementPtr elemDecl; + xmlNodePtr node; root = xmlDocGetRootElement(doc); if (root == NULL) { xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL); return (ctxt->err); } + if (root->ns != NULL) elemDecl = xmlHashLookup3(ctxt->schema->elemDecl, root->name, root->ns->href, NULL);