diff --git a/ChangeLog b/ChangeLog index d53f3867..bbe98d7c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Sun Jan 26 01:49:58 CET 2003 Daniel Veillard + + * relaxng.c: more work on Relax-NG + * test/relaxng/* result/relaxng/*: augmented/updated the + regression tests + Sat Jan 25 18:59:54 CET 2003 Daniel Veillard * README: updated the policy on private mail answers diff --git a/relaxng.c b/relaxng.c index 61af8c0d..2391f72f 100644 --- a/relaxng.c +++ b/relaxng.c @@ -98,6 +98,7 @@ struct _xmlRelaxNGDefine { xmlNodePtr node; /* the node in the source */ xmlChar *name; /* the element local name if present */ xmlChar *ns; /* the namespace local name if present */ + xmlChar *value; /* value when available */ void *data; /* data lib or specific pointer */ xmlRelaxNGDefinePtr content;/* the expected content */ xmlRelaxNGDefinePtr next; /* list within grouping sequences */ @@ -438,6 +439,8 @@ xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define) xmlFree(define->name); if (define->ns != NULL) xmlFree(define->ns); + if (define->value != NULL) + xmlFree(define->value); if (define->attrs != NULL) xmlRelaxNGFreeDefineList(define->attrs); if ((define->content != NULL) && @@ -967,6 +970,88 @@ xmlRelaxNGGetDataTypeLibrary(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED, return(NULL); } +/** + * xmlRelaxNGParseValue: + * @ctxt: a Relax-NG parser context + * @node: the data node. + * + * parse the content of a RelaxNG value node. + * + * Returns the definition pointer or NULL in case of error + */ +static xmlRelaxNGDefinePtr +xmlRelaxNGParseValue(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { + xmlRelaxNGDefinePtr def = NULL; + xmlRelaxNGTypeLibraryPtr lib; + xmlChar *type; + xmlChar *library; + int tmp; + + def = xmlRelaxNGNewDefine(ctxt, node); + if (def == NULL) + return(NULL); + def->type = XML_RELAXNG_VALUE; + + type = xmlGetProp(node, BAD_CAST "type"); + if (type != NULL) { + library = xmlRelaxNGGetDataTypeLibrary(ctxt, node); + if (library == NULL) + library = xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0"); + + def->name = type; + def->ns = library; + + lib = (xmlRelaxNGTypeLibraryPtr) + xmlHashLookup(xmlRelaxNGRegisteredTypes, library); + if (lib == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Use of unregistered type library '%s'\n", + library); + ctxt->nbErrors++; + def->data = NULL; + } else { + def->data = lib; + if (lib->have == NULL) { + ctxt->error(ctxt->userData, + "Internal error with type library '%s': no 'have'\n", + library); + ctxt->nbErrors++; + } else { + tmp = lib->have(lib->data, def->name); + if (tmp != 1) { + ctxt->error(ctxt->userData, + "Error type '%s' is not exported by type library '%s'\n", + def->name, library); + ctxt->nbErrors++; + } + } + } + } + if (node->children == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Element has no content\n"); + ctxt->nbErrors++; + } else if ((node->children->type != XML_TEXT_NODE) || + (node->children->next != NULL)) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Expecting a single text value for content\n"); + ctxt->nbErrors++; + } else { + def->value = xmlNodeGetContent(node); + if (def->value == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Element has no content\n"); + ctxt->nbErrors++; + } + } + /* TODO check ahead of time that the value is okay per the type */ + return(def); +} + /** * xmlRelaxNGParseData: * @ctxt: a Relax-NG parser context @@ -1234,6 +1319,8 @@ xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { } else if (IS_RELAXNG(node, "define")) { xmlRelaxNGParseDefine(ctxt, node); def = NULL; + } else if (IS_RELAXNG(node, "value")) { + def = xmlRelaxNGParseValue(ctxt, node); } else { TODO } @@ -2545,6 +2632,49 @@ xmlRelaxNGSkipIgnored(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED, return(node); } +/** + * xmlRelaxNGNormalize: + * @ctxt: a schema validation context + * @str: the string to normalize + * + * Implements the normalizeWhiteSpace( s ) function from + * section 6.2.9 of the spec + * + * Returns the new string or NULL in case of error. + */ +static xmlChar * +xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar *str) { + xmlChar *ret, *p; + const xmlChar *tmp; + int len; + + if (str == NULL) + return(NULL); + tmp = str; + while (*tmp != 0) tmp++; + len = tmp - str; + + ret = (xmlChar *) xmlMalloc((len + 1) * sizeof(xmlChar)); + if (ret == NULL) { + VALID_CTXT(); + VALID_ERROR("xmlRelaxNGNormalize: out of memory\n"); + return(NULL); + } + p = ret; + while (IS_BLANK(*str)) str++; + while (*str != 0) { + if (IS_BLANK(*str)) { + while (IS_BLANK(*str)) str++; + if (*str == 0) + break; + *p++ = ' '; + } else + *p++ = *str++; + } + *p = 0; + return(ret); +} + /** * xmlRelaxNGValidateDatatype: * @ctxt: a Relax-NG validation context @@ -2596,7 +2726,7 @@ xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar *value, static int xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGDefinePtr define) { - int ret = 0; + int ret = 0, oldflags; xmlChar *value; value = ctxt->state->value; @@ -2607,6 +2737,46 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, break; case XML_RELAXNG_TEXT: break; + case XML_RELAXNG_CHOICE: { + xmlRelaxNGDefinePtr list = define->content; + + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + + while (list != NULL) { + ret = xmlRelaxNGValidateValue(ctxt, list); + if (ret == 0) { + break; + } + list = list->next; + } + ctxt->flags = oldflags; + break; + } + case XML_RELAXNG_VALUE: { + if (!xmlStrEqual(value, define->value)) { + if (define->name != NULL) { + TODO /* value validation w.r.t. the type */ + } else { + xmlChar *nval, *nvalue; + + /* + * TODO: trivial optimizations are possible by + * computing at compile-time + */ + nval = xmlRelaxNGNormalize(ctxt, define->value); + nvalue = xmlRelaxNGNormalize(ctxt, value); + + if (!xmlStrEqual(nval, nvalue)) + ret = -1; + if (nval != NULL) + xmlFree(nval); + if (nvalue != NULL) + xmlFree(nvalue); + } + } + break; + } default: TODO ret = -1; diff --git a/result/relaxng/tutor3_2_1.err b/result/relaxng/tutor3_2_1.err index 8e233346..48ac0c4a 100644 --- a/result/relaxng/tutor3_2_1.err +++ b/result/relaxng/tutor3_2_1.err @@ -1,3 +1,3 @@ -error detected at relaxng.c:2812 -error detected at relaxng.c:2860 +error detected at relaxng.c:2982 +error detected at relaxng.c:3030 xmlRelaxNGValidateDefinition(): validated card : -1 diff --git a/result/relaxng/tutor3_5_2.err b/result/relaxng/tutor3_5_2.err index 909ad8b0..9c72d176 100644 --- a/result/relaxng/tutor3_5_2.err +++ b/result/relaxng/tutor3_5_2.err @@ -1,5 +1,5 @@ xmlRelaxNGValidateAttribute(name): -1 xmlRelaxNGValidateDefinition(): validated email : 0 xmlRelaxNGValidateDefinition(): validated card : -1 -error detected at relaxng.c:2860 +error detected at relaxng.c:3030 xmlRelaxNGValidateDefinition(): validated addressBook : -1 diff --git a/result/relaxng/tutor5_1_1.err b/result/relaxng/tutor5_1_1.err index d987a68f..e9fa2d92 100644 --- a/result/relaxng/tutor5_1_1.err +++ b/result/relaxng/tutor5_1_1.err @@ -1,3 +1,3 @@ -Unimplemented block at relaxng.c:667 -Unimplemented block at relaxng.c:686 +Unimplemented block at relaxng.c:670 +Unimplemented block at relaxng.c:689 xmlRelaxNGValidateDefinition(): validated number : 0 diff --git a/result/relaxng/tutor5_2_1.err b/result/relaxng/tutor5_2_1.err index 24865cc6..ac9beb0e 100644 --- a/result/relaxng/tutor5_2_1.err +++ b/result/relaxng/tutor5_2_1.err @@ -1,7 +1,7 @@ -Unimplemented block at relaxng.c:667 -Unimplemented block at relaxng.c:667 -Unimplemented block at relaxng.c:686 +Unimplemented block at relaxng.c:670 +Unimplemented block at relaxng.c:670 +Unimplemented block at relaxng.c:689 xmlRelaxNGValidateDefinition(): validated x : 0 -Unimplemented block at relaxng.c:686 +Unimplemented block at relaxng.c:689 xmlRelaxNGValidateDefinition(): validated y : 0 xmlRelaxNGValidateDefinition(): validated point : 0 diff --git a/result/relaxng/tutor5_3_1.err b/result/relaxng/tutor5_3_1.err index 0ea4f9a1..5f30338e 100644 --- a/result/relaxng/tutor5_3_1.err +++ b/result/relaxng/tutor5_3_1.err @@ -1,3 +1,3 @@ -error detected at relaxng.c:2993 +error detected at relaxng.c:3163 xmlRelaxNGValidateDefinition(): validated note : 0 xmlRelaxNGValidateDefinition(): validated bad : -1 diff --git a/result/relaxng/tutor6_1_1 b/result/relaxng/tutor6_1_1 new file mode 100644 index 00000000..3c44662c --- /dev/null +++ b/result/relaxng/tutor6_1_1 @@ -0,0 +1 @@ +./test/relaxng/tutor6_1_1.xml validates diff --git a/result/relaxng/tutor6_1_1.err b/result/relaxng/tutor6_1_1.err new file mode 100644 index 00000000..6e456218 --- /dev/null +++ b/result/relaxng/tutor6_1_1.err @@ -0,0 +1,4 @@ +xmlRelaxNGValidateAttribute(preferredFormat): 0 +xmlRelaxNGValidateAttribute(email): 0 +xmlRelaxNGValidateAttribute(name): 0 +xmlRelaxNGValidateDefinition(): validated card : 0 diff --git a/result/relaxng/tutor6_1_2 b/result/relaxng/tutor6_1_2 new file mode 100644 index 00000000..6c70fedf --- /dev/null +++ b/result/relaxng/tutor6_1_2 @@ -0,0 +1 @@ +./test/relaxng/tutor6_1_2.xml validates diff --git a/result/relaxng/tutor6_1_2.err b/result/relaxng/tutor6_1_2.err new file mode 100644 index 00000000..6e456218 --- /dev/null +++ b/result/relaxng/tutor6_1_2.err @@ -0,0 +1,4 @@ +xmlRelaxNGValidateAttribute(preferredFormat): 0 +xmlRelaxNGValidateAttribute(email): 0 +xmlRelaxNGValidateAttribute(name): 0 +xmlRelaxNGValidateDefinition(): validated card : 0 diff --git a/result/relaxng/tutor6_1_3 b/result/relaxng/tutor6_1_3 new file mode 100644 index 00000000..2dea6749 --- /dev/null +++ b/result/relaxng/tutor6_1_3 @@ -0,0 +1,2 @@ +Extra attribute preferredFormat for element card +./test/relaxng/tutor6_1_3.xml validation generated an internal error diff --git a/result/relaxng/tutor6_1_3.err b/result/relaxng/tutor6_1_3.err new file mode 100644 index 00000000..68f183fd --- /dev/null +++ b/result/relaxng/tutor6_1_3.err @@ -0,0 +1,5 @@ +xmlRelaxNGValidateAttribute(preferredFormat): -1 +xmlRelaxNGValidateAttribute(email): 0 +xmlRelaxNGValidateAttribute(name): 0 +error detected at relaxng.c:3038 +xmlRelaxNGValidateDefinition(): validated card : -1 diff --git a/test/relaxng/tutor6_1_1.xml b/test/relaxng/tutor6_1_1.xml new file mode 100644 index 00000000..30460aee --- /dev/null +++ b/test/relaxng/tutor6_1_1.xml @@ -0,0 +1 @@ + diff --git a/test/relaxng/tutor6_1_2.xml b/test/relaxng/tutor6_1_2.xml new file mode 100644 index 00000000..bf3dfc24 --- /dev/null +++ b/test/relaxng/tutor6_1_2.xml @@ -0,0 +1 @@ + diff --git a/test/relaxng/tutor6_1_3.xml b/test/relaxng/tutor6_1_3.xml new file mode 100644 index 00000000..6038d790 --- /dev/null +++ b/test/relaxng/tutor6_1_3.xml @@ -0,0 +1 @@ +