From 377e1a9059a439c90be6b7787789c9e0ed76aaba Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Fri, 16 Apr 2004 16:30:05 +0000 Subject: [PATCH] move the TODO as comments as the function while not finished are usable * xmlsave.c: move the TODO as comments as the function while not finished are usable as-is * xmlschemas.c include/libxml/xmlerror.h: patch from Kasimier Buchcik implementing union * test/schemas/union_0_0.x* result/schemas/union_0_0*: added example * python/Makefile.am: applied fix from Mike Hommey Daniel --- ChangeLog | 9 ++ include/libxml/xmlerror.h | 1 + python/Makefile.am | 6 +- result/schemas/union_0_0 | 1 + result/schemas/union_0_0.err | 0 test/schemas/union_0_0.xml | 7 ++ test/schemas/union_0_0.xsd | 50 ++++++++++ xmlsave.c | 6 +- xmlschemas.c | 183 +++++++++++++++++++++++++++++++++-- 9 files changed, 251 insertions(+), 12 deletions(-) create mode 100644 result/schemas/union_0_0 create mode 100644 result/schemas/union_0_0.err create mode 100644 test/schemas/union_0_0.xml create mode 100644 test/schemas/union_0_0.xsd diff --git a/ChangeLog b/ChangeLog index beb6de31..51dd281e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Fri Apr 16 18:22:25 CEST 2004 Daniel Veillard + + * xmlsave.c: move the TODO as comments as the function while not + finished are usable as-is + * xmlschemas.c include/libxml/xmlerror.h: patch from Kasimier Buchcik + implementing union + * test/schemas/union_0_0.x* result/schemas/union_0_0*: added example + * python/Makefile.am: applied fix from Mike Hommey + Fri Apr 16 23:58:42 HKT 2004 William Brack * parser.c: fixed problem with detecting external dtd diff --git a/include/libxml/xmlerror.h b/include/libxml/xmlerror.h index 46d93c41..815000b7 100644 --- a/include/libxml/xmlerror.h +++ b/include/libxml/xmlerror.h @@ -544,6 +544,7 @@ typedef enum { XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI, /* 1769 */ XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI, /* 1770 */ XML_SCHEMAP_NOT_SCHEMA, /* 1771 */ + XML_SCHEMAP_UNKNOWN_MEMBER_TYPE, /* 1772 */ XML_SCHEMAV_NOROOT = 1800, XML_SCHEMAV_UNDECLAREDELEM, /* 1801 */ XML_SCHEMAV_NOTTOPLEVEL, /* 1802 */ diff --git a/python/Makefile.am b/python/Makefile.am index 8782efbb..f4734216 100644 --- a/python/Makefile.am +++ b/python/Makefile.am @@ -51,9 +51,12 @@ GENERATE = generator.py API_DESC = $(top_srcdir)/doc/libxml2-api.xml $(srcdir)/libxml2-python-api.xml GENERATED= $(srcdir)/libxml2class.py \ $(srcdir)/libxml2-export.c \ + $(srcdir)/libxml2class.txt \ $(srcdir)/libxml2-py.c \ $(srcdir)/libxml2-py.h +CLEANFILES= $(GENERATED) gen_prog libxml2.py + $(GENERATED): gen_prog gen_prog: $(srcdir)/$(GENERATE) $(API_DESC) @@ -68,6 +71,3 @@ endif tests test: all cd tests && $(MAKE) tests -clean: - rm -f $(GENERATED) *.o _libxml.so *.pyc libxml2.py gen_prog - diff --git a/result/schemas/union_0_0 b/result/schemas/union_0_0 new file mode 100644 index 00000000..3dbc8615 --- /dev/null +++ b/result/schemas/union_0_0 @@ -0,0 +1 @@ +./test/schemas/union_0_0.xml validates diff --git a/result/schemas/union_0_0.err b/result/schemas/union_0_0.err new file mode 100644 index 00000000..e69de29b diff --git a/test/schemas/union_0_0.xml b/test/schemas/union_0_0.xml new file mode 100644 index 00000000..79078f94 --- /dev/null +++ b/test/schemas/union_0_0.xml @@ -0,0 +1,7 @@ + + + EMP0090 + EMP0099 + + diff --git a/test/schemas/union_0_0.xsd b/test/schemas/union_0_0.xsd new file mode 100644 index 00000000..a6dfad0c --- /dev/null +++ b/test/schemas/union_0_0.xsd @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xmlsave.c b/xmlsave.c index 583fb58b..1a60a315 100644 --- a/xmlsave.c +++ b/xmlsave.c @@ -1265,6 +1265,8 @@ xmlSaveToIO(xmlOutputWriteCallback iowrite, * @doc: a document * * Save a full document to a saving context + * TODO: The function is not fully implemented yet as it does not return the + * byte count but 0 instead * * Returns the number of byte written or -1 in case of error */ @@ -1274,7 +1276,6 @@ xmlSaveDoc(xmlSaveCtxtPtr ctxt, xmlDocPtr doc) long ret = 0; xmlDocContentDumpOutput(ctxt, doc); - TODO /* compute ret */ return(ret); } @@ -1284,6 +1285,8 @@ xmlSaveDoc(xmlSaveCtxtPtr ctxt, xmlDocPtr doc) * @node: a document * * Save a subtree starting at the node parameter to a saving context + * TODO: The function is not fully implemented yet as it does not return the + * byte count but 0 instead * * Returns the number of byte written or -1 in case of error */ @@ -1293,7 +1296,6 @@ xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr node) long ret = 0; xmlNodeDumpOutputInternal(ctxt, node); - TODO /* compute ret */ return(ret); } diff --git a/xmlschemas.c b/xmlschemas.c index 99bf02b9..be7b6ae8 100644 --- a/xmlschemas.c +++ b/xmlschemas.c @@ -2279,7 +2279,7 @@ xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, if (type == NULL) return (NULL); type->node = node; - type->type = XML_SCHEMA_TYPE_LIST; + type->type = XML_SCHEMA_TYPE_UNION; type->id = xmlSchemaGetProp(ctxt, node, "id"); type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes"); @@ -4358,6 +4358,57 @@ xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem, } } +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,6 +4604,7 @@ xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl, 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: @@ -5076,6 +5128,28 @@ static int xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt, 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; @@ -5101,7 +5175,8 @@ xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt, 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 (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; @@ -5115,6 +5190,76 @@ xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt, * * ************************************************************************/ +/** + * 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); + if (tmp != NULL) + xmlFree(tmp); + if (prefix != NULL) + xmlFree(prefix); + 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 @@ -5129,6 +5274,25 @@ xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt, static int 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,7 +5311,7 @@ xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt, } ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value), ctxt->cur); - if (ret != 0) { + 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,7 +5320,7 @@ xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt, base = type->baseType; if (base != NULL) { - ret = xmlSchemaValidateSimpleValue(ctxt, base, value); + ret = xmlSchemaValidateSimpleValueInternal(ctxt, base, value, fireErrors); } else if (type->subtypes != NULL) { TODO } @@ -5168,7 +5332,7 @@ xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt, if (ctxt->schema != NULL) { if (ret == 0) { facet = type->facets; - ret = xmlSchemaValidateFacets(ctxt, base, facet, value); + ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet, value, fireErrors); } } } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) { @@ -5176,7 +5340,7 @@ xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt, base = type->subtypes; if (base != NULL) { - ret = xmlSchemaValidateSimpleValue(ctxt, base, value); + ret = xmlSchemaValidateSimpleValueInternal(ctxt, base, value, fireErrors); } else { TODO} } else if (type->type == XML_SCHEMA_TYPE_LIST) { @@ -5202,12 +5366,17 @@ xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt, if (end == cur) break; tmp = xmlStrndup(cur, end - cur); - ret2 = xmlSchemaValidateSimpleValue(ctxt, base, tmp); + 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 }