Index: xmlschemas.c =================================================================== RCS file: /cvs/gnome/libxml2/xmlschemas.c,v retrieving revision 1.55 diff -c -r1.55 xmlschemas.c *** xmlschemas.c 1 Apr 2004 10:42:31 -0000 1.55 --- xmlschemas.c 15 Apr 2004 11:14:16 -0000 *************** *** 2279,2285 **** if (type == NULL) return (NULL); type->node = node; ! type->type = XML_SCHEMA_TYPE_LIST; type->id = xmlSchemaGetProp(ctxt, node, "id"); type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes"); --- 2279,2285 ---- if (type == NULL) return (NULL); type->node = node; ! type->type = XML_SCHEMA_TYPE_UNION; type->id = xmlSchemaGetProp(ctxt, node, "id"); type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes"); *************** *** 4358,4363 **** --- 4358,4414 ---- } } + static void + xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr typeDecl, + xmlSchemaParserCtxtPtr ctxt) + { + const xmlChar *cur, *end, *prefix, *ncName, *namespace; + xmlChar *tmp; + xmlSchemaTypePtr subtype; + 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++; + 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(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 char *) tmp); + } 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 char *) tmp); + } + xmlFree(tmp); + cur = end; + } while (*cur != 0); + + } + /** * xmlSchemaTypeFixup: * @typeDecl: the schema type definition *************** *** 4553,4558 **** --- 4604,4610 ---- case XML_SCHEMA_TYPE_NOTATION: case XML_SCHEMA_TYPE_LIST: case XML_SCHEMA_TYPE_UNION: + xmlSchemaParseUnionRefCheck(typeDecl, ctxt); case XML_SCHEMA_FACET_MININCLUSIVE: case XML_SCHEMA_FACET_MINEXCLUSIVE: case XML_SCHEMA_FACET_MAXINCLUSIVE: *************** *** 5077,5082 **** --- 5129,5156 ---- xmlSchemaTypePtr base, xmlSchemaFacetPtr facets, const xmlChar * value) { + return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1)); + } + + /** + * xmlSchemaValidateFacetsInternal: + * @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 + * @fireErrors: if 0, only internal errors will be fired; otherwise all errors will be fired. + * + * 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 + xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt, + xmlSchemaTypePtr base, + xmlSchemaFacetPtr facets, const xmlChar * value, int fireErrors) + { int ret = 0; int tmp = 0; xmlSchemaTypeType type; *************** *** 5101,5107 **** if (tmp != 0) { ret = tmp; ! xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_FACET, "Failed to validate type with facet %s\n", (const xmlChar *) xmlSchemaFacetTypeToString(type), NULL); } if (facet != NULL) facet = facet->next; --- 5175,5182 ---- 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 (facet != NULL) facet = facet->next; *************** *** 5116,5121 **** --- 5191,5263 ---- ************************************************************************/ /** + * xmlSchemaValidateSimpleValueUnion: + * @ctxt: a schema validation context + * @type: the type declaration + * @value: the value to validate + * + * Validates a value against a union. + * + * Returns 0 if the value is valid, a positive error code + * number otherwise and -1 in case of internal or API error. + */ + static int + xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt, + xmlSchemaTypePtr type, const xmlChar * value) + { + int ret = 0; + const xmlChar *cur, *end, *prefix, *ncName; + xmlChar *tmp; + xmlSchemaTypePtr subtype; + xmlNsPtr ns; + int len; + + + /* Process referenced memberTypes. */ + 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 = xmlStrndup(tmp, len); + /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */ + } else { + prefix = NULL; + ncName = tmp; + } + /* We won't do additional checks here, since they have been performed during parsing. */ + ns = xmlSearchNs(type->node->doc, type->node, prefix); + /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */ + subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href); + xmlFree(tmp); + ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0); + if ((ret == 0) || (ret == -1)) { + return (ret); + } + cur = end; + } while (*cur != 0); + + if (type->subtypes != NULL) { + subtype = type->subtypes; + do { + ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0); + if ((ret == 0) || (ret == -1)) { + return (ret); + } + subtype = subtype->next; + } while (subtype != NULL); + } + return (ret); + } + + /** * xmlSchemaValidateSimpleValue: * @ctxt: a schema validation context * @type: the type declaration *************** *** 5130,5135 **** --- 5272,5296 ---- xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt, xmlSchemaTypePtr type, const xmlChar * value) { + return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1)); + } + + /** + * xmlSchemaValidateSimpleValue: + * @ctxt: a schema validation context + * @type: the type declaration + * @value: the value to validate + * @fireErrors: if 0, only internal errors will be fired; otherwise all errors will be fired. + * + * Validate a value against a simple type + * + * Returns 0 if the value is valid, a positive error code + * number otherwise and -1 in case of internal or API error. + */ + static int + xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt, + xmlSchemaTypePtr type, const xmlChar * value, int fireErrors) + { int ret = 0; /* *************** *** 5147,5153 **** } ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value), ctxt->cur); ! if (ret != 0) { xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE, "Failed to validate basic type %s\n", type->name, NULL); } } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) { --- 5308,5314 ---- } ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value), ctxt->cur); ! if ((fireErrors) && (ret != 0)) { xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE, "Failed to validate basic type %s\n", type->name, NULL); } } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) { *************** *** 5156,5162 **** base = type->baseType; if (base != NULL) { ! ret = xmlSchemaValidateSimpleValue(ctxt, base, value); } else if (type->subtypes != NULL) { TODO } --- 5317,5323 ---- base = type->baseType; if (base != NULL) { ! ret = xmlSchemaValidateSimpleValueInternal(ctxt, base, value, fireErrors); } else if (type->subtypes != NULL) { TODO } *************** *** 5168,5174 **** if (ctxt->schema != NULL) { if (ret == 0) { facet = type->facets; ! ret = xmlSchemaValidateFacets(ctxt, base, facet, value); } } } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) { --- 5329,5335 ---- if (ctxt->schema != NULL) { if (ret == 0) { facet = type->facets; ! ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet, value, fireErrors); } } } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) { *************** *** 5176,5182 **** base = type->subtypes; if (base != NULL) { ! ret = xmlSchemaValidateSimpleValue(ctxt, base, value); } else { TODO} } else if (type->type == XML_SCHEMA_TYPE_LIST) { --- 5337,5343 ---- base = type->subtypes; if (base != NULL) { ! ret = xmlSchemaValidateSimpleValueInternal(ctxt, base, value, fireErrors); } else { TODO} } else if (type->type == XML_SCHEMA_TYPE_LIST) { *************** *** 5202,5213 **** if (end == cur) break; tmp = xmlStrndup(cur, end - cur); ! ret2 = xmlSchemaValidateSimpleValue(ctxt, base, tmp); xmlFree(tmp); if (ret2 != 0) ret = 1; cur = end; } while (*cur != 0); } else { TODO } --- 5363,5379 ---- if (end == cur) break; tmp = xmlStrndup(cur, end - cur); ! ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base, tmp, fireErrors); xmlFree(tmp); if (ret2 != 0) ret = 1; cur = end; } while (*cur != 0); + } else if (type->type == XML_SCHEMA_TYPE_UNION) { + ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value); + if ((fireErrors) && (ret != 0)) { + xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE, "Failed to validate type %s\n", type->name, NULL); + } } else { TODO }