diff options
author | Daniel Veillard <veillard@src.gnome.org> | 2003-03-16 17:52:32 +0000 |
---|---|---|
committer | Daniel Veillard <veillard@src.gnome.org> | 2003-03-16 17:52:32 +0000 |
commit | fd573f18a53ab92101471a9c95af6cca5e4e3b1e (patch) | |
tree | 0eba4a6bc5efae02b11975a82b656cd5397caa8e | |
parent | 1564e6e52ef9a944c41736c74edb475671ae798c (diff) | |
download | libxml2-fd573f18a53ab92101471a9c95af6cca5e4e3b1e.tar.gz |
switched back to the previous Relax-NG code base, the derivation algorithm
* relaxng.c: switched back to the previous Relax-NG code base,
the derivation algorithm need severe constraining code to avoid
combinatorial explosion. Fixed the problem with Sebastian Rahtz
TEI based example and other bugs
* result/relaxng/*err: updated the results
* test/relaxng/testsuite.xml: started a new test suite
Daniel
26 files changed, 3455 insertions, 2864 deletions
@@ -1,3 +1,12 @@ +Sun Mar 16 18:45:50 CET 2003 Daniel Veillard <daniel@veillard.com> + + * relaxng.c: switched back to the previous Relax-NG code base, + the derivation algorithm need severe constraining code to avoid + combinatorial explosion. Fixed the problem with Sebastian Rahtz + TEI based example and other bugs + * result/relaxng/*err: updated the results + * test/relaxng/testsuite.xml: started a new test suite + Sat Mar 15 22:26:46 CET 2003 Daniel Veillard <daniel@veillard.com> * relaxng.c include/libxml/relaxng.h: After coming to the conclusion diff --git a/include/libxml/relaxng.h b/include/libxml/relaxng.h index 37d399a3..1ba320b8 100644 --- a/include/libxml/relaxng.h +++ b/include/libxml/relaxng.h @@ -67,7 +67,8 @@ typedef enum { XML_RELAXNG_ERR_VALUE, XML_RELAXNG_ERR_LIST, XML_RELAXNG_ERR_NOGRAMMAR, - XML_RELAXNG_ERR_EXTRADATA + XML_RELAXNG_ERR_EXTRADATA, + XML_RELAXNG_ERR_LACKDATA } xmlRelaxNGValidErr; /* @@ -12,6 +12,7 @@ * - handle namespace declarations as attributes. * - add support for DTD compatibility spec * http://www.oasis-open.org/committees/relax-ng/compatibility-20011203.html + * - report better mem allocations at runtime and abort immediately. */ #define IN_LIBXML @@ -46,7 +47,7 @@ static const xmlChar *xmlRelaxNGNs = (const xmlChar *) (xmlStrEqual(node->ns->href, xmlRelaxNGNs))) -/* #define DEBUG 1 */ +/* #define DEBUG 1 */ /* #define DEBUG_GRAMMAR 1 */ /* #define DEBUG_CONTENT 1 */ /* #define DEBUG_TYPE 1 */ @@ -102,9 +103,7 @@ struct _xmlRelaxNGGrammar { typedef enum { -#if 0 XML_RELAXNG_NOOP = -1, /* a no operation from simplification */ -#endif XML_RELAXNG_EMPTY = 0, /* an empty pattern */ XML_RELAXNG_NOT_ALLOWED, /* not allowed top */ XML_RELAXNG_EXCEPT, /* except present in nameclass defs */ @@ -119,43 +118,34 @@ typedef enum { XML_RELAXNG_REF, /* reference to a definition */ XML_RELAXNG_EXTERNALREF, /* reference to an external def */ XML_RELAXNG_PARENTREF, /* reference to a def in the parent grammar */ + XML_RELAXNG_OPTIONAL, /* optional patterns */ + XML_RELAXNG_ZEROORMORE, /* zero or more non empty patterns */ XML_RELAXNG_ONEORMORE, /* one or more non empty patterns */ XML_RELAXNG_CHOICE, /* a choice between non empty patterns */ XML_RELAXNG_GROUP, /* a pair/group of non empty patterns */ XML_RELAXNG_INTERLEAVE, /* interleaving choice of non-empty patterns */ - XML_RELAXNG_START, /* Used to keep track of starts on grammars */ - XML_RELAXNG_AFTER /* only generated at runtime */ + XML_RELAXNG_START /* Used to keep track of starts on grammars */ } xmlRelaxNGType; -#define IS_NULLABLE 1 -#define IS_NOT_NULLABLE 2 -#define IS_DYNAMIC 4 - -struct _xmlRelaxNGShortDefine { - xmlRelaxNGType type; /* the type of definition */ - short flags; /* used for the cycle detection */ - short depth; /* used for the cycle detection */ - xmlRelaxNGDefinePtr content;/* the expected content */ - xmlRelaxNGDefinePtr cont2; /* the second content if dual operator */ - xmlChar *name; /* the element local name if present */ -}; +#define IS_NULLABLE 1 +#define IS_NOT_NULLABLE 2 +#define IS_INDETERMINIST 4 struct _xmlRelaxNGDefine { xmlRelaxNGType type; /* the type of definition */ - short flags; /* used for the cycle detection */ - short depth; /* used for the cycle detection */ - xmlRelaxNGDefinePtr content;/* the expected content */ - xmlRelaxNGDefinePtr cont2; /* the second content if dual operator */ - xmlChar *name; /* the element local name if present */ 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 parent; /* the parent definition, if any */ xmlRelaxNGDefinePtr next; /* list within grouping sequences */ - xmlRelaxNGDefinePtr prop; /* properties */ + xmlRelaxNGDefinePtr attrs; /* list of attributes for elements */ xmlRelaxNGDefinePtr nameClass;/* the nameClass definition if any */ xmlRelaxNGDefinePtr nextHash;/* next define in defs/refs hash tables */ + short depth; /* used for the cycle detection */ + short flags; /* define related flags */ }; /** @@ -277,6 +267,19 @@ struct _xmlRelaxNGValidState { }; /** + * xmlRelaxNGStates: + * + * A RelaxNGs container for validation state + */ +typedef struct _xmlRelaxNGStates xmlRelaxNGStates; +typedef xmlRelaxNGStates *xmlRelaxNGStatesPtr; +struct _xmlRelaxNGStates { + int nbState; /* the number of states */ + int maxState; /* the size of the array */ + xmlRelaxNGValidStatePtr *tabState; +}; + +/** * xmlRelaxNGValidError: * * A RelaxNGs validation error @@ -304,7 +307,6 @@ struct _xmlRelaxNGValidCtxt { xmlRelaxNGPtr schema; /* The schema in use */ xmlDocPtr doc; /* the document being validated */ - xmlRelaxNGValidStatePtr state; /* the current validation state */ int flags; /* validation flags */ int depth; /* validation depth */ @@ -317,12 +319,8 @@ struct _xmlRelaxNGValidCtxt { int errMax; /* Max depth of the error stack */ xmlRelaxNGValidErrorPtr errTab; /* stack of errors */ - /* - * To improve !!! - */ - int defNr; /* number of defines used */ - int defMax; /* number of defines aloocated */ - xmlRelaxNGDefinePtr *defTab; /* pointer to the allocated definitions */ + xmlRelaxNGValidStatePtr state; /* the current validation state */ + xmlRelaxNGStatesPtr states; /* the accumulated state list */ }; /** @@ -445,7 +443,11 @@ static void xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar); static void xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define); static void xmlRelaxNGNormExtSpace(xmlChar *value); static void xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema); -static int xmlRelaxNGIsNullable(xmlRelaxNGDefinePtr define); +static int xmlRelaxNGEqualValidState( + xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED, + xmlRelaxNGValidStatePtr state1, + xmlRelaxNGValidStatePtr state2); +static void xmlRelaxNGFreeValidState(xmlRelaxNGValidStatePtr state); /** * xmlRelaxNGFreeDocument: @@ -661,15 +663,13 @@ xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar) * xmlRelaxNGNewDefine: * @ctxt: a Relax-NG validation context * @node: the node in the input document. - * @type: the define type * * Allocate a new RelaxNG define. * * Returns the newly allocated structure or NULL in case or error */ static xmlRelaxNGDefinePtr -xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, - xmlRelaxNGType type) +xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { xmlRelaxNGDefinePtr ret; @@ -708,7 +708,6 @@ xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, ctxt->defTab[ctxt->defNr++] = ret; ret->node = node; ret->depth = -1; - ret->type = type; return (ret); } @@ -765,6 +764,105 @@ xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define) } /** + * xmlRelaxNGNewStates: + * @ctxt: a Relax-NG validation context + * @size: the default size for the container + * + * Allocate a new RelaxNG validation state container + * TODO: keep a pool in the ctxt + * + * Returns the newly allocated structure or NULL in case or error + */ +static xmlRelaxNGStatesPtr +xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size) +{ + xmlRelaxNGStatesPtr ret; + + if (size < 16) size = 16; + + ret = (xmlRelaxNGStatesPtr) xmlMalloc(sizeof(xmlRelaxNGStates) + + (size - 1) * sizeof(xmlRelaxNGValidStatePtr)); + if (ret == NULL) { + if ((ctxt != NULL) && (ctxt->error != NULL)) + ctxt->error(ctxt->userData, "Out of memory\n"); + return (NULL); + } + ret->nbState = 0; + ret->maxState = size; + ret->tabState = (xmlRelaxNGValidStatePtr *) xmlMalloc( + (size) * sizeof(xmlRelaxNGValidStatePtr)); + if (ret->tabState == NULL) { + if ((ctxt != NULL) && (ctxt->error != NULL)) + ctxt->error(ctxt->userData, "Out of memory\n"); + xmlFree(ret->tabState); + return (NULL); + } + return(ret); +} + +/** + * xmlRelaxNGAddState: + * @ctxt: a Relax-NG validation context + * @states: the states container + * @state: the validation state + * + * Add a RelaxNG validation state to the container + * + * Return 1 in case of success and 0 if this is a duplicate and -1 on error + */ +static int +xmlRelaxNGAddStates(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGStatesPtr states, + xmlRelaxNGValidStatePtr state) +{ + int i; + + if (state == NULL) { + return(-1); + } + if (states->nbState >= states->maxState) { + xmlRelaxNGValidStatePtr *tmp; + int size; + + size = states->maxState * 2; + tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState, + (size) * sizeof(xmlRelaxNGValidStatePtr)); + if (tmp == NULL) { + if ((ctxt != NULL) && (ctxt->error != NULL)) + ctxt->error(ctxt->userData, "Out of memory\n"); + return(-1); + } + states->tabState = tmp; + states->maxState = size; + } + for (i = 0;i < states->nbState;i++) { + if (xmlRelaxNGEqualValidState(ctxt, state, states->tabState[i])) { + xmlRelaxNGFreeValidState(state); + return(0); + } + } + states->tabState[states->nbState++] = state; + return(1); +} + +/** + * xmlRelaxNGFreeStates: + * @ctxt: a Relax-NG validation context + * @states: teh container + * + * Free a RelaxNG validation state container + * TODO: keep a pool in the ctxt + */ +static void +xmlRelaxNGFreeStates(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED, + xmlRelaxNGStatesPtr states) +{ + if (states != NULL) { + xmlFree(states->tabState); + xmlFree(states); + } +} + +/** * xmlRelaxNGNewValidState: * @ctxt: a Relax-NG validation context * @node: the current node or NULL for the document @@ -837,10 +935,83 @@ xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node) } /** + * xmlRelaxNGCopyValidState: + * @ctxt: a Relax-NG validation context + * @state: a validation state + * + * Copy the validation state + * + * Returns the newly allocated structure or NULL in case or error + */ +static xmlRelaxNGValidStatePtr +xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGValidStatePtr state) +{ + xmlRelaxNGValidStatePtr ret; + unsigned int size; + + if (state == NULL) + return(NULL); + + size = sizeof(xmlRelaxNGValidState) + + state->nbAttrs * sizeof(xmlAttrPtr); + ret = (xmlRelaxNGValidStatePtr) xmlMalloc(size); + if (ret == NULL) { + if ((ctxt != NULL) && (ctxt->error != NULL)) + ctxt->error(ctxt->userData, "Out of memory\n"); + return (NULL); + } + memcpy(ret, state, size); + return(ret); +} + +/** + * xmlRelaxNGEqualValidState: + * @ctxt: a Relax-NG validation context + * @state1: a validation state + * @state2: a validation state + * + * Compare the validation states for equality + * + * Returns 1 if equald, 0 otherwise + */ +static int +xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED, + xmlRelaxNGValidStatePtr state1, + xmlRelaxNGValidStatePtr state2) +{ + int i; + + if ((state1 == NULL) || (state2 == NULL)) + return(0); + if (state1 == state2) + return(1); + if (state1->node != state2->node) + return(0); + if (state1->seq != state2->seq) + return(0); + if (state1->nbAttrLeft != state2->nbAttrLeft) + return(0); + if (state1->nbAttrs != state2->nbAttrs) + return(0); + if (state1->endvalue != state2->endvalue) + return(0); + if ((state1->value != state2->value) && + (!xmlStrEqual(state1->value, state2->value))) + return(0); + for (i = 0;i < state1->nbAttrs;i++) { + if (state1->attrs[i] != state2->attrs[i]) + return(0); + } + return(1); +} + +/** * xmlRelaxNGFreeValidState: * @state: a validation state structure * * Deallocate a RelaxNG validation state structure. + * TODO: keep a pool in the ctxt */ static void xmlRelaxNGFreeValidState(xmlRelaxNGValidStatePtr state) @@ -1210,6 +1381,10 @@ xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGValidErr err, return (0); } } + if ((ctxt->err != NULL) && + (ctxt->err->node == ctxt->state->node) && + (ctxt->err->err == err)) + return(ctxt->errNr); cur = &ctxt->errTab[ctxt->errNr]; cur->err = err; cur->arg1 = arg1; @@ -1249,7 +1424,6 @@ xmlRelaxNGValidErrorPop(xmlRelaxNGValidCtxtPtr ctxt) return (ret); } - /** * xmlRelaxNGDocumentPush: * @ctxt: the parser context @@ -1419,6 +1593,7 @@ xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar *URL, #define VALID_ERR2(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL); #define VALID_ERR3(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c); +#ifdef DEBUG static const char * xmlRelaxNGDefName(xmlRelaxNGDefinePtr def) { if (def == NULL) @@ -1437,19 +1612,19 @@ xmlRelaxNGDefName(xmlRelaxNGDefinePtr def) { case XML_RELAXNG_REF: return("ref"); case XML_RELAXNG_EXTERNALREF: return("externalRef"); case XML_RELAXNG_PARENTREF: return("parentRef"); + case XML_RELAXNG_OPTIONAL: return("optional"); + case XML_RELAXNG_ZEROORMORE: return("zeroOrMore"); case XML_RELAXNG_ONEORMORE: return("oneOrMore"); case XML_RELAXNG_CHOICE: return("choice"); case XML_RELAXNG_GROUP: return("group"); case XML_RELAXNG_INTERLEAVE: return("interleave"); case XML_RELAXNG_START: return("start"); -#if 0 case XML_RELAXNG_NOOP: return("noop"); -#endif case XML_RELAXNG_PARAM: return("param"); - case XML_RELAXNG_AFTER: return("after"); } return("unknown"); } +#endif /** * xmlRelaxNGGetErrorString: @@ -1462,138 +1637,115 @@ xmlRelaxNGDefName(xmlRelaxNGDefinePtr def) { * Returns the error string, it must be deallocated by the caller */ static xmlChar * -xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1, - const xmlChar * arg2) -{ +xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar *arg1, + const xmlChar *arg2) { char msg[1000]; if (arg1 == NULL) - arg1 = BAD_CAST ""; + arg1 = BAD_CAST ""; if (arg2 == NULL) - arg2 = BAD_CAST ""; + arg2 = BAD_CAST ""; msg[0] = 0; switch (err) { - case XML_RELAXNG_OK: - return (NULL); - case XML_RELAXNG_ERR_MEMORY: - return (xmlCharStrdup("out of memory")); + case XML_RELAXNG_OK: + return(NULL); + case XML_RELAXNG_ERR_MEMORY: + return(xmlCharStrdup("out of memory")); case XML_RELAXNG_ERR_TYPE: - snprintf(msg, 1000, "failed to validate type %s", arg1); - break; - case XML_RELAXNG_ERR_TYPEVAL: - snprintf(msg, 1000, "Type %s doesn't allow value %s", arg1, - arg2); - break; - case XML_RELAXNG_ERR_TYPECMP: - snprintf(msg, 1000, "failed to compare type %s", arg1); - break; - case XML_RELAXNG_ERR_NOSTATE: - return (xmlCharStrdup("Internal error: no state")); - case XML_RELAXNG_ERR_NODEFINE: - return (xmlCharStrdup("Internal error: no define")); - case XML_RELAXNG_ERR_LISTEXTRA: - snprintf(msg, 1000, "Extra data in list: %s", arg1); - break; - case XML_RELAXNG_ERR_LISTEMPTY: - return (xmlCharStrdup("List is empty")); - case XML_RELAXNG_ERR_INTERNODATA: - return (xmlCharStrdup - ("Internal: interleave block has no data")); - case XML_RELAXNG_ERR_INTERSEQ: - return (xmlCharStrdup("Invalid sequence in interleave")); - case XML_RELAXNG_ERR_INTEREXTRA: - snprintf(msg, 1000, "Extra element %s in interleave", arg1); - break; - case XML_RELAXNG_ERR_ELEMNAME: - snprintf(msg, 1000, "Expecting element %s, got %s", arg1, - arg2); - break; - case XML_RELAXNG_ERR_ELEMNONS: - snprintf(msg, 1000, "Expecting a namespace for element %s", - arg1); - break; - case XML_RELAXNG_ERR_ELEMWRONGNS: - snprintf(msg, 1000, - "Element %s has wrong namespace: expecting %s", arg1, - arg2); - break; - case XML_RELAXNG_ERR_ELEMEXTRANS: - snprintf(msg, 1000, "Expecting no namespace for element %s", - arg1); - break; - case XML_RELAXNG_ERR_ATTRNAME: - snprintf(msg, 1000, "Expecting attribute %s, got %s", arg1, - arg2); - break; - case XML_RELAXNG_ERR_ATTRNONS: - snprintf(msg, 1000, "Expecting a namespace for attribute %s", - arg1); - break; - case XML_RELAXNG_ERR_ATTRWRONGNS: - snprintf(msg, 1000, - "Attribute %s has wrong namespace: expecting %s", - arg1, arg2); - break; - case XML_RELAXNG_ERR_ATTREXTRANS: - snprintf(msg, 1000, "Expecting no namespace for attribute %s", - arg1); - break; - case XML_RELAXNG_ERR_ELEMNOTEMPTY: - snprintf(msg, 1000, "Expecting element %s to be empty", arg1); - break; - case XML_RELAXNG_ERR_NOELEM: - snprintf(msg, 1000, "Expecting an element %s, got nothing", - arg1); - break; - case XML_RELAXNG_ERR_NOTELEM: - return (xmlCharStrdup("Expecting an element got text")); - case XML_RELAXNG_ERR_ATTRVALID: - snprintf(msg, 1000, "Element %s failed to validate attributes", - arg1); - break; - case XML_RELAXNG_ERR_CONTENTVALID: - snprintf(msg, 1000, "Element %s failed to validate content", - arg1); - break; - case XML_RELAXNG_ERR_EXTRACONTENT: - snprintf(msg, 1000, "Element %s has extra content: %s", - arg1, arg2); - break; - case XML_RELAXNG_ERR_INVALIDATTR: - snprintf(msg, 1000, "Invalid attribute %s for element %s", - arg1, arg2); - break; - case XML_RELAXNG_ERR_DATAELEM: - snprintf(msg, 1000, "Datatype element %s has child elements", - arg1); - break; - case XML_RELAXNG_ERR_VALELEM: - snprintf(msg, 1000, "Value element %s has child elements", - arg1); - break; - case XML_RELAXNG_ERR_LISTELEM: - snprintf(msg, 1000, "List element %s has child elements", - arg1); - break; - case XML_RELAXNG_ERR_DATATYPE: - snprintf(msg, 1000, "Error validating datatype %s", arg1); - break; - case XML_RELAXNG_ERR_VALUE: - snprintf(msg, 1000, "Error validating value %s", arg1); - break; - case XML_RELAXNG_ERR_LIST: - return (xmlCharStrdup("Error validating list")); - case XML_RELAXNG_ERR_NOGRAMMAR: - return (xmlCharStrdup("No top grammar defined")); - case XML_RELAXNG_ERR_EXTRADATA: - return (xmlCharStrdup("Extra data in the document")); + snprintf(msg, 1000, "failed to validate type %s", arg1); + break; + case XML_RELAXNG_ERR_TYPEVAL: + snprintf(msg, 1000, "Type %s doesn't allow value %s", arg1, arg2); + break; + case XML_RELAXNG_ERR_TYPECMP: + snprintf(msg, 1000, "failed to compare type %s", arg1); + break; + case XML_RELAXNG_ERR_NOSTATE: + return(xmlCharStrdup("Internal error: no state")); + case XML_RELAXNG_ERR_NODEFINE: + return(xmlCharStrdup("Internal error: no define")); + case XML_RELAXNG_ERR_LISTEXTRA: + snprintf(msg, 1000, "Extra data in list: %s", arg1); + break; + case XML_RELAXNG_ERR_INTERNODATA: + return(xmlCharStrdup("Internal: interleave block has no data")); + case XML_RELAXNG_ERR_INTERSEQ: + return(xmlCharStrdup("Invalid sequence in interleave")); + case XML_RELAXNG_ERR_INTEREXTRA: + snprintf(msg, 1000, "Extra element %s in interleave", arg1); + break; + case XML_RELAXNG_ERR_ELEMNAME: + snprintf(msg, 1000, "Expecting element %s, got %s", arg1, arg2); + break; + case XML_RELAXNG_ERR_ELEMNONS: + snprintf(msg, 1000, "Expecting a namespace for element %s", arg1); + break; + case XML_RELAXNG_ERR_ELEMWRONGNS: + snprintf(msg, 1000, "Element %s has wrong namespace: expecting %s", + arg1, arg2); + break; + case XML_RELAXNG_ERR_ELEMEXTRANS: + snprintf(msg, 1000, "Expecting no namespace for element %s", arg1); + break; + case XML_RELAXNG_ERR_ELEMNOTEMPTY: + snprintf(msg, 1000, "Expecting element %s to be empty", arg1); + break; + case XML_RELAXNG_ERR_NOELEM: + snprintf(msg, 1000, "Expecting an element %s, got nothing", arg1); + break; + case XML_RELAXNG_ERR_NOTELEM: + return(xmlCharStrdup("Expecting an element got text")); + case XML_RELAXNG_ERR_ATTRVALID: + snprintf(msg, 1000, "Element %s failed to validate attributes", + arg1); + break; + case XML_RELAXNG_ERR_CONTENTVALID: + snprintf(msg, 1000, "Element %s failed to validate content", + arg1); + break; + case XML_RELAXNG_ERR_EXTRACONTENT: + snprintf(msg, 1000, "Element %s has extra content: %s", + arg1, arg2); + break; + case XML_RELAXNG_ERR_INVALIDATTR: + snprintf(msg, 1000, "Invalid attribute %s for element %s", + arg1, arg2); + break; + case XML_RELAXNG_ERR_DATAELEM: + snprintf(msg, 1000, "Datatype element %s has child elements", + arg1); + break; + case XML_RELAXNG_ERR_VALELEM: + snprintf(msg, 1000, "Value element %s has child elements", + arg1); + break; + case XML_RELAXNG_ERR_LISTELEM: + snprintf(msg, 1000, "List element %s has child elements", + arg1); + break; + case XML_RELAXNG_ERR_DATATYPE: + snprintf(msg, 1000, "Error validating datatype %s", + arg1); + break; + case XML_RELAXNG_ERR_VALUE: + snprintf(msg, 1000, "Error validating value %s", + arg1); + break; + case XML_RELAXNG_ERR_LIST: + return(xmlCharStrdup("Error validating list")); + case XML_RELAXNG_ERR_NOGRAMMAR: + return(xmlCharStrdup("No top grammar defined")); + case XML_RELAXNG_ERR_EXTRADATA: + return(xmlCharStrdup("Extra data in the document")); + default: + TODO } if (msg[0] == 0) { - snprintf(msg, 1000, "Unknown error code %d", err); + snprintf(msg, 1000, "Unknown error code %d", err); } msg[1000] = 0; - return (xmlStrdup((xmlChar *) msg)); + return(xmlStrdup((xmlChar *) msg)); } /** @@ -2168,8 +2320,8 @@ static xmlRelaxNGDefinePtr xmlRelaxNGParseNameClass( xmlRelaxNGDefinePtr def); static xmlRelaxNGGrammarPtr xmlRelaxNGParseGrammar( xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes); -static int xmlRelaxNGNsNameMatch(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr define, xmlNodePtr elem, int eora); +static int xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define, xmlNodePtr elem); #define IS_BLANK_NODE(n) \ @@ -2178,6 +2330,80 @@ static int xmlRelaxNGNsNameMatch(xmlRelaxNGValidCtxtPtr ctxt, (xmlRelaxNGIsBlank((n)->content))) /** + * xmlRelaxNGIsNullable: + * @define: the definition to verify + * + * Check if a definition is nullable. + * + * Returns 1 if yes, 0 if no and -1 in case of error + */ +static int +xmlRelaxNGIsNullable(xmlRelaxNGDefinePtr define) { + int ret; + if (define == NULL) + return(-1); + + if (define->flags & IS_NULLABLE) + return(1); + if (define->flags & IS_NOT_NULLABLE) + return(0); + switch (define->type) { + case XML_RELAXNG_EMPTY: + case XML_RELAXNG_TEXT: + ret = 1; break; + case XML_RELAXNG_NOOP: + case XML_RELAXNG_DEF: + case XML_RELAXNG_REF: + case XML_RELAXNG_EXTERNALREF: + case XML_RELAXNG_PARENTREF: + case XML_RELAXNG_ONEORMORE: + ret = xmlRelaxNGIsNullable(define->content); + break; + case XML_RELAXNG_EXCEPT: + case XML_RELAXNG_NOT_ALLOWED: + case XML_RELAXNG_ELEMENT: + case XML_RELAXNG_DATATYPE: + case XML_RELAXNG_PARAM: + case XML_RELAXNG_VALUE: + case XML_RELAXNG_LIST: + case XML_RELAXNG_ATTRIBUTE: + ret = 0; break; + case XML_RELAXNG_CHOICE: { + xmlRelaxNGDefinePtr list = define->content; + + while (list != NULL) { + ret = xmlRelaxNGIsNullable(list); + if (ret != 0) + goto done; + list = list->next; + } + ret = 0; break; + } + case XML_RELAXNG_START: + case XML_RELAXNG_INTERLEAVE: + case XML_RELAXNG_GROUP: { + xmlRelaxNGDefinePtr list = define->content; + + while (list != NULL) { + ret = xmlRelaxNGIsNullable(list); + if (ret != 1) + goto done; + list = list->next; + } + return(1); + } + default: + return(-1); + } +done: + if (ret == 0) + define->flags |= IS_NOT_NULLABLE; + if (ret == 1) + define->flags |= IS_NULLABLE; + return(ret); +} + +/** * xmlRelaxNGIsBlank: * @str: a string * @@ -2262,9 +2488,10 @@ xmlRelaxNGParseValue(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { xmlChar *library; int tmp; - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_VALUE); + def = xmlRelaxNGNewDefine(ctxt, node); if (def == NULL) return(NULL); + def->type = XML_RELAXNG_VALUE; type = xmlGetProp(node, BAD_CAST "type"); if (type != NULL) { @@ -2373,11 +2600,12 @@ xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { if (library == NULL) library = xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0"); - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_DATATYPE); + def = xmlRelaxNGNewDefine(ctxt, node); if (def == NULL) { xmlFree(type); return(NULL); } + def->type = XML_RELAXNG_DATATYPE; def->name = type; def->ns = library; @@ -2429,8 +2657,9 @@ xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { (xmlStrEqual(content->name, BAD_CAST "param"))) content = content->next; } else { - param = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_PARAM); + param = xmlRelaxNGNewDefine(ctxt, node); if (param != NULL) { + param->type = XML_RELAXNG_PARAM; param->name = xmlGetProp(content, BAD_CAST "name"); if (param->name == NULL) { if (ctxt->error != NULL) @@ -2440,7 +2669,7 @@ xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { } param->value = xmlNodeGetContent(content); if (lastparam == NULL) { - def->prop = lastparam = param; + def->attrs = lastparam = param; } else { lastparam->next = param; lastparam = param; @@ -2458,10 +2687,11 @@ xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { xmlNodePtr child; xmlRelaxNGDefinePtr tmp2, last2 = NULL; - except = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_EXCEPT); + except = xmlRelaxNGNewDefine(ctxt, node); if (except == NULL) { return(def); } + except->type = XML_RELAXNG_EXCEPT; child = content->children; if (last == NULL) { def->content = except; @@ -2546,8 +2776,7 @@ xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1, } else { ns.href = invalidName; } - if (xmlRelaxNGNsNameMatch(&ctxt, def2, &node, - (def1->type == XML_RELAXNG_ELEMENT))) { + if (xmlRelaxNGElementMatch(&ctxt, def2, &node)) { if (def1->nameClass != NULL) { ret = xmlRelaxNGCompareNameClasses(def1->nameClass, def2); } else { @@ -2586,8 +2815,7 @@ xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1, } else { ns.href = invalidName; } - if (xmlRelaxNGNsNameMatch(&ctxt, def1, &node, - (def1->type == XML_RELAXNG_ELEMENT))) { + if (xmlRelaxNGElementMatch(&ctxt, def1, &node)) { if (def2->nameClass != NULL) { ret = xmlRelaxNGCompareNameClasses(def2->nameClass, def1); } else { @@ -2652,7 +2880,7 @@ static xmlRelaxNGDefinePtr * xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def, int eora) { - xmlRelaxNGDefinePtr *ret = NULL, parent, cur; + xmlRelaxNGDefinePtr *ret = NULL, parent, cur, tmp; int len = 0; int max = 0; @@ -2697,28 +2925,27 @@ xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt, (cur->type == XML_RELAXNG_INTERLEAVE) || (cur->type == XML_RELAXNG_GROUP) || (cur->type == XML_RELAXNG_ONEORMORE) || + (cur->type == XML_RELAXNG_ZEROORMORE) || + (cur->type == XML_RELAXNG_OPTIONAL) || (cur->type == XML_RELAXNG_REF) || (cur->type == XML_RELAXNG_DEF)) { /* * Don't go within elements or attributes or string values. * Just gather the element top list */ - if (cur->cont2 != NULL) - cur->cont2->parent = cur; if (cur->content != NULL) { parent = cur; cur = cur->content; - cur->parent = parent; + tmp = cur; + while (tmp != NULL) { + tmp->parent = parent; + tmp = tmp->next; + } continue; } } if (cur == def) break; - if ((cur->parent != NULL) && (cur == cur->parent->content) && - (cur->parent->cont2 != NULL)) { - cur = cur->parent->cont2; - continue; - } if (cur->next != NULL) { cur = cur->next; continue; @@ -2737,21 +2964,23 @@ xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt, } /** - * xmlRelaxNGCheckGroupAttrs: + * xmlRelaxNGCheckChoiceDeterminism: * @ctxt: a Relax-NG parser context - * @def: the group definition + * @def: the choice definition * - * Detects violations of rule 7.3 + * Also used to find indeterministic pattern in choice */ static void -xmlRelaxNGCheckGroupAttrs(xmlRelaxNGParserCtxtPtr ctxt, - xmlRelaxNGDefinePtr def) { - xmlRelaxNGDefinePtr *list[2]; - int ret; +xmlRelaxNGCheckChoiceDeterminism(xmlRelaxNGParserCtxtPtr ctxt, + xmlRelaxNGDefinePtr def) { + xmlRelaxNGDefinePtr **list; + xmlRelaxNGDefinePtr cur; + int nbchild = 0, i, j, ret; + int is_nullable = 0; + int is_indeterminist = 0; if ((def == NULL) || - ((def->type != XML_RELAXNG_GROUP) && - (def->type != XML_RELAXNG_INTERLEAVE))) + (def->type != XML_RELAXNG_CHOICE)) return; /* @@ -2761,43 +2990,71 @@ xmlRelaxNGCheckGroupAttrs(xmlRelaxNGParserCtxtPtr ctxt, if (ctxt->nbErrors != 0) return; - list[0] = xmlRelaxNGGetElements(ctxt, def->content, 1); - list[1] = xmlRelaxNGGetElements(ctxt, def->cont2, 1); + is_nullable = xmlRelaxNGIsNullable(def); - ret = xmlRelaxNGCompareElemDefLists(ctxt, list[0], list[1]); - if (ret == 0) { - if (ctxt->error != NULL) { - if (def->type == XML_RELAXNG_GROUP) - ctxt->error(ctxt->userData, - "Attributes conflicts in group\n"); - else - ctxt->error(ctxt->userData, - "Attributes conflicts in interleave\n"); + cur = def->content; + while (cur != NULL) { + nbchild++; + cur = cur->next; + } - } + list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild * + sizeof(xmlRelaxNGDefinePtr *)); + if (list == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Out of memory in choice computation\n"); ctxt->nbErrors++; + return; + } + i = 0; + cur = def->content; + while (cur != NULL) { + list[i] = xmlRelaxNGGetElements(ctxt, cur, 0); + i++; + cur = cur->next; + } + + for (i = 0;i < nbchild;i++) { + if (list[i] == NULL) + continue; + for (j = 0;j < i;j++) { + if (list[j] == NULL) + continue; + ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]); + if (ret == 0) { + is_indeterminist = 1; + } + } + } + for (i = 0;i < nbchild;i++) { + if (list[i] != NULL) + xmlFree(list[i]); + } + + xmlFree(list); + if (is_indeterminist) { + def->flags |= IS_INDETERMINIST; } - if (list[0] != NULL) - xmlFree(list[0]); - if (list[1] != NULL) - xmlFree(list[1]); } /** - * xmlRelaxNGCheckInterleave: + * xmlRelaxNGCheckGroupAttrs: * @ctxt: a Relax-NG parser context * @def: the group definition * * Detects violations of rule 7.3 */ static void -xmlRelaxNGCheckInterleave(xmlRelaxNGParserCtxtPtr ctxt, +xmlRelaxNGCheckGroupAttrs(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def) { - xmlRelaxNGDefinePtr *list[2]; - int ret; + xmlRelaxNGDefinePtr **list; + xmlRelaxNGDefinePtr cur; + int nbchild = 0, i, j, ret; if ((def == NULL) || - (def->type != XML_RELAXNG_INTERLEAVE)) + ((def->type != XML_RELAXNG_GROUP) && + (def->type != XML_RELAXNG_ELEMENT))) return; /* @@ -2807,21 +3064,186 @@ xmlRelaxNGCheckInterleave(xmlRelaxNGParserCtxtPtr ctxt, if (ctxt->nbErrors != 0) return; - list[0] = xmlRelaxNGGetElements(ctxt, def->content, 0); - list[1] = xmlRelaxNGGetElements(ctxt, def->cont2, 0); + cur = def->attrs; + while (cur != NULL) { + nbchild++; + cur = cur->next; + } + cur = def->content; + while (cur != NULL) { + nbchild++; + cur = cur->next; + } - ret = xmlRelaxNGCompareElemDefLists(ctxt, list[0], list[1]); - if (ret == 0) { - if (ctxt->error != NULL) { + list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild * + sizeof(xmlRelaxNGDefinePtr *)); + if (list == NULL) { + if (ctxt->error != NULL) ctxt->error(ctxt->userData, - "Element or text conflicts in interleave\n"); - } + "Out of memory in group computation\n"); ctxt->nbErrors++; + return; + } + i = 0; + cur = def->attrs; + while (cur != NULL) { + list[i] = xmlRelaxNGGetElements(ctxt, cur, 1); + i++; + cur = cur->next; + } + cur = def->content; + while (cur != NULL) { + list[i] = xmlRelaxNGGetElements(ctxt, cur, 1); + i++; + cur = cur->next; + } + + for (i = 0;i < nbchild;i++) { + if (list[i] == NULL) + continue; + for (j = 0;j < i;j++) { + if (list[j] == NULL) + continue; + ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]); + if (ret == 0) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Attributes conflicts in group\n"); + ctxt->nbErrors++; + } + } + } + for (i = 0;i < nbchild;i++) { + if (list[i] != NULL) + xmlFree(list[i]); + } + + xmlFree(list); +} + +/** + * xmlRelaxNGComputeInterleaves: + * @def: the interleave definition + * @ctxt: a Relax-NG parser context + * @name: the definition name + * + * A lot of work for preprocessing interleave definitions + * is potentially needed to get a decent execution speed at runtime + * - trying to get a total order on the element nodes generated + * by the interleaves, order the list of interleave definitions + * following that order. + * - if <text/> is used to handle mixed content, it is better to + * flag this in the define and simplify the runtime checking + * algorithm + */ +static void +xmlRelaxNGComputeInterleaves(xmlRelaxNGDefinePtr def, + xmlRelaxNGParserCtxtPtr ctxt, + xmlChar *name ATTRIBUTE_UNUSED) { + xmlRelaxNGDefinePtr cur; + + xmlRelaxNGPartitionPtr partitions = NULL; + xmlRelaxNGInterleaveGroupPtr *groups = NULL; + xmlRelaxNGInterleaveGroupPtr group; + int i,j,ret; + int nbgroups = 0; + int nbchild = 0; + + /* + * Don't run that check in case of error. Infinite recursion + * becomes possible. + */ + if (ctxt->nbErrors != 0) + return; + +#ifdef DEBUG_INTERLEAVE + xmlGenericError(xmlGenericErrorContext, + "xmlRelaxNGComputeInterleaves(%s)\n", + name); +#endif + cur = def->content; + while (cur != NULL) { + nbchild++; + cur = cur->next; + } + +#ifdef DEBUG_INTERLEAVE + xmlGenericError(xmlGenericErrorContext, " %d child\n", nbchild); +#endif + groups = (xmlRelaxNGInterleaveGroupPtr *) + xmlMalloc(nbchild * sizeof(xmlRelaxNGInterleaveGroupPtr)); + if (groups == NULL) + goto error; + cur = def->content; + while (cur != NULL) { + groups[nbgroups] = (xmlRelaxNGInterleaveGroupPtr) + xmlMalloc(sizeof(xmlRelaxNGInterleaveGroup)); + if (groups[nbgroups] == NULL) + goto error; + groups[nbgroups]->rule = cur; + groups[nbgroups]->defs = xmlRelaxNGGetElements(ctxt, cur, 0); + groups[nbgroups]->attrs = xmlRelaxNGGetElements(ctxt, cur, 1); + nbgroups++; + cur = cur->next; + } +#ifdef DEBUG_INTERLEAVE + xmlGenericError(xmlGenericErrorContext, " %d groups\n", nbgroups); +#endif + + /* + * Let's check that all rules makes a partitions according to 7.4 + */ + partitions = (xmlRelaxNGPartitionPtr) + xmlMalloc(sizeof(xmlRelaxNGPartition)); + if (partitions == NULL) + goto error; + partitions->nbgroups = nbgroups; + for (i = 0;i < nbgroups;i++) { + group = groups[i]; + for (j = i+1;j < nbgroups;j++) { + if (groups[j] == NULL) + continue; + ret = xmlRelaxNGCompareElemDefLists(ctxt, group->defs, + groups[j]->defs); + if (ret == 0) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Element or text conflicts in interleave\n"); + ctxt->nbErrors++; + } + ret = xmlRelaxNGCompareElemDefLists(ctxt, group->attrs, + groups[j]->attrs); + if (ret == 0) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Attributes conflicts in interleave\n"); + ctxt->nbErrors++; + } + } + } + partitions->groups = groups; + + /* + * and save the partition list back in the def + */ + def->data = partitions; + return; + +error: + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Out of memory in interleave computation\n"); + ctxt->nbErrors++; + if (groups != NULL) { + for (i = 0;i < nbgroups;i++) + if (groups[i] != NULL) { + if (groups[i]->defs != NULL) + xmlFree(groups[i]->defs); + xmlFree(groups[i]); + } + xmlFree(groups); } - if (list[0] != NULL) - xmlFree(list[0]); - if (list[1] != NULL) - xmlFree(list[1]); + xmlRelaxNGFreePartition(partitions); } /** @@ -2836,32 +3258,57 @@ xmlRelaxNGCheckInterleave(xmlRelaxNGParserCtxtPtr ctxt, static xmlRelaxNGDefinePtr xmlRelaxNGParseInterleave(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { xmlRelaxNGDefinePtr def = NULL; + xmlRelaxNGDefinePtr last = NULL, cur; xmlNodePtr child; - child = node->children; - if (child == NULL) { + def = xmlRelaxNGNewDefine(ctxt, node); + if (def == NULL) { + return(NULL); + } + def->type = XML_RELAXNG_INTERLEAVE; + + if (ctxt->interleaves == NULL) + ctxt->interleaves = xmlHashCreate(10); + if (ctxt->interleaves == NULL) { if (ctxt->error != NULL) - ctxt->error(ctxt->userData, "Element interleave is empty\n"); + ctxt->error(ctxt->userData, + "Failed to create interleaves hash table\n"); ctxt->nbErrors++; - } else if (child->next == NULL) { - def = xmlRelaxNGParseElement(ctxt, child); } else { - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_INTERLEAVE); - if (def == NULL) { - return(NULL); - } + char name[32]; - def->content = xmlRelaxNGParsePattern(ctxt, child); - child = child->next; - def->cont2 = xmlRelaxNGParsePattern(ctxt, child); - child = child->next; - if (child != NULL) { + snprintf(name, 32, "interleave%d", ctxt->nbInterleaves++); + if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST name, def) < 0) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, - "Internal: interleave has more than 2 children"); + "Failed to add %s to hash table\n", name); ctxt->nbErrors++; } } + child = node->children; + if (child == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, "Element interleave is empty\n"); + ctxt->nbErrors++; + } + while (child != NULL) { + if (IS_RELAXNG(child, "element")) { + cur = xmlRelaxNGParseElement(ctxt, child); + } else { + cur = xmlRelaxNGParsePattern(ctxt, child); + } + if (cur != NULL) { + cur->parent = def; + if (last == NULL) { + def->content = last = cur; + } else { + last->next = cur; + last = cur; + } + } + child = child->next; + } + return(def); } @@ -2951,11 +3398,12 @@ xmlRelaxNGParseDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { name); ctxt->nbErrors++; } - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_DEF); + def = xmlRelaxNGNewDefine(ctxt, node); if (def == NULL) { xmlFree(name); return(-1); } + def->type = XML_RELAXNG_DEF; def->name = name; if (node->children == NULL) { if (ctxt->error != NULL) @@ -3019,9 +3467,10 @@ xmlRelaxNGProcessExternalRef(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { docu = node->_private; if (docu != NULL) { - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_EXTERNALREF); + def = xmlRelaxNGNewDefine(ctxt, node); if (def == NULL) return(NULL); + def->type = XML_RELAXNG_EXTERNALREF; if (docu->content == NULL) { /* @@ -3107,45 +3556,43 @@ xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { } else if (IS_RELAXNG(node, "attribute")) { def = xmlRelaxNGParseAttribute(ctxt, node); } else if (IS_RELAXNG(node, "empty")) { - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_EMPTY); + def = xmlRelaxNGNewDefine(ctxt, node); if (def == NULL) return(NULL); + def->type = XML_RELAXNG_EMPTY; if (node->children != NULL) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, "empty: had a child node\n"); ctxt->nbErrors++; } } else if (IS_RELAXNG(node, "text")) { - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_TEXT); + def = xmlRelaxNGNewDefine(ctxt, node); if (def == NULL) return(NULL); + def->type = XML_RELAXNG_TEXT; if (node->children != NULL) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, "text: had a child node\n"); ctxt->nbErrors++; } } else if (IS_RELAXNG(node, "zeroOrMore")) { - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_CHOICE); + def = xmlRelaxNGNewDefine(ctxt, node); if (def == NULL) return(NULL); + def->type = XML_RELAXNG_ZEROORMORE; if (node->children == NULL) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, "Element %s is empty\n", node->name); ctxt->nbErrors++; } else { - def->cont2 = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_EMPTY); - def->content = xmlRelaxNGNewDefine(ctxt, node, - XML_RELAXNG_ONEORMORE); - if (def->content != NULL) { - def->content->content = - xmlRelaxNGParsePatterns(ctxt, node->children, 1); - } + def->content = xmlRelaxNGParsePatterns(ctxt, node->children, 1); } } else if (IS_RELAXNG(node, "oneOrMore")) { - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_ONEORMORE); + def = xmlRelaxNGNewDefine(ctxt, node); if (def == NULL) return(NULL); + def->type = XML_RELAXNG_ONEORMORE; if (node->children == NULL) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, @@ -3155,63 +3602,49 @@ xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { def->content = xmlRelaxNGParsePatterns(ctxt, node->children, 1); } } else if (IS_RELAXNG(node, "optional")) { - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_CHOICE); + def = xmlRelaxNGNewDefine(ctxt, node); if (def == NULL) return(NULL); + def->type = XML_RELAXNG_OPTIONAL; if (node->children == NULL) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, "Element %s is empty\n", node->name); ctxt->nbErrors++; } else { - def->cont2 = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_EMPTY); def->content = xmlRelaxNGParsePatterns(ctxt, node->children, 1); } } else if (IS_RELAXNG(node, "choice")) { + def = xmlRelaxNGNewDefine(ctxt, node); + if (def == NULL) + return(NULL); + def->type = XML_RELAXNG_CHOICE; if (node->children == NULL) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, "Element %s is empty\n", node->name); ctxt->nbErrors++; - } else if (node->children->next == NULL) { - def = xmlRelaxNGParsePattern(ctxt, node->children); } else { - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_CHOICE); - if (def == NULL) - return(NULL); - def->content = xmlRelaxNGParsePattern(ctxt, node->children); - def->cont2 = xmlRelaxNGParsePattern(ctxt, node->children->next); + def->content = xmlRelaxNGParsePatterns(ctxt, node->children, 0); } - } else if (IS_RELAXNG(node, "interleave")) { - if (node->children == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Element %s is empty\n", node->name); - ctxt->nbErrors++; - } else if (node->children->next == NULL) { - def = xmlRelaxNGParsePattern(ctxt, node->children); - } else { - def = xmlRelaxNGParseInterleave(ctxt, node); - } } else if (IS_RELAXNG(node, "group")) { + def = xmlRelaxNGNewDefine(ctxt, node); + if (def == NULL) + return(NULL); + def->type = XML_RELAXNG_GROUP; if (node->children == NULL) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, "Element %s is empty\n", node->name); ctxt->nbErrors++; - } else if (node->children->next == NULL) { - def = xmlRelaxNGParsePattern(ctxt, node->children); } else { - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_GROUP); - if (def == NULL) - return(NULL); - def->content = xmlRelaxNGParsePattern(ctxt, node->children); - def->cont2 = xmlRelaxNGParsePattern(ctxt, node->children->next); + def->content = xmlRelaxNGParsePatterns(ctxt, node->children, 0); } } else if (IS_RELAXNG(node, "ref")) { - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_REF); + def = xmlRelaxNGNewDefine(ctxt, node); if (def == NULL) return(NULL); + def->type = XML_RELAXNG_REF; def->name = xmlGetProp(node, BAD_CAST "name"); if (def->name == NULL) { if (ctxt->error != NULL) @@ -3275,9 +3708,10 @@ xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { } else if (IS_RELAXNG(node, "value")) { def = xmlRelaxNGParseValue(ctxt, node); } else if (IS_RELAXNG(node, "list")) { - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_LIST); + def = xmlRelaxNGNewDefine(ctxt, node); if (def == NULL) return(NULL); + def->type = XML_RELAXNG_LIST; if (node->children == NULL) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, @@ -3286,12 +3720,15 @@ xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { } else { def->content = xmlRelaxNGParsePatterns(ctxt, node->children, 0); } + } else if (IS_RELAXNG(node, "interleave")) { + def = xmlRelaxNGParseInterleave(ctxt, node); } else if (IS_RELAXNG(node, "externalRef")) { def = xmlRelaxNGProcessExternalRef(ctxt, node); } else if (IS_RELAXNG(node, "notAllowed")) { - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_NOT_ALLOWED); + def = xmlRelaxNGNewDefine(ctxt, node); if (def == NULL) return(NULL); + def->type = XML_RELAXNG_NOT_ALLOWED; if (node->children != NULL) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, @@ -3332,9 +3769,10 @@ xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { ctxt->nbErrors++; return(NULL); } - def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_PARENTREF); + def = xmlRelaxNGNewDefine(ctxt, node); if (def == NULL) return(NULL); + def->type = XML_RELAXNG_PARENTREF; def->name = xmlGetProp(node, BAD_CAST "name"); if (def->name == NULL) { if (ctxt->error != NULL) @@ -3388,8 +3826,34 @@ xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { } } } else if (IS_RELAXNG(node, "mixed")) { - /* we should not go there unless an error happened */ - def = NULL; + if (node->children == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Mixed is empty\n"); + ctxt->nbErrors++; + def = NULL; + } else { + def = xmlRelaxNGParseInterleave(ctxt, node); + if (def != NULL) { + xmlRelaxNGDefinePtr tmp; + + if ((def->content != NULL) && (def->content->next != NULL)) { + tmp = xmlRelaxNGNewDefine(ctxt, node); + if (tmp != NULL) { + tmp->type = XML_RELAXNG_GROUP; + tmp->content = def->content; + def->content = tmp; + } + } + + tmp = xmlRelaxNGNewDefine(ctxt, node); + if (tmp == NULL) + return(def); + tmp->type = XML_RELAXNG_TEXT; + tmp->next = def->content; + def->content = tmp; + } + } } else { if (ctxt->error != NULL) ctxt->error(ctxt->userData, @@ -3416,9 +3880,10 @@ xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { xmlNodePtr child; int old_flags; - ret = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_ATTRIBUTE); + ret = xmlRelaxNGNewDefine(ctxt, node); if (ret == NULL) return(NULL); + ret->type = XML_RELAXNG_ATTRIBUTE; ret->parent = ctxt->def; child = node->children; if (child == NULL) { @@ -3450,6 +3915,8 @@ xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { case XML_RELAXNG_EXTERNALREF: case XML_RELAXNG_DEF: case XML_RELAXNG_ONEORMORE: + case XML_RELAXNG_ZEROORMORE: + case XML_RELAXNG_OPTIONAL: case XML_RELAXNG_CHOICE: case XML_RELAXNG_GROUP: case XML_RELAXNG_INTERLEAVE: @@ -3465,7 +3932,6 @@ xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { "attribute has invalid content\n"); ctxt->nbErrors++; break; -#if 0 case XML_RELAXNG_NOOP: TODO if (ctxt->error != NULL) @@ -3473,14 +3939,6 @@ xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { "Internal error, noop found\n"); ctxt->nbErrors++; break; -#endif - case XML_RELAXNG_AFTER: - TODO - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Internal error, after found\n"); - ctxt->nbErrors++; - break; } } child = child->next; @@ -3531,16 +3989,19 @@ xmlRelaxNGParseExceptNameClass(xmlRelaxNGParserCtxtPtr ctxt, return(NULL); } - ret = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_EXCEPT); + ret = xmlRelaxNGNewDefine(ctxt, node); if (ret == NULL) return(NULL); + ret->type = XML_RELAXNG_EXCEPT; child = node->children; while (child != NULL) { - cur = xmlRelaxNGNewDefine(ctxt, child, XML_RELAXNG_ELEMENT); + cur = xmlRelaxNGNewDefine(ctxt, child); if (cur == NULL) break; if (attr) cur->type = XML_RELAXNG_ATTRIBUTE; + else + cur->type = XML_RELAXNG_ELEMENT; if (xmlRelaxNGParseNameClass(ctxt, child, cur) != NULL) { if (last == NULL) { @@ -3569,7 +4030,7 @@ xmlRelaxNGParseExceptNameClass(xmlRelaxNGParserCtxtPtr ctxt, static xmlRelaxNGDefinePtr xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, xmlRelaxNGDefinePtr def) { - xmlRelaxNGDefinePtr ret; + xmlRelaxNGDefinePtr ret, tmp; xmlChar *val; ret = def; @@ -3577,12 +4038,14 @@ xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, (IS_RELAXNG(node, "nsName"))) { if ((def->type != XML_RELAXNG_ELEMENT) && (def->type != XML_RELAXNG_ATTRIBUTE)) { - ret = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_ELEMENT); + ret = xmlRelaxNGNewDefine(ctxt, node); if (ret == NULL) return(NULL); ret->parent = def; if (ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) ret->type = XML_RELAXNG_ATTRIBUTE; + else + ret->type = XML_RELAXNG_ELEMENT; } } if (IS_RELAXNG(node, "name")) { @@ -3652,31 +4115,44 @@ xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, (def->type == XML_RELAXNG_ATTRIBUTE)); } } else if (IS_RELAXNG(node, "choice")) { + xmlNodePtr child; + xmlRelaxNGDefinePtr last = NULL; + + ret = xmlRelaxNGNewDefine(ctxt, node); + if (ret == NULL) + return(NULL); + ret->parent = def; + ret->type = XML_RELAXNG_CHOICE; + if (node->children == NULL) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, "Element choice is empty\n"); ctxt->nbErrors++; - } else if (node->children->next == NULL) { - ret = xmlRelaxNGParseNameClass(ctxt, node->children, def); - def->nameClass = ret; } else { - ret = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_CHOICE); - if (ret == NULL) - return(NULL); - ret->content = xmlRelaxNGParseNameClass(ctxt, node->children, ret); - ret->cont2 = xmlRelaxNGParseNameClass(ctxt, node->children->next, ret); - def->nameClass = ret; + + child = node->children; + while (child != NULL) { + tmp = xmlRelaxNGParseNameClass(ctxt, child, ret); + if (tmp != NULL) { + if (last == NULL) { + last = ret->nameClass = tmp; + } else { + last->next = tmp; + last = tmp; + } + } + child = child->next; + } } } else { if (ctxt->error != NULL) ctxt->error(ctxt->userData, - "expecting name, anyName, nsName or choice : got %s\n", + "expecting name, anyName, nsName or choice : got %s\n", node->name); ctxt->nbErrors++; return(NULL); } -#if 0 if (ret != def) { if (def->nameClass == NULL) { def->nameClass = ret; @@ -3688,7 +4164,6 @@ xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, tmp->next = ret; } } -#endif return(ret); } @@ -3707,9 +4182,10 @@ xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { xmlNodePtr child; const xmlChar *olddefine; - ret = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_ELEMENT); + ret = xmlRelaxNGNewDefine(ctxt, node); if (ret == NULL) return(NULL); + ret->type = XML_RELAXNG_ELEMENT; ret->parent = ctxt->def; child = node->children; if (child == NULL) { @@ -3749,19 +4225,20 @@ xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { case XML_RELAXNG_PARENTREF: case XML_RELAXNG_EXTERNALREF: case XML_RELAXNG_DEF: + case XML_RELAXNG_ZEROORMORE: case XML_RELAXNG_ONEORMORE: + case XML_RELAXNG_OPTIONAL: case XML_RELAXNG_CHOICE: case XML_RELAXNG_GROUP: - case XML_RELAXNG_ATTRIBUTE: case XML_RELAXNG_INTERLEAVE: if (last == NULL) { ret->content = last = cur; } else { if ((last->type == XML_RELAXNG_ELEMENT) && (ret->content == last)) { - ret->content = xmlRelaxNGNewDefine(ctxt, node, - XML_RELAXNG_GROUP); + ret->content = xmlRelaxNGNewDefine(ctxt, node); if (ret->content != NULL) { + ret->content->type = XML_RELAXNG_GROUP; ret->content->content = last; } else { ret->content = last; @@ -3771,14 +4248,16 @@ xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { last = cur; } break; + case XML_RELAXNG_ATTRIBUTE: + cur->next = ret->attrs; + ret->attrs = cur; + break; case XML_RELAXNG_START: case XML_RELAXNG_PARAM: case XML_RELAXNG_EXCEPT: - case XML_RELAXNG_AFTER: TODO ctxt->nbErrors++; break; -#if 0 case XML_RELAXNG_NOOP: TODO if (ctxt->error != NULL) @@ -3786,7 +4265,6 @@ xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { "Internal error, noop found\n"); ctxt->nbErrors++; break; -#endif } } child = child->next; @@ -3819,7 +4297,8 @@ xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes, } else { if ((group == 1) && (def->type == XML_RELAXNG_ELEMENT) && (def == last)) { - def = xmlRelaxNGNewDefine(ctxt, nodes, XML_RELAXNG_GROUP); + def = xmlRelaxNGNewDefine(ctxt, nodes); + def->type = XML_RELAXNG_GROUP; def->content = last; } last->next = cur; @@ -3864,18 +4343,20 @@ xmlRelaxNGParseStart(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes) { return(-1); } if (IS_RELAXNG(nodes, "empty")) { - def = xmlRelaxNGNewDefine(ctxt, nodes, XML_RELAXNG_EMPTY); + def = xmlRelaxNGNewDefine(ctxt, nodes); if (def == NULL) return(-1); + def->type = XML_RELAXNG_EMPTY; if (nodes->children != NULL) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, "element empty is not empty\n"); ctxt->nbErrors++; } } else if (IS_RELAXNG(nodes, "notAllowed")) { - def = xmlRelaxNGNewDefine(ctxt, nodes, XML_RELAXNG_NOT_ALLOWED); + def = xmlRelaxNGNewDefine(ctxt, nodes); if (def == NULL) return(-1); + def->type = XML_RELAXNG_NOT_ALLOWED; if (nodes->children != NULL) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, @@ -4088,11 +4569,13 @@ xmlRelaxNGCheckCombine(xmlRelaxNGDefinePtr define, #endif if (choiceOrInterleave == -1) choiceOrInterleave = 0; - cur = xmlRelaxNGNewDefine(ctxt, define->node, XML_RELAXNG_CHOICE); + cur = xmlRelaxNGNewDefine(ctxt, define->node); if (cur == NULL) return; if (choiceOrInterleave == 0) cur->type = XML_RELAXNG_INTERLEAVE; + else + cur->type = XML_RELAXNG_CHOICE; tmp = define; last = NULL; while (tmp != NULL) { @@ -4101,10 +4584,10 @@ xmlRelaxNGCheckCombine(xmlRelaxNGDefinePtr define, /* * we need first to create a wrapper. */ - tmp2 = xmlRelaxNGNewDefine(ctxt, tmp->content->node, - XML_RELAXNG_GROUP); + tmp2 = xmlRelaxNGNewDefine(ctxt, tmp->content->node); if (tmp2 == NULL) break; + tmp2->type = XML_RELAXNG_GROUP; tmp2->content = tmp->content; } else { tmp2 = tmp->content; @@ -4120,6 +4603,26 @@ xmlRelaxNGCheckCombine(xmlRelaxNGDefinePtr define, tmp = tmp->nextHash; } define->content = cur; + if (choiceOrInterleave == 0) { + if (ctxt->interleaves == NULL) + ctxt->interleaves = xmlHashCreate(10); + if (ctxt->interleaves == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Failed to create interleaves hash table\n"); + ctxt->nbErrors++; + } else { + char tmpname[32]; + + snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++); + if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) < 0) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Failed to add %s to hash table\n", tmpname); + ctxt->nbErrors++; + } + } + } } /** @@ -4201,13 +4704,35 @@ xmlRelaxNGCombineStart(xmlRelaxNGParserCtxtPtr ctxt, #endif if (choiceOrInterleave == -1) choiceOrInterleave = 0; - cur = xmlRelaxNGNewDefine(ctxt, starts->node, XML_RELAXNG_CHOICE); + cur = xmlRelaxNGNewDefine(ctxt, starts->node); if (cur == NULL) return; if (choiceOrInterleave == 0) cur->type = XML_RELAXNG_INTERLEAVE; + else + cur->type = XML_RELAXNG_CHOICE; cur->content = grammar->start; grammar->start = cur; + if (choiceOrInterleave == 0) { + if (ctxt->interleaves == NULL) + ctxt->interleaves = xmlHashCreate(10); + if (ctxt->interleaves == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Failed to create interleaves hash table\n"); + ctxt->nbErrors++; + } else { + char tmpname[32]; + + snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++); + if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) < 0) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Failed to add %s to hash table\n", tmpname); + ctxt->nbErrors++; + } + } + } } /** @@ -4242,17 +4767,13 @@ xmlRelaxNGCheckCycles(xmlRelaxNGParserCtxtPtr ctxt, } else if (cur->type == XML_RELAXNG_ELEMENT) { ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth + 1); } else { - if (cur->content != NULL) - ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth); - if ((cur->cont2 != NULL) && (ret == 0)) - ret = xmlRelaxNGCheckCycles(ctxt, cur->cont2, depth); + ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth); } cur = cur->next; } return(ret); } -#if 0 /** * xmlRelaxNGTryUnlink: * @ctxt: a Relax-NG parser context @@ -4269,8 +4790,23 @@ xmlRelaxNGTryUnlink(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED, xmlRelaxNGDefinePtr cur, xmlRelaxNGDefinePtr parent, xmlRelaxNGDefinePtr prev) { + if (prev != NULL) { + prev->next = cur->next; + } else { + if (parent != NULL) { + if (parent->content == cur) + parent->content = cur->next; + else if (parent->attrs == cur) + parent->attrs = cur->next; + else if (parent->nameClass == cur) + parent->nameClass = cur->next; + } else { + cur->type = XML_RELAXNG_NOOP; + prev = cur; + } + } + return(prev); } -#endif /** * xmlRelaxNGSimplify: @@ -4283,211 +4819,117 @@ static void xmlRelaxNGSimplify(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr cur, xmlRelaxNGDefinePtr parent) { - if ((cur == NULL) || (ctxt->nbErrors != 0)) - return; - cur->parent = parent; - if ((cur->type == XML_RELAXNG_REF) || - (cur->type == XML_RELAXNG_PARENTREF)) { - if (cur->depth != -3) { - cur->depth = -3; - xmlRelaxNGSimplify(ctxt, cur->content, cur); - } - } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) { - if ((parent != NULL) && - ((parent->type == XML_RELAXNG_ATTRIBUTE) || - (parent->type == XML_RELAXNG_LIST) || - (parent->type == XML_RELAXNG_GROUP) || - (parent->type == XML_RELAXNG_INTERLEAVE) || - (parent->type == XML_RELAXNG_ONEORMORE))) { - parent->type = XML_RELAXNG_NOT_ALLOWED; - } - } else if (cur->type == XML_RELAXNG_EMPTY){ - cur->parent = parent; - if ((parent != NULL) && - (parent->type == XML_RELAXNG_ONEORMORE)) { - parent->type = XML_RELAXNG_EMPTY; - } - } else if ((cur->type == XML_RELAXNG_GROUP) || - (cur->type == XML_RELAXNG_CHOICE) || - (cur->type == XML_RELAXNG_INTERLEAVE)) { - cur->parent = parent; - if ((cur->cont2 != NULL) && (cur->content == NULL)) { - cur->content = cur->cont2; - cur->cont2 = NULL; - } - - if ((cur->cont2 == NULL) && (cur->content != NULL) && - (cur->content->next != NULL)) { - xmlRelaxNGDefinePtr c, n, tmp; - - c = cur; - n = cur->content; - while (n->next != NULL) { - tmp = n->next; - - n->next = NULL; - n->parent = c; - c->content = n; - - n = tmp; - if (n->next != NULL) { - tmp = xmlRelaxNGNewDefine(ctxt, cur->node, cur->type); - if (tmp != NULL) { - c->cont2 = tmp; - tmp->parent = c; - c = tmp; - c->content = n; - } else { - c->cont2 = tmp; - } - } else { - c->cont2 = n; - n->parent = c; - } - } - } - - if (cur->content != NULL) - xmlRelaxNGSimplify(ctxt, cur->content, cur); - if (cur->cont2 != NULL) - xmlRelaxNGSimplify(ctxt, cur->cont2, cur); - - if ((cur->cont2 != NULL) && (cur->content == NULL)) { - cur->content = cur->cont2; - cur->cont2 = NULL; - } - if ((cur->content == NULL) && (cur->cont2 == NULL)) { - cur->type = XML_RELAXNG_EMPTY; - } else if (cur->cont2 == NULL) { - xmlRelaxNGDefinePtr tmp = cur->content; + xmlRelaxNGDefinePtr prev = NULL; - memcpy(cur, cur->content, sizeof(xmlRelaxNGDefine)); - memset(tmp, 0, sizeof(xmlRelaxNGDefine)); - } else if ((cur->type == XML_RELAXNG_GROUP) || - (cur->type == XML_RELAXNG_INTERLEAVE)) { - if ((cur->content != NULL) && - (cur->content->type == XML_RELAXNG_EMPTY)) { - xmlRelaxNGDefinePtr tmp = cur->cont2; - - memcpy(cur, cur->cont2, sizeof(xmlRelaxNGDefine)); - memset(tmp, 0, sizeof(xmlRelaxNGDefine)); - } else if ((cur->cont2 != NULL) && - (cur->cont2->type == XML_RELAXNG_EMPTY)) { - xmlRelaxNGDefinePtr tmp = cur->content; - - memcpy(cur, cur->content, sizeof(xmlRelaxNGDefine)); - memset(tmp, 0, sizeof(xmlRelaxNGDefine)); - } else if ((cur->content != NULL) && - (cur->content->type == XML_RELAXNG_NOT_ALLOWED)) { - cur->type = XML_RELAXNG_NOT_ALLOWED; - } else if ((cur->cont2 != NULL) && - (cur->cont2->type == XML_RELAXNG_NOT_ALLOWED)) { - cur->type = XML_RELAXNG_NOT_ALLOWED; - } - } else if (cur->type == XML_RELAXNG_CHOICE) { - if ((cur->content != NULL) && - (cur->content->type == XML_RELAXNG_NOT_ALLOWED)) { - xmlRelaxNGDefinePtr tmp = cur->cont2; - - memcpy(cur, cur->cont2, sizeof(xmlRelaxNGDefine)); - memset(tmp, 0, sizeof(xmlRelaxNGDefine)); - } else if ((cur->cont2 != NULL) && - (cur->cont2->type == XML_RELAXNG_NOT_ALLOWED)) { - xmlRelaxNGDefinePtr tmp = cur->content; - - memcpy(cur, cur->content, sizeof(xmlRelaxNGDefine)); - memset(tmp, 0, sizeof(xmlRelaxNGDefine)); + while (cur != NULL) { + if ((cur->type == XML_RELAXNG_REF) || + (cur->type == XML_RELAXNG_PARENTREF)) { + if (cur->depth != -3) { + cur->depth = -3; + xmlRelaxNGSimplify(ctxt, cur->content, cur); } - } - } else { - cur->parent = parent; - if (cur->content != NULL) - xmlRelaxNGSimplify(ctxt, cur->content, cur); - if (cur->cont2 != NULL) - xmlRelaxNGSimplify(ctxt, cur->cont2, cur); - if (cur->nameClass != NULL) - xmlRelaxNGSimplify(ctxt, cur->nameClass, cur); - /* - * the current node may have been transformed back - */ - if ((cur->type == XML_RELAXNG_EXCEPT) && - (cur->content != NULL) && - (cur->content->type == XML_RELAXNG_NOT_ALLOWED)) { - TODO } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) { + cur->parent = parent; if ((parent != NULL) && ((parent->type == XML_RELAXNG_ATTRIBUTE) || (parent->type == XML_RELAXNG_LIST) || (parent->type == XML_RELAXNG_GROUP) || (parent->type == XML_RELAXNG_INTERLEAVE) || - (parent->type == XML_RELAXNG_ONEORMORE))) { + (parent->type == XML_RELAXNG_ONEORMORE) || + (parent->type == XML_RELAXNG_ZEROORMORE))) { parent->type = XML_RELAXNG_NOT_ALLOWED; + break; } + if ((parent != NULL) && + (parent->type == XML_RELAXNG_CHOICE)) { + prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev); + } else + prev = cur; } else if (cur->type == XML_RELAXNG_EMPTY){ + cur->parent = parent; if ((parent != NULL) && - (parent->type == XML_RELAXNG_ONEORMORE)) { + ((parent->type == XML_RELAXNG_ONEORMORE) || + (parent->type == XML_RELAXNG_ZEROORMORE))) { parent->type = XML_RELAXNG_EMPTY; + break; } - } - } -} - -/** - * xmlRelaxNGSimplifyRefs: - * @ctxt: a Relax-NG parser context - * @cur: the current define children nodes - * - * Check for the elimination of the DEF/REF references - */ -static void -xmlRelaxNGSimplifyRefs(xmlRelaxNGParserCtxtPtr ctxt, - xmlRelaxNGDefinePtr cur) { - if ((cur == NULL) || (ctxt->nbErrors != 0)) - return; - if ((cur->content != NULL) && - ((cur->content->type == XML_RELAXNG_REF) || - (cur->content->type == XML_RELAXNG_PARENTREF))) { - if ((cur->content->content != NULL) && - (cur->content->content->type == XML_RELAXNG_DEF) && - (cur->content->content->content != NULL)) - cur->content = cur->content->content->content; - else { - if (ctxt->error != NULL) { - if (cur->content->name != NULL) { - ctxt->error(ctxt->userData, - "No target in %s reference\n", cur->content->name); - } else { - ctxt->error(ctxt->userData, - "No target in reference\n"); + if ((parent != NULL) && + ((parent->type == XML_RELAXNG_GROUP) || + (parent->type == XML_RELAXNG_INTERLEAVE))) { + prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev); + } else + prev = cur; + } else { + cur->parent = parent; + if (cur->content != NULL) + xmlRelaxNGSimplify(ctxt, cur->content, cur); + if (cur->attrs != NULL) + xmlRelaxNGSimplify(ctxt, cur->attrs, cur); + if (cur->nameClass != NULL) + xmlRelaxNGSimplify(ctxt, cur->nameClass, cur); + /* + * This may result in a simplification + */ + if ((cur->type == XML_RELAXNG_GROUP) || + (cur->type == XML_RELAXNG_INTERLEAVE)) { + if (cur->content == NULL) + cur->type = XML_RELAXNG_EMPTY; + else if (cur->content->next == NULL) { + if ((parent == NULL) && (prev == NULL)) { + cur->type = XML_RELAXNG_NOOP; + } else if (prev == NULL) { + parent->content = cur->content; + cur->content->next = cur->next; + cur = cur->content; + } else { + cur->content->next = cur->next; + prev->next = cur->content; + cur = cur->content; + } } } - ctxt->nbErrors++; - } - } - if ((cur->cont2 != NULL) && - ((cur->cont2->type == XML_RELAXNG_REF) || - (cur->cont2->type == XML_RELAXNG_PARENTREF))) { - if ((cur->cont2->content != NULL) && - (cur->cont2->content->type == XML_RELAXNG_DEF) && - (cur->cont2->content->content != NULL)) - cur->cont2 = cur->cont2->content->content; - else { - if (ctxt->error != NULL) { - if (cur->cont2->name != NULL) { - ctxt->error(ctxt->userData, - "No target in %s reference\n", cur->cont2->name); - } else { - ctxt->error(ctxt->userData, - "No target in reference\n"); + /* + * the current node may have been transformed back + */ + if ((cur->type == XML_RELAXNG_EXCEPT) && + (cur->content != NULL) && + (cur->content->type == XML_RELAXNG_NOT_ALLOWED)) { + prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev); + } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) { + if ((parent != NULL) && + ((parent->type == XML_RELAXNG_ATTRIBUTE) || + (parent->type == XML_RELAXNG_LIST) || + (parent->type == XML_RELAXNG_GROUP) || + (parent->type == XML_RELAXNG_INTERLEAVE) || + (parent->type == XML_RELAXNG_ONEORMORE) || + (parent->type == XML_RELAXNG_ZEROORMORE))) { + parent->type = XML_RELAXNG_NOT_ALLOWED; + break; } + if ((parent != NULL) && + (parent->type == XML_RELAXNG_CHOICE)) { + prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev); + } else + prev = cur; + } else if (cur->type == XML_RELAXNG_EMPTY){ + if ((parent != NULL) && + ((parent->type == XML_RELAXNG_ONEORMORE) || + (parent->type == XML_RELAXNG_ZEROORMORE))) { + parent->type = XML_RELAXNG_EMPTY; + break; + } + if ((parent != NULL) && + ((parent->type == XML_RELAXNG_GROUP) || + (parent->type == XML_RELAXNG_INTERLEAVE) || + (parent->type == XML_RELAXNG_CHOICE))) { + prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev); + } else + prev = cur; + } else { + prev = cur; } - ctxt->nbErrors++; } - } - if (cur->depth != -4) { - cur->depth = -4; - if (cur->content != NULL) xmlRelaxNGSimplifyRefs(ctxt, cur->content); - if (cur->cont2 != NULL) xmlRelaxNGSimplifyRefs(ctxt, cur->cont2); + cur = cur->next; } } @@ -4545,127 +4987,134 @@ xmlRelaxNGMaxContentType(xmlRelaxNGContentType ct1, * @ctxt: a Relax-NG parser context * @cur: the current definition * @flags: some accumulated flags + * @ptype: the parent type * * Check for rules in section 7.1 and 7.2 * * Returns the content type of @cur */ static xmlRelaxNGContentType -xmlRelaxNGCheckRules(xmlRelaxNGParserCtxtPtr ctxt, - xmlRelaxNGDefinePtr cur, int flags) -{ +xmlRelaxNGCheckRules(xmlRelaxNGParserCtxtPtr ctxt, + xmlRelaxNGDefinePtr cur, int flags, + xmlRelaxNGType ptype) { int nflags = flags; - xmlRelaxNGContentType ret, tmp; + xmlRelaxNGContentType ret, tmp, val = XML_RELAXNG_CONTENT_EMPTY; - ret = XML_RELAXNG_CONTENT_EMPTY; - if (cur == NULL) - return (ret); - switch (cur->type) { - case XML_RELAXNG_REF: - case XML_RELAXNG_PARENTREF: - if (flags & XML_RELAXNG_IN_LIST) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern list//ref\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_DATAEXCEPT) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern data/except//ref\n"); - ctxt->nbErrors++; - } - if (cur->depth > -4) { - cur->depth = -4; - ret = xmlRelaxNGCheckRules(ctxt, cur->content, flags); - cur->depth = ret - 15; - } else if (cur->depth == -4) { - ret = XML_RELAXNG_CONTENT_COMPLEX; - } else { - ret = (xmlRelaxNGContentType) cur->depth + 15; - } - break; - case XML_RELAXNG_ELEMENT: - /* - * The 7.3 Attribute derivation rule for groups is plugged there - */ - if (flags & XML_RELAXNG_IN_DATAEXCEPT) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern data/except//element(ref)\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_LIST) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern list//element(ref)\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_ATTRIBUTE) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern attribute//element(ref)\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_ATTRIBUTE) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, + while (cur != NULL) { + ret = XML_RELAXNG_CONTENT_EMPTY; + if ((cur->type == XML_RELAXNG_REF) || + (cur->type == XML_RELAXNG_PARENTREF)) { + if (flags & XML_RELAXNG_IN_LIST) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern list//ref\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_DATAEXCEPT) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern data/except//ref\n"); + ctxt->nbErrors++; + } + if (cur->depth > -4) { + cur->depth = -4; + ret = xmlRelaxNGCheckRules(ctxt, cur->content, + flags, cur->type); + cur->depth = ret - 15 ; + } else if (cur->depth == -4) { + ret = XML_RELAXNG_CONTENT_COMPLEX; + } else { + ret = (xmlRelaxNGContentType) cur->depth + 15; + } + } else if (cur->type == XML_RELAXNG_ELEMENT) { + /* + * The 7.3 Attribute derivation rule for groups is plugged there + */ + xmlRelaxNGCheckGroupAttrs(ctxt, cur); + if (flags & XML_RELAXNG_IN_DATAEXCEPT) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern data/except//element(ref)\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_LIST) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern list//element(ref)\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_ATTRIBUTE) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern attribute//element(ref)\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_ATTRIBUTE) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, "Found forbidden pattern attribute//element(ref)\n"); - ctxt->nbErrors++; - } - /* - * reset since in the simple form elements are only child - * of grammar/define - */ - nflags = 0; - ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags); - if (ret == XML_RELAXNG_CONTENT_ERROR) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Element %s has a content type error\n", - cur->name); - ctxt->nbErrors++; - } else { - ret = XML_RELAXNG_CONTENT_COMPLEX; - } - break; - case XML_RELAXNG_ATTRIBUTE: - if (flags & XML_RELAXNG_IN_ATTRIBUTE) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern attribute//attribute\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_LIST) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern list//attribute\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_OOMGROUP) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, + ctxt->nbErrors++; + } + /* + * reset since in the simple form elements are only child + * of grammar/define + */ + nflags = 0; + ret = xmlRelaxNGCheckRules(ctxt, cur->attrs, nflags, cur->type); + if (ret != XML_RELAXNG_CONTENT_EMPTY) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Element %s attributes have a content type error\n", + cur->name); + ctxt->nbErrors++; + } + ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type); + if (ret == XML_RELAXNG_CONTENT_ERROR) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Element %s has a content type error\n", + cur->name); + ctxt->nbErrors++; + } else { + ret = XML_RELAXNG_CONTENT_COMPLEX; + } + } else if (cur->type == XML_RELAXNG_ATTRIBUTE) { + if (flags & XML_RELAXNG_IN_ATTRIBUTE) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern attribute//attribute\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_LIST) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern list//attribute\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_OOMGROUP) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, "Found forbidden pattern oneOrMore//group//attribute\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_OOMINTERLEAVE) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_OOMINTERLEAVE) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, "Found forbidden pattern oneOrMore//interleave//attribute\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_DATAEXCEPT) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_DATAEXCEPT) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, "Found forbidden pattern data/except//attribute\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_START) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern start//attribute\n"); - ctxt->nbErrors++; - } + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_START) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern start//attribute\n"); + ctxt->nbErrors++; + } if ((!(flags & XML_RELAXNG_IN_ONEORMORE)) && (cur->name == NULL)) { if (cur->ns == NULL) { if (ctxt->error != NULL) @@ -4679,196 +5128,180 @@ xmlRelaxNGCheckRules(xmlRelaxNGParserCtxtPtr ctxt, ctxt->nbErrors++; } } - nflags = flags | XML_RELAXNG_IN_ATTRIBUTE; - xmlRelaxNGCheckRules(ctxt, cur->content, nflags); - ret = XML_RELAXNG_CONTENT_EMPTY; - break; - case XML_RELAXNG_ONEORMORE: - if (flags & XML_RELAXNG_IN_DATAEXCEPT) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, + nflags = flags | XML_RELAXNG_IN_ATTRIBUTE; + xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type); + ret = XML_RELAXNG_CONTENT_EMPTY; + } else if ((cur->type == XML_RELAXNG_ONEORMORE) || + (cur->type == XML_RELAXNG_ZEROORMORE)) { + if (flags & XML_RELAXNG_IN_DATAEXCEPT) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, "Found forbidden pattern data/except//oneOrMore\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_START) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern start//oneOrMore\n"); - ctxt->nbErrors++; - } - nflags = flags | XML_RELAXNG_IN_ONEORMORE; - ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags); - ret = xmlRelaxNGGroupContentType(ret, ret); - break; - case XML_RELAXNG_LIST: - if (flags & XML_RELAXNG_IN_LIST) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern list//list\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_DATAEXCEPT) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern data/except//list\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_START) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern start//list\n"); - ctxt->nbErrors++; - } - nflags = flags | XML_RELAXNG_IN_LIST; - xmlRelaxNGCheckRules(ctxt, cur->content, nflags); - ret = XML_RELAXNG_CONTENT_SIMPLE; - break; - case XML_RELAXNG_GROUP: - if (flags & XML_RELAXNG_IN_DATAEXCEPT) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern data/except//group\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_START) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern start//group\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_ONEORMORE) - nflags = flags | XML_RELAXNG_IN_OOMGROUP; - else - nflags = flags; - ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags); - tmp = xmlRelaxNGCheckRules(ctxt, cur->cont2, nflags); - ret = xmlRelaxNGGroupContentType(ret, tmp); - /* - * The 7.3 Attribute derivation rule for groups is plugged there - */ - xmlRelaxNGCheckGroupAttrs(ctxt, cur); - break; - case XML_RELAXNG_INTERLEAVE: - if (flags & XML_RELAXNG_IN_LIST) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern list//interleave\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_DATAEXCEPT) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_START) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern start//oneOrMore\n"); + ctxt->nbErrors++; + } + nflags = flags | XML_RELAXNG_IN_ONEORMORE; + ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type); + ret = xmlRelaxNGGroupContentType(ret, ret); + } else if (cur->type == XML_RELAXNG_LIST) { + if (flags & XML_RELAXNG_IN_LIST) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern list//list\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_DATAEXCEPT) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern data/except//list\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_START) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern start//list\n"); + ctxt->nbErrors++; + } + nflags = flags | XML_RELAXNG_IN_LIST; + ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type); + } else if (cur->type == XML_RELAXNG_GROUP) { + if (flags & XML_RELAXNG_IN_DATAEXCEPT) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern data/except//group\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_START) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern start//group\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_ONEORMORE) + nflags = flags | XML_RELAXNG_IN_OOMGROUP; + else + nflags = flags; + ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type); + /* + * The 7.3 Attribute derivation rule for groups is plugged there + */ + xmlRelaxNGCheckGroupAttrs(ctxt, cur); + } else if (cur->type == XML_RELAXNG_INTERLEAVE) { + if (flags & XML_RELAXNG_IN_LIST) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern list//interleave\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_DATAEXCEPT) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, "Found forbidden pattern data/except//interleave\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_START) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern start//interleave\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_ONEORMORE) - nflags = flags | XML_RELAXNG_IN_OOMINTERLEAVE; - else - nflags = flags; - ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags); - tmp = xmlRelaxNGCheckRules(ctxt, cur->cont2, nflags); - ret = xmlRelaxNGMaxContentType(tmp, ret); - /* - * The 7.3 Attribute derivation rule for groups is plugged there - */ - xmlRelaxNGCheckGroupAttrs(ctxt, cur); - xmlRelaxNGCheckInterleave(ctxt, cur); - break; - case XML_RELAXNG_EXCEPT: - if ((cur->parent != NULL) && - (cur->parent->type == XML_RELAXNG_DATATYPE)) - nflags = flags | XML_RELAXNG_IN_DATAEXCEPT; - else - nflags = flags; - ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags); - break; - case XML_RELAXNG_DATATYPE: - if (flags & XML_RELAXNG_IN_START) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern start//data\n"); - ctxt->nbErrors++; - } - xmlRelaxNGCheckRules(ctxt, cur->content, flags); - ret = XML_RELAXNG_CONTENT_SIMPLE; - break; - case XML_RELAXNG_VALUE: - if (flags & XML_RELAXNG_IN_START) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern start//value\n"); - ctxt->nbErrors++; - } - xmlRelaxNGCheckRules(ctxt, cur->content, flags); - ret = XML_RELAXNG_CONTENT_SIMPLE; - break; - case XML_RELAXNG_TEXT: - if (flags & XML_RELAXNG_IN_LIST) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern list//text\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_DATAEXCEPT) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern data/except//text\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_START) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern start//text\n"); - ctxt->nbErrors++; - } - ret = XML_RELAXNG_CONTENT_COMPLEX; - break; - case XML_RELAXNG_EMPTY: - if (flags & XML_RELAXNG_IN_DATAEXCEPT) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern data/except//empty\n"); - ctxt->nbErrors++; - } - if (flags & XML_RELAXNG_IN_START) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found forbidden pattern start//empty\n"); - ctxt->nbErrors++; - } - ret = XML_RELAXNG_CONTENT_EMPTY; - break; - case XML_RELAXNG_CHOICE: - ret = xmlRelaxNGCheckRules(ctxt, cur->content, flags); - tmp = xmlRelaxNGCheckRules(ctxt, cur->cont2, flags); - ret = xmlRelaxNGMaxContentType(tmp, ret); - break; - case XML_RELAXNG_NOT_ALLOWED: - ret = XML_RELAXNG_CONTENT_EMPTY; - break; - case XML_RELAXNG_PARAM: - ret = XML_RELAXNG_CONTENT_EMPTY; - break; - case XML_RELAXNG_DEF: - ret = xmlRelaxNGCheckRules(ctxt, cur->content, flags); - break; - case XML_RELAXNG_EXTERNALREF: - ret = xmlRelaxNGCheckRules(ctxt, cur->content, flags); - break; - case XML_RELAXNG_START: - ret = xmlRelaxNGCheckRules(ctxt, cur->content, flags); - break; - case XML_RELAXNG_AFTER: - ret = XML_RELAXNG_CONTENT_ERROR; - break; + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_START) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern start//interleave\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_ONEORMORE) + nflags = flags | XML_RELAXNG_IN_OOMINTERLEAVE; + else + nflags = flags; + ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type); + } else if (cur->type == XML_RELAXNG_EXCEPT) { + if ((cur->parent != NULL) && + (cur->parent->type == XML_RELAXNG_DATATYPE)) + nflags = flags | XML_RELAXNG_IN_DATAEXCEPT; + else + nflags = flags; + ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type); + } else if (cur->type == XML_RELAXNG_DATATYPE) { + if (flags & XML_RELAXNG_IN_START) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern start//data\n"); + ctxt->nbErrors++; + } + xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type); + ret = XML_RELAXNG_CONTENT_SIMPLE; + } else if (cur->type == XML_RELAXNG_VALUE) { + if (flags & XML_RELAXNG_IN_START) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern start//value\n"); + ctxt->nbErrors++; + } + xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type); + ret = XML_RELAXNG_CONTENT_SIMPLE; + } else if (cur->type == XML_RELAXNG_TEXT) { + if (flags & XML_RELAXNG_IN_LIST) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern list//text\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_DATAEXCEPT) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern data/except//text\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_START) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern start//text\n"); + ctxt->nbErrors++; + } + ret = XML_RELAXNG_CONTENT_COMPLEX; + } else if (cur->type == XML_RELAXNG_EMPTY) { + if (flags & XML_RELAXNG_IN_DATAEXCEPT) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern data/except//empty\n"); + ctxt->nbErrors++; + } + if (flags & XML_RELAXNG_IN_START) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found forbidden pattern start//empty\n"); + ctxt->nbErrors++; + } + ret = XML_RELAXNG_CONTENT_EMPTY; + } else if (cur->type == XML_RELAXNG_CHOICE) { + xmlRelaxNGCheckChoiceDeterminism(ctxt, cur); + ret = xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type); + } else { + ret = xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type); + } + cur = cur->next; + if (ptype == XML_RELAXNG_GROUP) { + val = xmlRelaxNGGroupContentType(val, ret); + } else if (ptype == XML_RELAXNG_INTERLEAVE) { + tmp = xmlRelaxNGGroupContentType(val, ret); + if (tmp != XML_RELAXNG_CONTENT_ERROR) + tmp = xmlRelaxNGMaxContentType(val, ret); + } else if (ptype == XML_RELAXNG_CHOICE) { + val = xmlRelaxNGMaxContentType(val, ret); + } else if (ptype == XML_RELAXNG_LIST) { + val = XML_RELAXNG_CONTENT_SIMPLE; + } else if (ptype == XML_RELAXNG_EXCEPT) { + if (ret == XML_RELAXNG_CONTENT_ERROR) + val = XML_RELAXNG_CONTENT_ERROR; + else + val = XML_RELAXNG_CONTENT_SIMPLE; + } else { + val = xmlRelaxNGGroupContentType(val, ret); + } + } - return (ret); + return(val); } /** @@ -5001,16 +5434,15 @@ xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { } ctxt->define = olddefine; if (schema->topgrammar->start != NULL) { - xmlRelaxNGDefinePtr start; - - start = schema->topgrammar->start; - - xmlRelaxNGCheckCycles(ctxt, start, 0); + xmlRelaxNGCheckCycles(ctxt, schema->topgrammar->start, 0); if ((ctxt->flags & XML_RELAXNG_IN_EXTERNALREF) == 0) { - - xmlRelaxNGSimplify(ctxt, start, NULL); - xmlRelaxNGCheckRules(ctxt, start, XML_RELAXNG_IN_START); - xmlRelaxNGSimplifyRefs(ctxt, start); + xmlRelaxNGSimplify(ctxt, schema->topgrammar->start, NULL); + while ((schema->topgrammar->start != NULL) && + (schema->topgrammar->start->type == XML_RELAXNG_NOOP) && + (schema->topgrammar->start->next != NULL)) + schema->topgrammar->start = schema->topgrammar->start->content; + xmlRelaxNGCheckRules(ctxt, schema->topgrammar->start, + XML_RELAXNG_IN_START, XML_RELAXNG_NOOP); } } @@ -5272,15 +5704,15 @@ xmlRelaxNGCleanupAttributes(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) { } /** - * xmlRelaxNGCleanupBlanks: + * xmlRelaxNGCleanupTree: * @ctxt: a Relax-NG parser context * @root: an xmlNodePtr subtree * - * Cleanup the subtree from unwanted nodes for parsing, i.e. foreign - * namespaces and blanks nodes per rules 4.1 and 4.2 + * Cleanup the subtree from unwanted nodes for parsing, resolve + * Include and externalRef lookups. */ static void -xmlRelaxNGCleanupBlanks(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr root) { +xmlRelaxNGCleanupTree(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr root) { xmlNodePtr cur, delete; delete = NULL; @@ -5310,517 +5742,320 @@ xmlRelaxNGCleanupBlanks(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr root) { } delete = cur; goto skip_children; - } - } - /* - * Simplification 4.2 whitespaces - */ - else if ((cur->type == XML_TEXT_NODE) || - (cur->type == XML_CDATA_SECTION_NODE)) { - if (IS_BLANK_NODE(cur)) { - if (cur->parent->type == XML_ELEMENT_NODE) { - if ((!xmlStrEqual(cur->parent->name, BAD_CAST "value")) && - (!xmlStrEqual(cur->parent->name, BAD_CAST "param"))) - delete = cur; - } else { - delete = cur; - goto skip_children; - } - } - } else { - delete = cur; - goto skip_children; - } - - /* - * Skip to next node - */ - if (cur->children != NULL) { - if ((cur->children->type != XML_ENTITY_DECL) && - (cur->children->type != XML_ENTITY_REF_NODE) && - (cur->children->type != XML_ENTITY_NODE)) { - cur = cur->children; - continue; - } - } -skip_children: - if (cur->next != NULL) { - cur = cur->next; - continue; - } - - do { - cur = cur->parent; - if (cur == NULL) - break; - if (cur == root) { - cur = NULL; - break; - } - if (cur->next != NULL) { - cur = cur->next; - break; - } - } while (cur != NULL); - } - if (delete != NULL) { - xmlUnlinkNode(delete); - xmlFreeNode(delete); - delete = NULL; - } -} - -/** - * xmlRelaxNGCleanupTree: - * @ctxt: a Relax-NG parser context - * @root: an xmlNodePtr subtree - * - * Cleanup the subtree from unwanted nodes for parsing, resolve - * Include and externalRef lookups. - */ -static void -xmlRelaxNGCleanupTree(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr root) { - xmlNodePtr cur, delete; + } else { + xmlRelaxNGCleanupAttributes(ctxt, cur); + if (xmlStrEqual(cur->name, BAD_CAST "externalRef")) { + xmlChar *href, *ns, *base, *URL; + xmlRelaxNGDocumentPtr docu; + xmlNodePtr tmp; - delete = NULL; - cur = root; - while (cur != NULL) { - if (delete != NULL) { - xmlUnlinkNode(delete); - xmlFreeNode(delete); - delete = NULL; - } - if (cur->type == XML_ELEMENT_NODE) { - xmlRelaxNGCleanupAttributes(ctxt, cur); - - if (xmlStrEqual(cur->name, BAD_CAST "externalRef")) { - xmlChar *href, *ns, *base, *URL; - xmlRelaxNGDocumentPtr docu; - xmlNodePtr tmp; - - ns = xmlGetProp(cur, BAD_CAST "ns"); - if (ns == NULL) { - tmp = cur->parent; - while ((tmp != NULL) && - (tmp->type == XML_ELEMENT_NODE)) { - ns = xmlGetProp(tmp, BAD_CAST "ns"); - if (ns != NULL) - break; - tmp = tmp->parent; + ns = xmlGetProp(cur, BAD_CAST "ns"); + if (ns == NULL) { + tmp = cur->parent; + while ((tmp != NULL) && + (tmp->type == XML_ELEMENT_NODE)) { + ns = xmlGetProp(tmp, BAD_CAST "ns"); + if (ns != NULL) + break; + tmp = tmp->parent; + } + } + href = xmlGetProp(cur, BAD_CAST "href"); + if (href == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "xmlRelaxNGParse: externalRef has no href attribute\n"); + ctxt->nbErrors++; + delete = cur; + goto skip_children; + } + base = xmlNodeGetBase(cur->doc, cur); + URL = xmlBuildURI(href, base); + if (URL == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Failed to compute URL for externalRef %s\n", href); + ctxt->nbErrors++; + if (href != NULL) + xmlFree(href); + if (base != NULL) + xmlFree(base); + delete = cur; + goto skip_children; } - } - href = xmlGetProp(cur, BAD_CAST "href"); - if (href == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "xmlRelaxNGParse: externalRef has no href attribute\n"); - ctxt->nbErrors++; - delete = cur; - goto skip_children; - } - base = xmlNodeGetBase(cur->doc, cur); - URL = xmlBuildURI(href, base); - if (URL == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Failed to compute URL for externalRef %s\n", href); - ctxt->nbErrors++; if (href != NULL) xmlFree(href); if (base != NULL) xmlFree(base); - delete = cur; - goto skip_children; - } - if (href != NULL) - xmlFree(href); - if (base != NULL) - xmlFree(base); - docu = xmlRelaxNGLoadExternalRef(ctxt, URL, ns); - if (docu == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Failed to load externalRef %s\n", URL); - ctxt->nbErrors++; + docu = xmlRelaxNGLoadExternalRef(ctxt, URL, ns); + if (docu == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Failed to load externalRef %s\n", URL); + ctxt->nbErrors++; + xmlFree(URL); + delete = cur; + goto skip_children; + } + if (ns != NULL) + xmlFree(ns); xmlFree(URL); - delete = cur; - goto skip_children; - } - if (ns != NULL) - xmlFree(ns); - xmlFree(URL); - cur->_private = docu; - } else if (xmlStrEqual(cur->name, BAD_CAST "include")) { - xmlChar *href, *ns, *base, *URL; - xmlRelaxNGIncludePtr incl; - xmlNodePtr tmp; - - href = xmlGetProp(cur, BAD_CAST "href"); - if (href == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "xmlRelaxNGParse: include has no href attribute\n"); - ctxt->nbErrors++; - delete = cur; - goto skip_children; - } - base = xmlNodeGetBase(cur->doc, cur); - URL = xmlBuildURI(href, base); - if (URL == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Failed to compute URL for include %s\n", href); - ctxt->nbErrors++; + cur->_private = docu; + } else if (xmlStrEqual(cur->name, BAD_CAST "include")) { + xmlChar *href, *ns, *base, *URL; + xmlRelaxNGIncludePtr incl; + xmlNodePtr tmp; + + href = xmlGetProp(cur, BAD_CAST "href"); + if (href == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "xmlRelaxNGParse: include has no href attribute\n"); + ctxt->nbErrors++; + delete = cur; + goto skip_children; + } + base = xmlNodeGetBase(cur->doc, cur); + URL = xmlBuildURI(href, base); + if (URL == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Failed to compute URL for include %s\n", href); + ctxt->nbErrors++; + if (href != NULL) + xmlFree(href); + if (base != NULL) + xmlFree(base); + delete = cur; + goto skip_children; + } if (href != NULL) xmlFree(href); if (base != NULL) xmlFree(base); - delete = cur; - goto skip_children; - } - if (href != NULL) - xmlFree(href); - if (base != NULL) - xmlFree(base); - ns = xmlGetProp(cur, BAD_CAST "ns"); - if (ns == NULL) { - tmp = cur->parent; - while ((tmp != NULL) && - (tmp->type == XML_ELEMENT_NODE)) { - ns = xmlGetProp(tmp, BAD_CAST "ns"); - if (ns != NULL) - break; - tmp = tmp->parent; - } - } - incl = xmlRelaxNGLoadInclude(ctxt, URL, cur, ns); - if (ns != NULL) - xmlFree(ns); - if (incl == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Failed to load include %s\n", URL); - ctxt->nbErrors++; - xmlFree(URL); - delete = cur; - goto skip_children; - } - xmlFree(URL); - cur->_private = incl; - } else if ((xmlStrEqual(cur->name, BAD_CAST "element")) || - (xmlStrEqual(cur->name, BAD_CAST "attribute"))) { - xmlChar *name, *ns; - xmlNodePtr text = NULL; - - /* - * Simplification 4.8. name attribute of element - * and attribute elements - */ - name = xmlGetProp(cur, BAD_CAST "name"); - if (name != NULL) { - if (cur->children == NULL) { - text = xmlNewChild(cur, cur->ns, BAD_CAST "name", - name); - } else { - xmlNodePtr node; - node = xmlNewNode(cur->ns, BAD_CAST "name"); - if (node != NULL) { - xmlAddPrevSibling(cur->children, node); - text = xmlNewText(name); - xmlAddChild(node, text); - text = node; + ns = xmlGetProp(cur, BAD_CAST "ns"); + if (ns == NULL) { + tmp = cur->parent; + while ((tmp != NULL) && + (tmp->type == XML_ELEMENT_NODE)) { + ns = xmlGetProp(tmp, BAD_CAST "ns"); + if (ns != NULL) + break; + tmp = tmp->parent; } } - if (text == NULL) { + incl = xmlRelaxNGLoadInclude(ctxt, URL, cur, ns); + if (ns != NULL) + xmlFree(ns); + if (incl == NULL) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, - "Failed to create a name %s element\n", name); + "Failed to load include %s\n", URL); ctxt->nbErrors++; + xmlFree(URL); + delete = cur; + goto skip_children; } - xmlUnsetProp(cur, BAD_CAST "name"); - xmlFree(name); - ns = xmlGetProp(cur, BAD_CAST "ns"); - if (ns != NULL) { - if (text != NULL) { - xmlSetProp(text, BAD_CAST "ns", ns); - /* xmlUnsetProp(cur, BAD_CAST "ns"); */ + xmlFree(URL); + cur->_private = incl; + } else if ((xmlStrEqual(cur->name, BAD_CAST "element")) || + (xmlStrEqual(cur->name, BAD_CAST "attribute"))) { + xmlChar *name, *ns; + xmlNodePtr text = NULL; + + /* + * Simplification 4.8. name attribute of element + * and attribute elements + */ + name = xmlGetProp(cur, BAD_CAST "name"); + if (name != NULL) { + if (cur->children == NULL) { + text = xmlNewChild(cur, cur->ns, BAD_CAST "name", + name); + } else { + xmlNodePtr node; + node = xmlNewNode(cur->ns, BAD_CAST "name"); + if (node != NULL) { + xmlAddPrevSibling(cur->children, node); + text = xmlNewText(name); + xmlAddChild(node, text); + text = node; + } } - xmlFree(ns); - } else if (xmlStrEqual(cur->name, - BAD_CAST "attribute")) { - xmlSetProp(text, BAD_CAST "ns", BAD_CAST ""); - } - } - } else if ((xmlStrEqual(cur->name, BAD_CAST "name")) || - (xmlStrEqual(cur->name, BAD_CAST "nsName")) || - (xmlStrEqual(cur->name, BAD_CAST "value"))) { - /* - * Simplification 4.8. name attribute of element - * and attribute elements - */ - if (xmlHasProp(cur, BAD_CAST "ns") == NULL) { - xmlNodePtr node; - xmlChar *ns = NULL; - - node = cur->parent; - while ((node != NULL) && - (node->type == XML_ELEMENT_NODE)) { - ns = xmlGetProp(node, BAD_CAST "ns"); + if (text == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Failed to create a name %s element\n", name); + ctxt->nbErrors++; + } + xmlUnsetProp(cur, BAD_CAST "name"); + xmlFree(name); + ns = xmlGetProp(cur, BAD_CAST "ns"); if (ns != NULL) { - break; + if (text != NULL) { + xmlSetProp(text, BAD_CAST "ns", ns); + /* xmlUnsetProp(cur, BAD_CAST "ns"); */ + } + xmlFree(ns); + } else if (xmlStrEqual(cur->name, + BAD_CAST "attribute")) { + xmlSetProp(text, BAD_CAST "ns", BAD_CAST ""); } - node = node->parent; - } - if (ns == NULL) { - xmlSetProp(cur, BAD_CAST "ns", BAD_CAST ""); - } else { - xmlSetProp(cur, BAD_CAST "ns", ns); - xmlFree(ns); } - } - if (xmlStrEqual(cur->name, BAD_CAST "name")) { - xmlChar *name, *local, *prefix; - + } else if ((xmlStrEqual(cur->name, BAD_CAST "name")) || + (xmlStrEqual(cur->name, BAD_CAST "nsName")) || + (xmlStrEqual(cur->name, BAD_CAST "value"))) { /* - * Simplification: 4.10. QNames + * Simplification 4.8. name attribute of element + * and attribute elements */ - name = xmlNodeGetContent(cur); - if (name != NULL) { - local = xmlSplitQName2(name, &prefix); - if (local != NULL) { - xmlNsPtr ns; - - ns = xmlSearchNs(cur->doc, cur, prefix); - if (ns == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "xmlRelaxNGParse: no namespace for prefix %s\n", prefix); - ctxt->nbErrors++; - } else { - xmlSetProp(cur, BAD_CAST "ns", ns->href); - xmlNodeSetContent(cur, local); + if (xmlHasProp(cur, BAD_CAST "ns") == NULL) { + xmlNodePtr node; + xmlChar *ns = NULL; + + node = cur->parent; + while ((node != NULL) && + (node->type == XML_ELEMENT_NODE)) { + ns = xmlGetProp(node, BAD_CAST "ns"); + if (ns != NULL) { + break; } - xmlFree(local); - xmlFree(prefix); + node = node->parent; } - xmlFree(name); - } - } - /* - * 4.16 - */ - if (xmlStrEqual(cur->name, BAD_CAST "nsName")) { - if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) { + if (ns == NULL) { + xmlSetProp(cur, BAD_CAST "ns", BAD_CAST ""); + } else { + xmlSetProp(cur, BAD_CAST "ns", ns); + xmlFree(ns); + } + } + if (xmlStrEqual(cur->name, BAD_CAST "name")) { + xmlChar *name, *local, *prefix; + + /* + * Simplification: 4.10. QNames + */ + name = xmlNodeGetContent(cur); + if (name != NULL) { + local = xmlSplitQName2(name, &prefix); + if (local != NULL) { + xmlNsPtr ns; + + ns = xmlSearchNs(cur->doc, cur, prefix); + if (ns == NULL) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "xmlRelaxNGParse: no namespace for prefix %s\n", prefix); + ctxt->nbErrors++; + } else { + xmlSetProp(cur, BAD_CAST "ns", ns->href); + xmlNodeSetContent(cur, local); + } + xmlFree(local); + xmlFree(prefix); + } + xmlFree(name); + } + } + /* + * 4.16 + */ + if (xmlStrEqual(cur->name, BAD_CAST "nsName")) { + if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found nsName/except//nsName forbidden construct\n"); + ctxt->nbErrors++; + } + } + } else if ((xmlStrEqual(cur->name, BAD_CAST "except")) && + (cur != root)) { + int oldflags = ctxt->flags; + + /* + * 4.16 + */ + if ((cur->parent != NULL) && + (xmlStrEqual(cur->parent->name, BAD_CAST "anyName"))) { + ctxt->flags |= XML_RELAXNG_IN_ANYEXCEPT; + xmlRelaxNGCleanupTree(ctxt, cur); + ctxt->flags = oldflags; + goto skip_children; + } else if ((cur->parent != NULL) && + (xmlStrEqual(cur->parent->name, BAD_CAST "nsName"))) { + ctxt->flags |= XML_RELAXNG_IN_NSEXCEPT; + xmlRelaxNGCleanupTree(ctxt, cur); + ctxt->flags = oldflags; + goto skip_children; + } + } else if (xmlStrEqual(cur->name, BAD_CAST "anyName")) { + /* + * 4.16 + */ + if (ctxt->flags & XML_RELAXNG_IN_ANYEXCEPT) { if (ctxt->error != NULL) ctxt->error(ctxt->userData, - "Found nsName/except//nsName forbidden construct\n"); + "Found anyName/except//anyName forbidden construct\n"); + ctxt->nbErrors++; + } else if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Found nsName/except//anyName forbidden construct\n"); ctxt->nbErrors++; } } - } else if ((xmlStrEqual(cur->name, BAD_CAST "except")) && - (cur != root)) { - int oldflags = ctxt->flags; - - /* - * 4.16 - */ - if ((cur->parent != NULL) && - (xmlStrEqual(cur->parent->name, BAD_CAST "anyName"))) { - ctxt->flags |= XML_RELAXNG_IN_ANYEXCEPT; - xmlRelaxNGCleanupTree(ctxt, cur); - ctxt->flags = oldflags; - goto skip_children; - } else if ((cur->parent != NULL) && - (xmlStrEqual(cur->parent->name, BAD_CAST "nsName"))) { - ctxt->flags |= XML_RELAXNG_IN_NSEXCEPT; - xmlRelaxNGCleanupTree(ctxt, cur); - ctxt->flags = oldflags; - goto skip_children; - } - } else if (xmlStrEqual(cur->name, BAD_CAST "anyName")) { - /* - * 4.16 - */ - if (ctxt->flags & XML_RELAXNG_IN_ANYEXCEPT) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found anyName/except//anyName forbidden construct\n"); - ctxt->nbErrors++; - } else if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Found nsName/except//anyName forbidden construct\n"); - ctxt->nbErrors++; - } - } - /* - * Thisd is not an else since "include" is transformed - * into a div - */ - if (xmlStrEqual(cur->name, BAD_CAST "div")) { - xmlChar *ns; - xmlNodePtr child, ins, tmp; - /* - * implements rule 4.11 + * Thisd is not an else since "include" is transformed + * into a div */ + if (xmlStrEqual(cur->name, BAD_CAST "div")) { + xmlChar *ns; + xmlNodePtr child, ins, tmp; - ns = xmlGetProp(cur, BAD_CAST "ns"); - - child = cur->children; - ins = cur; - while (child != NULL) { - if (ns != NULL) { - if (!xmlHasProp(child, BAD_CAST "ns")) { - xmlSetProp(child, BAD_CAST "ns", ns); - } - } - tmp = child->next; - xmlUnlinkNode(child); - ins = xmlAddNextSibling(ins, child); - child = tmp; - } - if (ns != NULL) - xmlFree(ns); - delete = cur; - goto skip_children; - } + /* + * implements rule 4.11 + */ - /* - * Simplifications on 4.12 - */ - if ((xmlStrEqual(cur->name, BAD_CAST "define")) || - (xmlStrEqual(cur->name, BAD_CAST "oneOrMore")) || - (xmlStrEqual(cur->name, BAD_CAST "zeroOrMore")) || - (xmlStrEqual(cur->name, BAD_CAST "optional")) || - (xmlStrEqual(cur->name, BAD_CAST "list")) || - (xmlStrEqual(cur->name, BAD_CAST "mixed"))) { - if ((cur->children != NULL) && - (cur->children->next != NULL)) { - xmlNodePtr group, tmp; - - group = xmlNewNode(cur->ns, BAD_CAST "group"); - if (group == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Out of memory allocating <group>\n"); - ctxt->nbErrors++; - } else { - group->children = cur->children; - group->parent = cur; - cur->children = group; - cur->last = group; - tmp = group->children; - while (tmp != NULL) { - tmp->parent = group; - if (tmp->next == NULL) - group->last = tmp; - tmp = tmp->next; - } - } - } - } else if (xmlStrEqual(cur->name, BAD_CAST "element")) { - xmlNodePtr tmp, group; + ns = xmlGetProp(cur, BAD_CAST "ns"); - tmp = cur->children; - if ((tmp != NULL) && (tmp->next != NULL)) { - tmp = tmp->next; - if (tmp->next != NULL) { - group = xmlNewNode(cur->ns, BAD_CAST "group"); - if (group == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Out of memory allocating <group>\n"); - ctxt->nbErrors++; - } else { - group->children = tmp; - tmp->prev->next = group; - tmp->prev = NULL; - group->parent = cur; - cur->last = group; - while (tmp != NULL) { - tmp->parent = group; - if (tmp->next == NULL) - group->last = tmp; - tmp = tmp->next; + child = cur->children; + ins = cur; + while (child != NULL) { + if (ns != NULL) { + if (!xmlHasProp(child, BAD_CAST "ns")) { + xmlSetProp(child, BAD_CAST "ns", ns); } } + tmp = child->next; + xmlUnlinkNode(child); + ins = xmlAddNextSibling(ins, child); + child = tmp; } - } - } else if ((xmlStrEqual(cur->name, BAD_CAST "group")) || - (xmlStrEqual(cur->name, BAD_CAST "choice")) || - (xmlStrEqual(cur->name, BAD_CAST "interleave"))) { - xmlNodePtr tmp, group; - - if (cur->children == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Patterns <%s> has no children\n", cur->name); - ctxt->nbErrors++; + if (ns != NULL) + xmlFree(ns); delete = cur; goto skip_children; } - /* - * keep the node if cur->children->next to preserve the - * bases, those will be ignored at parsing. - */ - if ((cur->children->next != NULL) && - (cur->children->next->next != NULL)) { - group = xmlNewNode(cur->ns, cur->name); - if (group == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Out of memory allocating <%s>\n"); - ctxt->nbErrors++; - } else { - tmp = cur->children->next; - group->children = tmp; - tmp->prev->next = group; - tmp->prev = NULL; - group->parent = cur; - cur->last = group; - while (tmp != NULL) { - tmp->parent = group; - if (tmp->next == NULL) - group->last = tmp; - tmp = tmp->next; - } - } - } } - /* - * Simplifications on 4.13 - */ - if (xmlStrEqual(cur->name, BAD_CAST "mixed")) { - if (cur->children == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Mixed is empty\n"); - ctxt->nbErrors++; + } + /* + * Simplification 4.2 whitespaces + */ + else if ((cur->type == XML_TEXT_NODE) || + (cur->type == XML_CDATA_SECTION_NODE)) { + if (IS_BLANK_NODE(cur)) { + if (cur->parent->type == XML_ELEMENT_NODE) { + if ((!xmlStrEqual(cur->parent->name, BAD_CAST "value")) && + (!xmlStrEqual(cur->parent->name, BAD_CAST "param"))) + delete = cur; } else { - xmlChar *name = (xmlChar *) cur->name; - xmlNodePtr txt; - - cur->name = xmlStrdup(BAD_CAST "interleave"); - if (cur->name == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Out of memory handling <mixed>\n"); - ctxt->nbErrors++; - cur->name = name; - } else { - xmlFree(name); - txt = xmlNewChild(cur, cur->ns, BAD_CAST "text", NULL); - if (txt == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, - "Out of memory handling <mixed>\n"); - ctxt->nbErrors++; - cur->name = name; - } - } + delete = cur; + goto skip_children; } } + } else { + delete = cur; + goto skip_children; } /* @@ -5886,19 +6121,7 @@ xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc) { ctxt->nbErrors++; return (NULL); } - xmlRelaxNGCleanupBlanks(ctxt, root); - root = xmlDocGetRootElement(doc); - if (root == NULL) { - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, "xmlRelaxNGParse: %s is empty\n", - ctxt->URL); - ctxt->nbErrors++; - return (NULL); - } xmlRelaxNGCleanupTree(ctxt, root); -#if 0 -xmlDocDump(stdout, doc); -#endif return(doc); } @@ -5986,6 +6209,17 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt) } /* + * Check the ref/defines links + */ + /* + * try to preprocess interleaves + */ + if (ctxt->interleaves != NULL) { + xmlHashScan(ctxt->interleaves, + (xmlHashScanner)xmlRelaxNGComputeInterleaves, ctxt); + } + + /* * if there was a parsing error return NULL */ if (ctxt->nbErrors > 0) { @@ -6082,9 +6316,8 @@ xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define) { fprintf(output, " ns=\"%s\"", define->ns); fprintf(output, ">%s</name>\n", define->name); } - if (define->nameClass != NULL) - xmlRelaxNGDumpDefine(output, define->nameClass); - xmlRelaxNGDumpDefine(output, define->content); + xmlRelaxNGDumpDefines(output, define->attrs); + xmlRelaxNGDumpDefines(output, define->content); fprintf(output, "</element>\n"); break; case XML_RELAXNG_LIST: @@ -6094,38 +6327,37 @@ xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define) { break; case XML_RELAXNG_ONEORMORE: fprintf(output, "<oneOrMore>\n"); - xmlRelaxNGDumpDefine(output, define->content); + xmlRelaxNGDumpDefines(output, define->content); fprintf(output, "</oneOrMore>\n"); break; + case XML_RELAXNG_ZEROORMORE: + fprintf(output, "<zeroOrMore>\n"); + xmlRelaxNGDumpDefines(output, define->content); + fprintf(output, "</zeroOrMore>\n"); + break; case XML_RELAXNG_CHOICE: fprintf(output, "<choice>\n"); - xmlRelaxNGDumpDefine(output, define->content); - xmlRelaxNGDumpDefine(output, define->cont2); + xmlRelaxNGDumpDefines(output, define->content); fprintf(output, "</choice>\n"); break; case XML_RELAXNG_GROUP: fprintf(output, "<group>\n"); - xmlRelaxNGDumpDefine(output, define->content); - xmlRelaxNGDumpDefine(output, define->cont2); + xmlRelaxNGDumpDefines(output, define->content); fprintf(output, "</group>\n"); break; case XML_RELAXNG_INTERLEAVE: fprintf(output, "<interleave>\n"); - xmlRelaxNGDumpDefine(output, define->content); - xmlRelaxNGDumpDefine(output, define->cont2); + xmlRelaxNGDumpDefines(output, define->content); fprintf(output, "</interleave>\n"); break; + case XML_RELAXNG_OPTIONAL: + fprintf(output, "<optional>\n"); + xmlRelaxNGDumpDefines(output, define->content); + fprintf(output, "</optional>\n"); + break; case XML_RELAXNG_ATTRIBUTE: fprintf(output, "<attribute>\n"); - if (define->name != NULL) { - fprintf(output, "<name"); - if (define->ns != NULL) - fprintf(output, " ns=\"%s\"", define->ns); - fprintf(output, ">%s</name>\n", define->name); - } - if (define->nameClass != NULL) - xmlRelaxNGDumpDefine(output, define->nameClass); - xmlRelaxNGDumpDefine(output, define->content); + xmlRelaxNGDumpDefines(output, define->content); fprintf(output, "</attribute>\n"); break; case XML_RELAXNG_DEF: @@ -6133,7 +6365,7 @@ xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define) { if (define->name != NULL) fprintf(output, " name=\"%s\"", define->name); fprintf(output, ">\n"); - xmlRelaxNGDumpDefine(output, define->content); + xmlRelaxNGDumpDefines(output, define->content); fprintf(output, "</define>\n"); break; case XML_RELAXNG_REF: @@ -6141,7 +6373,7 @@ xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define) { if (define->name != NULL) fprintf(output, " name=\"%s\"", define->name); fprintf(output, ">\n"); - xmlRelaxNGDumpDefine(output, define->content); + xmlRelaxNGDumpDefines(output, define->content); fprintf(output, "</ref>\n"); break; case XML_RELAXNG_PARENTREF: @@ -6149,42 +6381,26 @@ xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define) { if (define->name != NULL) fprintf(output, " name=\"%s\"", define->name); fprintf(output, ">\n"); - xmlRelaxNGDumpDefine(output, define->content); + xmlRelaxNGDumpDefines(output, define->content); fprintf(output, "</parentRef>\n"); break; case XML_RELAXNG_EXTERNALREF: fprintf(output, "<externalRef>"); - xmlRelaxNGDumpDefine(output, define->content); + xmlRelaxNGDumpDefines(output, define->content); fprintf(output, "</externalRef>\n"); break; - case XML_RELAXNG_AFTER: - fprintf(output, "<after>"); - xmlRelaxNGDumpDefine(output, define->content); - xmlRelaxNGDumpDefine(output, define->cont2); - fprintf(output, "</after>\n"); - break; case XML_RELAXNG_DATATYPE: - fprintf(output, "<data>"); - fprintf(output, "</data>\n"); - break; case XML_RELAXNG_VALUE: - fprintf(output, "<value>"); - fprintf(output, "</value>\n"); - break; - case XML_RELAXNG_EXCEPT: - fprintf(output, "<except>\n"); - xmlRelaxNGDumpDefine(output, define->content); - fprintf(output, "</except>\n"); + TODO break; case XML_RELAXNG_START: + case XML_RELAXNG_EXCEPT: case XML_RELAXNG_PARAM: TODO break; -#if 0 case XML_RELAXNG_NOOP: - xmlRelaxNGDumpDefine(output, define->content); + xmlRelaxNGDumpDefines(output, define->content); break; -#endif } } @@ -6285,6 +6501,8 @@ xmlRelaxNGDumpTree(FILE * output, xmlRelaxNGPtr schema) * Validation implementation * * * ************************************************************************/ +static int xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define); static int xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGDefinePtr define); @@ -6384,8 +6602,8 @@ xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar *value, } lib = (xmlRelaxNGTypeLibraryPtr) define->data; if (lib->check != NULL) { - if ((define->prop != NULL) && - (define->prop->type == XML_RELAXNG_PARAM)) { + if ((define->attrs != NULL) && + (define->attrs->type == XML_RELAXNG_PARAM)) { ret = lib->check(lib->data, define->name, value, &result); } else { ret = lib->check(lib->data, define->name, value, NULL); @@ -6403,7 +6621,7 @@ xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar *value, VALID_ERR3(XML_RELAXNG_ERR_TYPEVAL, define->name, value); ret = -1; } - cur = define->prop; + cur = define->attrs; while ((ret == 0) && (cur != NULL) && (cur->type == XML_RELAXNG_PARAM)) { if (lib->facet != NULL) { tmp = lib->facet(lib->data, define->name, cur->name, @@ -6559,16 +6777,20 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, break; } case XML_RELAXNG_CHOICE: { + xmlRelaxNGDefinePtr list = define->content; xmlChar *oldvalue; oldflags = ctxt->flags; ctxt->flags |= FLAGS_IGNORABLE; oldvalue = ctxt->state->value; - ret = xmlRelaxNGValidateValue(ctxt, define->content); - if (ret != 0) { - oldvalue = ctxt->state->value; - ret = xmlRelaxNGValidateValue(ctxt, define->cont2); + while (list != NULL) { + ret = xmlRelaxNGValidateValue(ctxt, list); + if (ret == 0) { + break; + } + ctxt->state->value = oldvalue; + list = list->next; } ctxt->flags = oldflags; if (ret != 0) { @@ -6582,14 +6804,12 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, break; } case XML_RELAXNG_LIST: { + xmlRelaxNGDefinePtr list = define->content; xmlChar *oldvalue, *oldend, *val, *cur; #ifdef DEBUG_LIST int nb_values = 0; #endif - /* - * TODO: handle groups ... see 4.12 dimplification too - */ oldvalue = ctxt->state->value; oldend = ctxt->state->endvalue; @@ -6622,33 +6842,45 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, ctxt->state->endvalue = cur; cur = val; while ((*cur == 0) && (cur != ctxt->state->endvalue)) cur++; - if ((cur == ctxt->state->endvalue) && - (!xmlRelaxNGIsNullable(define->content))) { - VALID_ERR(XML_RELAXNG_ERR_LISTEMPTY); - ret = -1; - } else { - ctxt->state->value = cur; - ret = xmlRelaxNGValidateValue(ctxt, define->content); + ctxt->state->value = cur; - if ((ret == 0) && (ctxt->state->value != NULL) && - (ctxt->state->value != ctxt->state->endvalue)) { - VALID_ERR2(XML_RELAXNG_ERR_LISTEXTRA, ctxt->state->value); - ret = -1; + while (list != NULL) { + if (ctxt->state->value == ctxt->state->endvalue) + ctxt->state->value = NULL; + ret = xmlRelaxNGValidateValue(ctxt, list); + if (ret != 0) { +#ifdef DEBUG_LIST + xmlGenericError(xmlGenericErrorContext, + "Failed to validate value: '%s' with %d rule\n", + ctxt->state->value, nb_values); +#endif + break; } +#ifdef DEBUG_LIST + nb_values++; +#endif + list = list->next; + } + + if ((ret == 0) && (ctxt->state->value != NULL) && + (ctxt->state->value != ctxt->state->endvalue)) { + VALID_ERR2(XML_RELAXNG_ERR_LISTEXTRA, ctxt->state->value); + ret = -1; } xmlFree(val); ctxt->state->value = oldvalue; ctxt->state->endvalue = oldend; break; } - case XML_RELAXNG_ONEORMORE: { - xmlChar *cur, *temp; - + case XML_RELAXNG_ONEORMORE: ret = xmlRelaxNGValidateValueList(ctxt, define->content); if (ret != 0) { break; } + /* no break on purpose */ + case XML_RELAXNG_ZEROORMORE: { + xmlChar *cur, *temp; oldflags = ctxt->flags; ctxt->flags |= FLAGS_IGNORABLE; @@ -6690,15 +6922,23 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, break; } case XML_RELAXNG_DEF: - case XML_RELAXNG_GROUP: - if (define->content != NULL) - ret = xmlRelaxNGValidateValue(ctxt, define->content); - if ((ret == 0) && (define->cont2 != NULL)) - ret = xmlRelaxNGValidateValue(ctxt, define->cont2); + case XML_RELAXNG_GROUP: { + xmlRelaxNGDefinePtr list; + + list = define->content; + while (list != NULL) { + ret = xmlRelaxNGValidateValue(ctxt, list); + if (ret != 0) { + ret = -1; + break; + } else + ret = 0; + list = list->next; + } break; + } case XML_RELAXNG_REF: case XML_RELAXNG_PARENTREF: - case XML_RELAXNG_EXTERNALREF: ret = xmlRelaxNGValidateValue(ctxt, define->content); break; default: @@ -6732,6 +6972,57 @@ xmlRelaxNGValidateValueContent(xmlRelaxNGValidCtxtPtr ctxt, } /** + * xmlRelaxNGAttributeMatch: + * @ctxt: a Relax-NG validation context + * @define: the definition to check + * @prop: the attribute + * + * Check if the attribute matches the definition nameClass + * + * Returns 1 if the attribute matches, 0 if no, or -1 in case of error + */ +static int +xmlRelaxNGAttributeMatch(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define, + xmlAttrPtr prop) { + int ret; + + if (define->name != NULL) { + if (!xmlStrEqual(define->name, prop->name)) + return(0); + } + if (define->ns != NULL) { + if (define->ns[0] == 0) { + if (prop->ns != NULL) + return(0); + } else { + if ((prop->ns == NULL) || + (!xmlStrEqual(define->ns, prop->ns->href))) + return(0); + } + } + if (define->nameClass == NULL) + return(1); + define = define->nameClass; + if (define->type == XML_RELAXNG_EXCEPT) { + xmlRelaxNGDefinePtr list; + + list = define->content; + while (list != NULL) { + ret = xmlRelaxNGAttributeMatch(ctxt, list, prop); + if (ret == 1) + return(0); + if (ret < 0) + return(ret); + list = list->next; + } + } else { + TODO + } + return(1); +} + +/** * xmlRelaxNGValidateAttribute: * @ctxt: a Relax-NG validation context * @define: the definition to verify @@ -6791,8 +7082,7 @@ xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt, for (i = 0;i < ctxt->state->nbAttrs;i++) { tmp = ctxt->state->attrs[i]; if ((tmp != NULL) && - (xmlRelaxNGNsNameMatch(ctxt, define, - (xmlNodePtr)tmp, 0) == 1)) { + (xmlRelaxNGAttributeMatch(ctxt, define, tmp) == 1)) { prop = tmp; break; } @@ -6834,6 +7124,27 @@ xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt, } /** + * xmlRelaxNGValidateAttributeList: + * @ctxt: a Relax-NG validation context + * @define: the list of definition to verify + * + * Validate the given node against the list of attribute definitions + * + * Returns 0 if the validation succeeded or an error code. + */ +static int +xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr defines) { + int ret = 0; + while (defines != NULL) { + if (xmlRelaxNGValidateAttribute(ctxt, defines) != 0) + ret = -1; + defines = defines->next; + } + return(ret); +} + +/** * xmlRelaxNGNodeMatchesList: * @node: the node * @list: a NULL terminated array of definitions @@ -6855,9 +7166,14 @@ xmlRelaxNGNodeMatchesList(xmlNodePtr node, xmlRelaxNGDefinePtr *list) { if ((node->type == XML_ELEMENT_NODE) && (cur->type == XML_RELAXNG_ELEMENT)) { if (cur->name == NULL) { - if ((node->ns != NULL) && - (xmlStrEqual(node->ns->href, cur->ns))) - return(1); + if ((cur->ns == NULL) || (cur->ns[0] == 0)) { + if (node->ns == NULL) + return(1); + } else { + if ((node->ns != NULL) && + (xmlStrEqual(node->ns->href, cur->ns))) + return(1); + } } else if (xmlStrEqual(cur->name, node->name)) { if ((cur->ns == NULL) || (cur->ns[0] == 0)) { if (node->ns == NULL) @@ -6879,1276 +7195,1043 @@ xmlRelaxNGNodeMatchesList(xmlNodePtr node, xmlRelaxNGDefinePtr *list) { } /** - * xmlRelaxNGNsNameMatch: + * xmlRelaxNGValidateInterleave: * @ctxt: a Relax-NG validation context - * @define: the definition to check - * @elem: the node - * @eora: element or attribute + * @define: the definition to verify * - * Check if the element/attribute matches the definition nameClass + * Validate an interleave definition for a node. * - * Returns 1 if the node matches, 0 if no, or -1 in case of error + * Returns 0 if the validation succeeded or an error code. */ static int -xmlRelaxNGNsNameMatch(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr define, - xmlNodePtr elem, int eora) -{ - int ret, oldflags; - - if (define->type == XML_RELAXNG_CHOICE) { - oldflags = ctxt->flags; - ctxt->flags |= FLAGS_IGNORABLE; - - ret = xmlRelaxNGNsNameMatch(ctxt, define->content, elem, eora); - if (ret == 0) - ret = xmlRelaxNGNsNameMatch(ctxt, define->cont2, elem, eora); - if (ret != 1) { - if ((ctxt->flags & FLAGS_IGNORABLE) == 0) - xmlRelaxNGDumpValidError(ctxt); - } else { - ctxt->errNr = 0; - } - ctxt->flags = oldflags; - return (ret); - } else if ((define->type == XML_RELAXNG_ELEMENT) || - (define->type == XML_RELAXNG_ATTRIBUTE)) { - if (define->name != NULL) { - if (!xmlStrEqual(elem->name, define->name)) { - if (eora) { - VALID_ERR3(XML_RELAXNG_ERR_ELEMNAME, - define->name, elem->name); - } else { - VALID_ERR3(XML_RELAXNG_ERR_ATTRNAME, - define->name, elem->name); - } - return (0); - } - } - if ((define->ns != NULL) && (define->ns[0] != 0)) { - if (elem->ns == NULL) { - if (eora) { - VALID_ERR2(XML_RELAXNG_ERR_ELEMNONS, elem->name); - } else { - VALID_ERR2(XML_RELAXNG_ERR_ATTRNONS, elem->name); - } - return (0); - } else if (!xmlStrEqual(elem->ns->href, define->ns)) { - if (eora) { - VALID_ERR3(XML_RELAXNG_ERR_ELEMWRONGNS, - elem->name, define->ns); - } else { - VALID_ERR3(XML_RELAXNG_ERR_ATTRWRONGNS, - elem->name, define->ns); - } - return (0); - } - } else if ((elem->ns != NULL) && (define->ns != NULL) && - (define->name == NULL)) { - if (eora) { - VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, elem->name); - } else { - VALID_ERR2(XML_RELAXNG_ERR_ATTREXTRANS, elem->name); - } - return (0); - } else if ((elem->ns != NULL) && (define->name != NULL)) { - if (eora) { - VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, define->name); - } else { - VALID_ERR2(XML_RELAXNG_ERR_ATTREXTRANS, define->name); - } - return (0); - } - if (define->nameClass == NULL) - return (1); - ret = xmlRelaxNGNsNameMatch(ctxt, define->nameClass, elem, eora); - } else if (define->type == XML_RELAXNG_EXCEPT) { - xmlRelaxNGDefinePtr list; - - oldflags = ctxt->flags; - ctxt->flags |= FLAGS_IGNORABLE; - - list = define->content; - while (list != NULL) { - ret = xmlRelaxNGNsNameMatch(ctxt, list, elem, eora); - if (ret == 1) { - ctxt->flags = oldflags; - return (0); - } - if (ret < 0) { - ctxt->flags = oldflags; - return (ret); - } - list = list->next; - } - ret = 1; - ctxt->flags = oldflags; +xmlRelaxNGValidateInterleave(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define) { + int ret = 0, i, nbgroups, left; + int errNr = ctxt->errNr; + + xmlRelaxNGValidStatePtr oldstate; + xmlRelaxNGPartitionPtr partitions; + xmlRelaxNGInterleaveGroupPtr group = NULL; + xmlNodePtr cur, start, last = NULL, lastchg = NULL, lastelem; + xmlNodePtr *list = NULL, *lasts = NULL; + + if (define->data != NULL) { + partitions = (xmlRelaxNGPartitionPtr) define->data; + nbgroups = partitions->nbgroups; + left = nbgroups; } else { - TODO ret = -1; + VALID_ERR(XML_RELAXNG_ERR_INTERNODATA); + return(-1); } - return (ret); -} -/** - * xmlRelaxNGValidateNodeValue: - * @ctxt: a Relax-NG validation context - * @define: the definition to verify - * @nodes: the list of nodes - * - * Validate the given value definition for that node (or nodes) - * - * Returns 0 if the validation succeeded or an error code. - */ -static int -xmlRelaxNGValidateNodeValue(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr define, - xmlNodePtr nodes) { - int ret = 0; - xmlChar *content = NULL; + /* + * Build arrays to store the first and last node of the chain + * pertaining to each group + */ + list = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr)); + if (list == NULL) { + VALID_ERR(XML_RELAXNG_ERR_MEMORY); + return(-1); + } + memset(list, 0, nbgroups * sizeof(xmlNodePtr)); + lasts = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr)); + if (lasts == NULL) { + VALID_ERR(XML_RELAXNG_ERR_MEMORY); + return(-1); + } + memset(lasts, 0, nbgroups * sizeof(xmlNodePtr)); - while (nodes != NULL) { - if (nodes->type == XML_ELEMENT_NODE) { + /* + * Walk the sequence of children finding the right group and + * sorting them in sequences. + */ + cur = ctxt->state->seq; + cur = xmlRelaxNGSkipIgnored(ctxt, cur); + start = cur; + while (cur != NULL) { + ctxt->state->seq = cur; + for (i = 0;i < nbgroups;i++) { + group = partitions->groups[i]; + if (group == NULL) + continue; + if (xmlRelaxNGNodeMatchesList(cur, group->defs)) + break; + } + /* + * We break as soon as an element not matched is found + */ + if (i >= nbgroups) { break; - } else if ((nodes->type == XML_TEXT_NODE) || - (nodes->type == XML_CDATA_SECTION_NODE)) { - content = xmlStrcat(content, nodes->content); } - /* TODO: handle entities ... */ - nodes = nodes->next; - } - if (content == NULL) { - content = xmlStrdup(BAD_CAST ""); - if (content == NULL) { - VALID_ERR(XML_RELAXNG_ERR_MEMORY); - return(-1); + if (lasts[i] != NULL) { + lasts[i]->next = cur; + lasts[i] = cur; + } else { + list[i] = cur; + lasts[i] = cur; } + if (cur->next != NULL) + lastchg = cur->next; + else + lastchg = cur; + cur = xmlRelaxNGSkipIgnored(ctxt, cur->next); } - ctxt->state->value = content; - ret = xmlRelaxNGValidateValue(ctxt, define); - if (ret == -1) { - VALID_ERR2(XML_RELAXNG_ERR_VALUE, define->name); - } - if (content != NULL) - xmlFree(content); - return(ret); -} - -/** - * xmlRelaxNGValidateNodeList: - * @ctxt: a Relax-NG validation context - * @define: the definition to verify - * @nodes: the list of nodes - * - * Validate the given value definition for that node (or nodes) - * - * Returns 0 if the validation succeeded or an error code. - */ -static int -xmlRelaxNGValidateNodeList(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr define, - xmlNodePtr nodes) { - int ret = 0, len; - xmlChar *content = NULL; + if (ret != 0) { + VALID_ERR(XML_RELAXNG_ERR_INTERSEQ); + ret = -1; + goto done; + } + lastelem = cur; + oldstate = ctxt->state; + for (i = 0;i < nbgroups;i++) { + ctxt->state = xmlRelaxNGCopyValidState(ctxt, oldstate); + group = partitions->groups[i]; + if (lasts[i] != NULL) { + last = lasts[i]->next; + lasts[i]->next = NULL; + } + ctxt->state->seq = list[i]; + ret = xmlRelaxNGValidateDefinition(ctxt, group->rule); + if (ret != 0) + break; + if (ctxt->state != NULL) { + cur = ctxt->state->seq; + cur = xmlRelaxNGSkipIgnored(ctxt, cur); + xmlRelaxNGFreeValidState(oldstate); + oldstate = ctxt->state; + ctxt->state = NULL; + if (cur != NULL) { + VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name); + ret = -1; + ctxt->state = oldstate; + goto done; + } + } else if (ctxt->states != NULL) { + int j; + int found = 0; - while (nodes != NULL) { - if (nodes->type == XML_ELEMENT_NODE) { + for (j = 0;j < ctxt->states->nbState;j++) { + cur = ctxt->states->tabState[j]->seq; + cur = xmlRelaxNGSkipIgnored(ctxt, cur); + if (cur == NULL) { + found = 1; + break; + } + } + if (ctxt->states->nbState > 0) { + xmlRelaxNGFreeValidState(oldstate); + oldstate = ctxt->states->tabState[ctxt->states->nbState - 1]; + } + for (j = 0;j < ctxt->states->nbState - 1;j++) { + xmlRelaxNGFreeValidState(ctxt->states->tabState[j]); + } + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; + if (found == 0) { + VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name); + ret = -1; + ctxt->state = oldstate; + goto done; + } + } else { + ret = -1; break; - } else if ((nodes->type == XML_TEXT_NODE) || - (nodes->type == XML_CDATA_SECTION_NODE)) { - content = xmlStrcat(content, nodes->content); } - /* TODO: handle entities ... */ - nodes = nodes->next; - } - if (content == NULL) { - content = xmlStrdup(BAD_CAST ""); - if (content == NULL) { - VALID_ERR(XML_RELAXNG_ERR_MEMORY); - return(-1); + if (lasts[i] != NULL) { + lasts[i]->next = last; } } - len = xmlStrlen(content); - ctxt->state->value = content; - ctxt->state->endvalue = content + len; - ret = xmlRelaxNGValidateValue(ctxt, define); - ctxt->state->value = NULL; - ctxt->state->endvalue = NULL; - if (ret == -1) { - VALID_ERR(XML_RELAXNG_ERR_LIST); + if (ctxt->state != NULL) + xmlRelaxNGFreeValidState(ctxt->state); + ctxt->state = oldstate; + ctxt->state->seq = lastelem; + if (ret != 0) { + VALID_ERR(XML_RELAXNG_ERR_INTERSEQ); + ret = -1; + goto done; } - if (content != NULL) - xmlFree(content); - return(ret); -} -/** - * xmlRelaxNGValidateNodeDatatype: - * @ctxt: a Relax-NG validation context - * @define: the definition to verify - * @nodes: the list of nodes - * - * Validate the given datatype definition for that node (or nodes) - * - * Returns 0 if the validation succeeded or an error code. - */ -static int -xmlRelaxNGValidateNodeDatatype(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr define, - xmlNodePtr nodes) { - int ret = 0; - xmlChar *content = NULL; - - while (nodes != NULL) { - if (nodes->type == XML_ELEMENT_NODE) { +done: + /* + * builds the next links chain from the prev one + */ + cur = lastchg; + while (cur != NULL) { + if ((cur == start) || (cur->prev == NULL)) break; - } else if ((nodes->type == XML_TEXT_NODE) || - (nodes->type == XML_CDATA_SECTION_NODE)) { - content = xmlStrcat(content, nodes->content); - } - /* TODO: handle entities ... */ - nodes = nodes->next; + cur->prev->next = cur; + cur = cur->prev; } - if (content == NULL) { - content = xmlStrdup(BAD_CAST ""); - if (content == NULL) { - VALID_ERR(XML_RELAXNG_ERR_MEMORY); - return(-1); - } - } - ctxt->state->value = NULL; - ret = xmlRelaxNGValidateDatatype(ctxt, content, define); - if (ret == -1) { - VALID_ERR2(XML_RELAXNG_ERR_DATATYPE, define->name); + if (ret == 0) { + ctxt->errNr = errNr; } - if (content != NULL) - xmlFree(content); + + xmlFree(list); + xmlFree(lasts); return(ret); } -/************************************************************************ - * * - * Derivative validation implementation * - * * - ************************************************************************/ - -static xmlRelaxNGDefinePtr xmlRelaxNGChildDeriv( - xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr define, - xmlNodePtr node); - -static struct _xmlRelaxNGDefine _empty = { XML_RELAXNG_EMPTY, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -static xmlRelaxNGDefinePtr xmlRelaxNGEmptyDeriv = &_empty; -static struct _xmlRelaxNGDefine _nallow = { XML_RELAXNG_NOT_ALLOWED, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -static xmlRelaxNGDefinePtr xmlRelaxNGNotAllowedDeriv = &_nallow; - -typedef xmlRelaxNGDefinePtr (*xmlRelaxNGDerivFunc) ( - xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr arg1, - xmlRelaxNGDefinePtr arg2); - /** - * xmlRelaxNGIsNullable: - * @define: the definition to verify + * xmlRelaxNGValidateDefinitionList: + * @ctxt: a Relax-NG validation context + * @define: the list of definition to verify * - * Check if a definition is nullable. + * Validate the given node content against the (list) of definitions * - * Returns 1 if yes, 0 if no and -1 in case of error + * Returns 0 if the validation succeeded or an error code. */ static int -xmlRelaxNGIsNullable(xmlRelaxNGDefinePtr define) { - int ret; - if (define == NULL) - return(-1); +xmlRelaxNGValidateDefinitionList(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr defines) { + int ret = 0, res; - if (define->flags & IS_NULLABLE) - return(1); - if (define->flags & IS_NOT_NULLABLE) - return(0); - switch (define->type) { - case XML_RELAXNG_EMPTY: - case XML_RELAXNG_TEXT: - ret = 1; break; -#if 0 - case XML_RELAXNG_NOOP: -#endif - case XML_RELAXNG_DEF: - case XML_RELAXNG_REF: - case XML_RELAXNG_EXTERNALREF: - case XML_RELAXNG_PARENTREF: - case XML_RELAXNG_ONEORMORE: - case XML_RELAXNG_START: - ret = xmlRelaxNGIsNullable(define->content); - break; - case XML_RELAXNG_EXCEPT: - case XML_RELAXNG_NOT_ALLOWED: - case XML_RELAXNG_ELEMENT: - case XML_RELAXNG_DATATYPE: - case XML_RELAXNG_PARAM: - case XML_RELAXNG_VALUE: - case XML_RELAXNG_LIST: - case XML_RELAXNG_ATTRIBUTE: - ret = 0; break; - case XML_RELAXNG_CHOICE: - ret = xmlRelaxNGIsNullable(define->cont2); - if (ret != 1) - ret = xmlRelaxNGIsNullable(define->content); - break; - case XML_RELAXNG_INTERLEAVE: - case XML_RELAXNG_GROUP: - ret = xmlRelaxNGIsNullable(define->content); - if (ret != 0) - ret = xmlRelaxNGIsNullable(define->cont2); - break; - default: + + while (defines != NULL) { + if ((ctxt->state != NULL) || (ctxt->states != NULL)) { + res = xmlRelaxNGValidateDefinition(ctxt, defines); + if (res < 0) + ret = -1; + } else { + VALID_ERR(XML_RELAXNG_ERR_NOSTATE); return(-1); + } + if (ret < 0) + break; + defines = defines->next; } - if (ret == 0) - define->flags |= IS_NOT_NULLABLE; - if (ret == 1) - define->flags |= IS_NULLABLE; - return(ret); -} -#if 0 -#define DEBUG_DERIV(define) xmlRelaxNGDebugDeriv(ctxt, define, node); -/** - * xmlRelaxNGDebugDeriv: - * @ctxt: a Relax-NG validation context - * @define: the current derivation - * @node: the current node - * - * Dump some debug informations about the current derivation state - */ -static void -xmlRelaxNGDebugDeriv(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr define, - xmlNodePtr node) { - xmlRelaxNGValidErrorContext(ctxt, node, NULL); - xmlRelaxNGDumpDefine(stdout, define); + return(ret); } -#endif /** - * xmlRelaxNGNewDeriv: + * xmlRelaxNGElementMatch: * @ctxt: a Relax-NG validation context - * @type: the derivation type - * @c1: the first children - * @c2: the second children + * @define: the definition to check + * @elem: the element * - * Build a new derivated definition at runtime. + * Check if the element matches the definition nameClass * - * Returns the new definition or NULL + * Returns 1 if the element matches, 0 if no, or -1 in case of error */ -static xmlRelaxNGDefinePtr -xmlRelaxNGNewDeriv(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED, - xmlRelaxNGType type, - xmlRelaxNGDefinePtr c1, xmlRelaxNGDefinePtr c2) { - xmlRelaxNGDefinePtr def = NULL; - - def = (xmlRelaxNGDefinePtr) xmlMalloc(sizeof(xmlRelaxNGDefine)); - if (def == NULL) { - TODO - return(NULL); - } - def->type = type; - def->content = c1; - def->cont2 = c2; - def->flags = IS_DYNAMIC; - def->depth = 1; -#ifdef DEBUG_REFEREENCES -printf("new %p:", def); -if (c1 != NULL) printf(" %p(%d)", c1, c1->depth); else printf(" NULL"); -if (c2 != NULL) printf(" %p(%d)\n", c2, c2->depth); else printf(" NULL\n"); -#endif - return(def); -} - -#define FREE_DERIV(d) if (d->flags & IS_DYNAMIC) xmlRelaxNGFreeDeriv(ctxt, d) -#define REF_DERIV(d) if (d->flags & IS_DYNAMIC) d->depth++ -#define REF_DERIV2(d) if (d->flags & IS_DYNAMIC) d->depth += 2 - -/** - * xmlRelaxNGFreeDeriv: - * @ctxt: a Relax-NG validation context - * @def: the derivation - * - * Discard a dynamic derivated definition at runtime. - */ -static void -xmlRelaxNGFreeDeriv(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED, - xmlRelaxNGDefinePtr def) { - if (def == NULL) - return; - if (!(def->flags & IS_DYNAMIC)) - return; - -#ifdef DEBUG_REFEREENCES -printf("free %p:", def); -if (def->content != NULL) printf(" %p(%d)", def->content, def->content->depth); else printf(" NULL"); -if (def->cont2 != NULL) printf(" %p(%d)\n", def->cont2, def->cont2->depth); else printf(" NULL\n"); -#endif +static int +xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define, + xmlNodePtr elem) { + int ret, oldflags; - def->depth --; - if (def->depth > 0) - return; - if ((def->content != NULL) && (def->content->flags & IS_DYNAMIC)) { - def->content->depth--; - if (def->content->depth <= 0) - xmlRelaxNGFreeDeriv(ctxt, def->content); + if (define->name != NULL) { + if (!xmlStrEqual(elem->name, define->name)) { + VALID_ERR3(XML_RELAXNG_ERR_ELEMNAME, define->name, elem->name); + return(0); + } } - if ((def->cont2 != NULL) && (def->cont2->flags & IS_DYNAMIC)) { - def->cont2->depth--; - if (def->cont2->depth <= 0) - xmlRelaxNGFreeDeriv(ctxt, def->cont2); + if ((define->ns != NULL) && (define->ns[0] != 0)) { + if (elem->ns == NULL) { + VALID_ERR2(XML_RELAXNG_ERR_ELEMNONS, + elem->name); + return(0); + } else if (!xmlStrEqual(elem->ns->href, define->ns)) { + VALID_ERR3(XML_RELAXNG_ERR_ELEMWRONGNS, + elem->name, define->ns); + return(0); + } + } else if ((elem->ns != NULL) && (define->ns != NULL) && + (define->name == NULL)) { + VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, + elem->name); + return(0); + } else if ((elem->ns != NULL) && (define->name != NULL)) { + VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, + define->name); + return(0); } - xmlFree(def); -} -/** - * choice: - * @ctxt: a Relax-NG validation context - * @c1: the first children - * @c2: the second children - * - * Build a new choice definition at runtime. - * - * Returns the new definition or NULL - */ -static xmlRelaxNGDefinePtr -choice(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr c1, xmlRelaxNGDefinePtr c2) { - if (c1 == NULL) return(c2); - if (c2 == NULL) return(c1); - if (c1->type == XML_RELAXNG_NOT_ALLOWED) - return(c2); - if (c2->type == XML_RELAXNG_NOT_ALLOWED) - return(c1); - if ((c1->type == XML_RELAXNG_EMPTY) && (c2->type == XML_RELAXNG_EMPTY)) - return(xmlRelaxNGEmptyDeriv); - if (c2->type == XML_RELAXNG_EMPTY) - return(xmlRelaxNGNewDeriv(ctxt, XML_RELAXNG_CHOICE, c2, c1)); - return(xmlRelaxNGNewDeriv(ctxt, XML_RELAXNG_CHOICE, c1, c2)); -} - -/** - * group: - * @ctxt: a Relax-NG validation context - * @type: the derivation type - * @c1: the first children - * @c2: the second children - * - * Build a new group definition at runtime. - * - * Returns the new definition or NULL - */ -static xmlRelaxNGDefinePtr -group(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr c1, xmlRelaxNGDefinePtr c2) { - if (c1 == NULL) return(NULL); - if (c2 == NULL) return(NULL); - if (c1->type == XML_RELAXNG_NOT_ALLOWED) { - FREE_DERIV(c2); - return(xmlRelaxNGNotAllowedDeriv); - } - if (c2->type == XML_RELAXNG_NOT_ALLOWED) { - FREE_DERIV(c1); - return(xmlRelaxNGNotAllowedDeriv); - } - if (c1->type == XML_RELAXNG_EMPTY) - return(c2); - if (c2->type == XML_RELAXNG_EMPTY) - return(c1); - return(xmlRelaxNGNewDeriv(ctxt, XML_RELAXNG_GROUP, c1, c2)); -} - -static xmlRelaxNGDefinePtr -group_flip(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr c1, xmlRelaxNGDefinePtr c2) { - return(group(ctxt, c2, c1)); -} - -/** - * interleave: - * @ctxt: a Relax-NG validation context - * @type: the derivation type - * @c1: the first children - * @c2: the second children - * - * Build a new interleave definition at runtime. - * - * Returns the new definition or NULL - */ -static xmlRelaxNGDefinePtr -interleave(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr c1, xmlRelaxNGDefinePtr c2) { - if (c1 == NULL) return(NULL); - if (c2 == NULL) return(NULL); - if (c1->type == XML_RELAXNG_NOT_ALLOWED) { - FREE_DERIV(c2); - return(xmlRelaxNGNotAllowedDeriv); - } - if (c2->type == XML_RELAXNG_NOT_ALLOWED) { - FREE_DERIV(c1); - return(xmlRelaxNGNotAllowedDeriv); - } - if (c1->type == XML_RELAXNG_EMPTY) - return(c2); - if (c2->type == XML_RELAXNG_EMPTY) - return(c1); - return(xmlRelaxNGNewDeriv(ctxt, XML_RELAXNG_INTERLEAVE, c1, c2)); -} - -static xmlRelaxNGDefinePtr -interleave_flip(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr c1, xmlRelaxNGDefinePtr c2) { - return(interleave(ctxt, c2, c1)); -} - -/** - * after: - * @ctxt: a Relax-NG validation context - * @type: the derivation type - * @c1: the first children - * @c2: the second children - * - * Build a new after definition at runtime. - * - * Returns the new definition or NULL - */ -static xmlRelaxNGDefinePtr -after(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr c1, xmlRelaxNGDefinePtr c2) { - if (c1 == NULL) return(NULL); - if (c2 == NULL) return(NULL); - if (c1->type == XML_RELAXNG_NOT_ALLOWED) { - FREE_DERIV(c2); - return(xmlRelaxNGNotAllowedDeriv); - } - if (c2->type == XML_RELAXNG_NOT_ALLOWED) { - FREE_DERIV(c1); - return(xmlRelaxNGNotAllowedDeriv); - } - return(xmlRelaxNGNewDeriv(ctxt, XML_RELAXNG_AFTER, c1, c2)); -} - -static xmlRelaxNGDefinePtr -after_flip(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr c1, xmlRelaxNGDefinePtr c2) { - return(after(ctxt, c2, c1)); -} - -/** - * oneormore: - * @ctxt: a Relax-NG validation context - * @type: the derivation type - * @c1: the children - * - * Build a new oneormore definition at runtime. - * - * Returns the new definition or NULL - */ -static xmlRelaxNGDefinePtr -oneormore(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGDefinePtr c1) { - if (c1 == NULL) return(NULL); - if (c1->type == XML_RELAXNG_NOT_ALLOWED) - return(xmlRelaxNGNotAllowedDeriv); - return(xmlRelaxNGNewDeriv(ctxt, XML_RELAXNG_ONEORMORE, c1, NULL)); -} - -/** - * apply_after: - * @ctxt: a Relax-NG validation context - * @f: the function to apply - * @arg: the definition - * - * Build a new oneormore definition at runtime. - * - * Returns the new definition or NULL - */ -static xmlRelaxNGDefinePtr -apply_after(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGDerivFunc f, - xmlRelaxNGDefinePtr f_arg2, xmlRelaxNGDefinePtr arg) { - xmlRelaxNGDefinePtr ret; + if (define->nameClass == NULL) + return(1); - if (arg->type == XML_RELAXNG_NOT_ALLOWED) { - ret = xmlRelaxNGNotAllowedDeriv; - } else if (arg->type == XML_RELAXNG_AFTER) { - REF_DERIV(f_arg2); - REF_DERIV(arg->cont2); - REF_DERIV(arg->content); - ret = after(ctxt, arg->content, f(ctxt, f_arg2, arg->cont2)); - } else if (arg->type == XML_RELAXNG_CHOICE) { - REF_DERIV2(f_arg2); - REF_DERIV(arg->content); - REF_DERIV(arg->cont2); - ret = choice(ctxt, - apply_after(ctxt, f, f_arg2, arg->content), - apply_after(ctxt, f, f_arg2, arg->cont2)); + define = define->nameClass; + if (define->type == XML_RELAXNG_EXCEPT) { + xmlRelaxNGDefinePtr list; + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + + list = define->content; + while (list != NULL) { + ret = xmlRelaxNGElementMatch(ctxt, list, elem); + if (ret == 1) { + ctxt->flags = oldflags; + return(0); + } + if (ret < 0) { + ctxt->flags = oldflags; + return(ret); + } + list = list->next; + } + ret = 1; + ctxt->flags = oldflags; + } else if (define->type == XML_RELAXNG_CHOICE) { + xmlRelaxNGDefinePtr list; + + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + + list = define->nameClass; + while (list != NULL) { + ret = xmlRelaxNGElementMatch(ctxt, list, elem); + if (ret == 1) { + ctxt->flags = oldflags; + return(1); + } + if (ret < 0) { + ctxt->flags = oldflags; + return(ret); + } + list = list->next; + } + if (ret != 0) { + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + } else { + ctxt->errNr = 0; + } + ret = 0; + ctxt->flags = oldflags; } else { - fprintf(stderr, "apply_after called on %s\n", xmlRelaxNGDefName(arg)); + TODO + ret = -1; } - FREE_DERIV(f_arg2); - FREE_DERIV(arg); return(ret); } - + /** - * xmlRelaxNGChildDeriv: + * xmlRelaxNGValidateElementEnd: * @ctxt: a Relax-NG validation context - * @define: the definition to verify - * @node: the current node * - * computes the derivation of a node + * Validate the end of the element, implements check that + * there is nothing left not consumed in the element content + * or in the attribute list. * - * Returns the new derivation or NULL in case of error. + * Returns 0 if the validation succeeded or an error code. */ -static xmlRelaxNGDefinePtr -xmlRelaxNGTextDeriv(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGDefinePtr define, - xmlNodePtr node) { - xmlRelaxNGDefinePtr d1, d2, ret; +static int +xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt) { + int ret = 0, i; + xmlRelaxNGValidStatePtr state; - if ((ctxt == NULL) || (define == NULL) || (node == NULL)) - return(NULL); - switch (define->type) { - case XML_RELAXNG_EMPTY: - if (((node->type == XML_TEXT_NODE) || - (node->type == XML_CDATA_SECTION_NODE)) && - (IS_BLANK_NODE(node))) - ret = xmlRelaxNGEmptyDeriv; - else - ret = xmlRelaxNGNotAllowedDeriv; - break; - case XML_RELAXNG_NOT_ALLOWED: - return(define); - case XML_RELAXNG_TEXT: - return(define); - case XML_RELAXNG_CHOICE: - REF_DERIV(define->content); - REF_DERIV(define->cont2); - d1 = xmlRelaxNGTextDeriv(ctxt, define->content, node); - d2 = xmlRelaxNGTextDeriv(ctxt, define->cont2, node); - ret = choice(ctxt, d1, d2); - break; - case XML_RELAXNG_INTERLEAVE: - REF_DERIV2(define->content); - REF_DERIV2(define->cont2); - d1 = interleave(ctxt, - xmlRelaxNGTextDeriv(ctxt, define->content, node), - define->cont2); - d2 = interleave(ctxt, - define->content, - xmlRelaxNGTextDeriv(ctxt, define->cont2, node)); - ret = choice(ctxt, d1, d2); - break; - case XML_RELAXNG_AFTER: - REF_DERIV(define->content); - REF_DERIV(define->cont2); - ret = after(ctxt, - xmlRelaxNGTextDeriv(ctxt, define->content, node), - define->cont2); - break; - case XML_RELAXNG_GROUP: - if (node->type == XML_ATTRIBUTE_NODE) { - REF_DERIV2(define->content); - REF_DERIV2(define->cont2); - d1 = group(ctxt, - xmlRelaxNGTextDeriv(ctxt, define->content, node), - define->cont2); - d2 = group(ctxt, - define->content, - xmlRelaxNGTextDeriv(ctxt, define->cont2, node)); - ret = choice(ctxt, d1, d2); - } else { - REF_DERIV(define->content); - REF_DERIV(define->cont2); - d1 = group(ctxt, - xmlRelaxNGTextDeriv(ctxt, define->content, node), - define->cont2); - if (xmlRelaxNGIsNullable(define->content)) { - REF_DERIV(define->cont2); - ret = choice(ctxt, d1, - xmlRelaxNGTextDeriv(ctxt, define->cont2, node)); - } else - ret = d1; - } - break; - case XML_RELAXNG_ONEORMORE: - REF_DERIV2(define->content); - ret = group(ctxt, - xmlRelaxNGTextDeriv(ctxt, define->content, node), - choice(ctxt, - oneormore(ctxt, define->content), - xmlRelaxNGEmptyDeriv)); - break; - case XML_RELAXNG_DEF: - case XML_RELAXNG_REF: - case XML_RELAXNG_PARENTREF: - case XML_RELAXNG_EXTERNALREF: - return(xmlRelaxNGTextDeriv(ctxt, define->content, node)); - case XML_RELAXNG_LIST: - if ((node->type == XML_TEXT_NODE) || - (node->type == XML_CDATA_SECTION_NODE)) { - int res; - - res = xmlRelaxNGValidateNodeList(ctxt, define, node); - if (res == 0) { - ret = xmlRelaxNGEmptyDeriv; - } else { - ret = xmlRelaxNGNotAllowedDeriv; - } - } else { - ret = xmlRelaxNGNotAllowedDeriv; - } - break; - case XML_RELAXNG_DATATYPE: - if ((node->type == XML_TEXT_NODE) || - (node->type == XML_CDATA_SECTION_NODE)) { - int res; - - res = xmlRelaxNGValidateNodeDatatype(ctxt, define, node); - if (res == 0) { - ret = xmlRelaxNGEmptyDeriv; - } else { - ret = xmlRelaxNGNotAllowedDeriv; - } - } else { - ret = xmlRelaxNGNotAllowedDeriv; - } - break; - case XML_RELAXNG_VALUE: - if ((node->type == XML_TEXT_NODE) || - (node->type == XML_CDATA_SECTION_NODE)) { - int res; - - res = xmlRelaxNGValidateNodeValue(ctxt, define, node); - if (res == 0) { - ret = xmlRelaxNGEmptyDeriv; - } else { - ret = xmlRelaxNGNotAllowedDeriv; - } - } else { - ret = xmlRelaxNGNotAllowedDeriv; - } - break; - case XML_RELAXNG_ELEMENT: - ret = xmlRelaxNGNotAllowedDeriv; - break; - default: - fprintf(stderr, "textDeriv unsupported on %s\n", - xmlRelaxNGDefName(define)); - ret = xmlRelaxNGNotAllowedDeriv; + state = ctxt->state; + if (state->seq != NULL) { + state->seq = xmlRelaxNGSkipIgnored(ctxt, state->seq); + if (state->seq != NULL) { + VALID_ERR3(XML_RELAXNG_ERR_EXTRACONTENT, + state->node->name, state->seq->name); + ret = -1; + } + } + for (i = 0;i < state->nbAttrs;i++) { + if (state->attrs[i] != NULL) { + VALID_ERR3(XML_RELAXNG_ERR_INVALIDATTR, + state->attrs[i]->name, state->node->name); + ret = -1; + } } - FREE_DERIV(define); return(ret); } /** - * xmlRelaxNGStartTagOpenDeriv: + * xmlRelaxNGValidateState: * @ctxt: a Relax-NG validation context * @define: the definition to verify - * @node: the current node * - * computes the start tag derivation of a node + * Validate the current state against the definition * - * Returns the new derivation or NULL in case of error. + * Returns 0 if the validation succeeded or an error code. */ -static xmlRelaxNGDefinePtr -xmlRelaxNGStartTagOpenDeriv(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr define, xmlNodePtr node) { - xmlRelaxNGDefinePtr d1, d2, ret; +static int +xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define) { + xmlNodePtr node; + int ret = 0, i, tmp, oldflags, errNr; + xmlRelaxNGValidStatePtr oldstate, state; - if ((ctxt == NULL) || (define == NULL) || (node == NULL)) - return(NULL); + if (define == NULL) { + VALID_ERR(XML_RELAXNG_ERR_NODEFINE); + return(-1); + } + + if (ctxt->state != NULL) { + node = ctxt->state->seq; + } else { + node = NULL; + } #ifdef DEBUG - printf("start_tag: node: %s\ndef : ", node->name); - xmlRelaxNGDumpDefine(stdout, define); + for (i = 0;i < ctxt->depth;i++) + xmlGenericError(xmlGenericErrorContext, " "); + xmlGenericError(xmlGenericErrorContext, + "Start validating %s ", xmlRelaxNGDefName(define)); + if (define->name != NULL) + xmlGenericError(xmlGenericErrorContext, "%s ", define->name); + if ((node != NULL) && (node->name != NULL)) + xmlGenericError(xmlGenericErrorContext, "on %s\n", node->name); + else + xmlGenericError(xmlGenericErrorContext, "\n"); #endif + ctxt->depth++; switch (define->type) { - case XML_RELAXNG_CHOICE: - REF_DERIV(define->content); - REF_DERIV(define->cont2); - ret = choice(ctxt, - xmlRelaxNGStartTagOpenDeriv(ctxt, define->content, node), - xmlRelaxNGStartTagOpenDeriv(ctxt, define->cont2, node)); - break; - case XML_RELAXNG_INTERLEAVE: - REF_DERIV2(define->content); - REF_DERIV2(define->cont2); - d1 = apply_after(ctxt, interleave_flip, define->cont2, - xmlRelaxNGStartTagOpenDeriv(ctxt, define->content, node)); - d2 = apply_after(ctxt, interleave, define->content, - xmlRelaxNGStartTagOpenDeriv(ctxt, define->cont2, node)); - ret = choice(ctxt, d1, d2); - break; - case XML_RELAXNG_AFTER: - REF_DERIV(define->content); - REF_DERIV(define->cont2); - d2 = xmlRelaxNGStartTagOpenDeriv(ctxt, define->content, node); - ret = apply_after(ctxt, after_flip, define->cont2, d2); + case XML_RELAXNG_EMPTY: + node = xmlRelaxNGSkipIgnored(ctxt, node); + ret = 0; break; - case XML_RELAXNG_GROUP: - REF_DERIV(define->content); - REF_DERIV(define->cont2); - d2 = xmlRelaxNGStartTagOpenDeriv(ctxt, define->content, node); - d1 = apply_after(ctxt, group_flip, define->cont2, d2); - - if (xmlRelaxNGIsNullable(define->content)) { - REF_DERIV(define->cont2); - ret = choice(ctxt, - xmlRelaxNGStartTagOpenDeriv(ctxt, define->cont2, node), - d1); - } else - ret = d1; + case XML_RELAXNG_NOT_ALLOWED: + ret = -1; break; - case XML_RELAXNG_ONEORMORE: - REF_DERIV2(define->content); - d1 = oneormore(ctxt, define->content); - d2 = choice(ctxt, d1, xmlRelaxNGEmptyDeriv); - ret = apply_after(ctxt, group_flip, - d2, - xmlRelaxNGStartTagOpenDeriv(ctxt, - define->content, node)); + case XML_RELAXNG_TEXT: + while ((node != NULL) && + ((node->type == XML_TEXT_NODE) || + (node->type == XML_COMMENT_NODE) || + (node->type == XML_PI_NODE) || + (node->type == XML_CDATA_SECTION_NODE))) + node = node->next; + ctxt->state->seq = node; break; - case XML_RELAXNG_ELEMENT: - if (xmlRelaxNGNsNameMatch(ctxt, define, node, 1) == 1) { -#ifdef debug - printf("start_tag: matched %s\n", node->name); -#endif - if (define->content == NULL) { - /* we may have only attributes */ - ret = after(ctxt, xmlRelaxNGEmptyDeriv, - xmlRelaxNGEmptyDeriv); - } else { - REF_DERIV(define->content); - ret = after(ctxt, define->content, xmlRelaxNGEmptyDeriv); + case XML_RELAXNG_ELEMENT: + errNr = ctxt->errNr; + node = xmlRelaxNGSkipIgnored(ctxt, node); + if (node == NULL) { + VALID_ERR2(XML_RELAXNG_ERR_NOELEM, define->name); + ret = -1; + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + break; + } + if (node->type != XML_ELEMENT_NODE) { + VALID_ERR(XML_RELAXNG_ERR_NOTELEM); + ret = -1; + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + break; + } + /* + * This node was already validated successfully against + * this definition. + */ + if (node->_private == define) { + ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt, node->next); + break; + } + + ret = xmlRelaxNGElementMatch(ctxt, define, node); + if (ret <= 0) { + ret = -1; + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + break; + } + ret = 0; + if (ctxt->errNr != 0) { + while ((ctxt->err != NULL) && + (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME) && + (xmlStrEqual(ctxt->err->arg2, node->name))) || + (ctxt->err->err == XML_RELAXNG_ERR_NOELEM) || + (ctxt->err->err == XML_RELAXNG_ERR_NOTELEM))) + xmlRelaxNGValidErrorPop(ctxt); + } + errNr = ctxt->errNr; + + state = xmlRelaxNGNewValidState(ctxt, node); + if (state == NULL) { + ret = -1; + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + break; + } + + oldstate = ctxt->state; + ctxt->state = state; + if (define->attrs != NULL) { + tmp = xmlRelaxNGValidateAttributeList(ctxt, define->attrs); + if (tmp != 0) { + ret = -1; + VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name); } - } else { - ret = xmlRelaxNGNotAllowedDeriv; } - break; - case XML_RELAXNG_DEF: - case XML_RELAXNG_REF: - case XML_RELAXNG_PARENTREF: - case XML_RELAXNG_EXTERNALREF: - return(xmlRelaxNGStartTagOpenDeriv(ctxt, define->content, node)); - default: - ret = xmlRelaxNGNotAllowedDeriv; - } - FREE_DERIV(define); - return(ret); -} + if (define->content != NULL) { + tmp = xmlRelaxNGValidateDefinitionList(ctxt, define->content); + if (tmp != 0) { + ret = -1; + VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID, node->name); + } + } + if (ctxt->states != NULL) { + tmp = -1; -/** - * xmlRelaxNGAttDeriv: - * @ctxt: a Relax-NG validation context - * @define: the definition to verify - * @node: the current node - * - * computes the start tag derivation of a node - * - * Returns the new derivation or NULL in case of error. - */ -static xmlRelaxNGDefinePtr -xmlRelaxNGAttDeriv(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr define, xmlNodePtr node) { - xmlRelaxNGDefinePtr ret; + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + + for (i = 0;i < ctxt->states->nbState;i++) { + state = ctxt->states->tabState[i]; + ctxt->state = state; + + if (xmlRelaxNGValidateElementEnd(ctxt) == 0) + tmp = 0; + xmlRelaxNGFreeValidState(state); + } + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->flags = oldflags; + ctxt->states = NULL; + if ((ret == 0) && (tmp == -1)) + ret = -1; + } else { + state = ctxt->state; + if (ret == 0) + ret = xmlRelaxNGValidateElementEnd(ctxt); + xmlRelaxNGFreeValidState(state); + } + ctxt->state = oldstate; + if (oldstate != NULL) + oldstate->seq = xmlRelaxNGSkipIgnored(ctxt, node->next); + if (ret == 0) { + node->_private = define; + } + if (ret != 0) { + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + } else { + ctxt->errNr = errNr; + } - if ((ctxt == NULL) || (define == NULL) || (node == NULL)) - return(NULL); #ifdef DEBUG - printf("att: node: %s\ndef : ", node->name); - xmlRelaxNGDumpDefine(stdout, define); + xmlGenericError(xmlGenericErrorContext, + "xmlRelaxNGValidateDefinition(): validated %s : %d", + node->name, ret); + if (oldstate == NULL) + xmlGenericError(xmlGenericErrorContext, ": no state\n"); + else if (oldstate->seq == NULL) + xmlGenericError(xmlGenericErrorContext, ": done\n"); + else if (oldstate->seq->type == XML_ELEMENT_NODE) + xmlGenericError(xmlGenericErrorContext, ": next elem %s\n", + oldstate->seq->name); + else + xmlGenericError(xmlGenericErrorContext, ": next %s %d\n", + oldstate->seq->name, oldstate->seq->type); #endif - switch (define->type) { - case XML_RELAXNG_CHOICE: - if (node->type != XML_ATTRIBUTE_NODE) - ret = xmlRelaxNGNotAllowedDeriv; - else { - REF_DERIV(define->content); - REF_DERIV(define->cont2); - ret = choice(ctxt, - xmlRelaxNGAttDeriv(ctxt, define->content, node), - xmlRelaxNGAttDeriv(ctxt, define->cont2, node)); - } break; - case XML_RELAXNG_INTERLEAVE: - if (node->type != XML_ATTRIBUTE_NODE) - ret = xmlRelaxNGNotAllowedDeriv; - else { - REF_DERIV2(define->content); - REF_DERIV2(define->cont2); - ret = choice(ctxt, - interleave(ctxt, - xmlRelaxNGAttDeriv(ctxt, define->content, node), - define->cont2), - interleave(ctxt, - define->content, - xmlRelaxNGAttDeriv(ctxt, define->cont2, node))); + case XML_RELAXNG_OPTIONAL: { + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state); + ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content); + if (ret != 0) { + if (ctxt->state != NULL) + xmlRelaxNGFreeValidState(ctxt->state); + ctxt->state = oldstate; + ctxt->flags = oldflags; + ret = 0; + break; } - break; - case XML_RELAXNG_AFTER: - if (node->type != XML_ATTRIBUTE_NODE) - ret = xmlRelaxNGNotAllowedDeriv; - else { - REF_DERIV(define->content); - REF_DERIV(define->cont2); - ret = after(ctxt, - xmlRelaxNGAttDeriv(ctxt, define->content, node), - define->cont2); + if (ctxt->states != NULL) { + xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate); + } else { + ctxt->states = xmlRelaxNGNewStates(ctxt, 1); + if (ctxt->states == NULL) { + xmlRelaxNGFreeValidState(oldstate); + ctxt->flags = oldflags; + ret = -1; + break; + } + xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate); + xmlRelaxNGAddStates(ctxt, ctxt->states, ctxt->state); + ctxt->state = NULL; } + ctxt->flags = oldflags; + ret = 0; break; - case XML_RELAXNG_GROUP: - if (node->type != XML_ATTRIBUTE_NODE) - ret = xmlRelaxNGNotAllowedDeriv; - else { - REF_DERIV2(define->content); - REF_DERIV2(define->cont2); - ret = choice(ctxt, - group(ctxt, - xmlRelaxNGAttDeriv(ctxt, define->content, node), - define->cont2), - group(ctxt, - define->content, - xmlRelaxNGAttDeriv(ctxt, define->cont2, node))); + } + case XML_RELAXNG_ONEORMORE: + ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content); + if (ret != 0) { + break; } - break; - case XML_RELAXNG_ONEORMORE: - if (node->type != XML_ATTRIBUTE_NODE) - ret = xmlRelaxNGNotAllowedDeriv; - else { - REF_DERIV(define->content); - REF_DERIV(define); - ret = group(ctxt, - xmlRelaxNGAttDeriv(ctxt, define->content, node), - choice(ctxt, - define, xmlRelaxNGEmptyDeriv)); + /* no break on purpose */ + case XML_RELAXNG_ZEROORMORE: { + int progress; + xmlRelaxNGStatesPtr states = NULL, res = NULL; + int base, j; + + res = xmlRelaxNGNewStates(ctxt, 1); + if (res == NULL) { + ret = -1; + break; } - break; - case XML_RELAXNG_DEF: - case XML_RELAXNG_REF: - case XML_RELAXNG_PARENTREF: - case XML_RELAXNG_EXTERNALREF: - return(xmlRelaxNGAttDeriv(ctxt, define->content, node)); - case XML_RELAXNG_ATTRIBUTE: - if (node->type != XML_ATTRIBUTE_NODE) - ret = xmlRelaxNGNotAllowedDeriv; - else if (xmlRelaxNGNsNameMatch(ctxt, define, node, 0)) { - xmlChar *value; - int res; - -#ifdef DEBUG - printf("attr: matched %s\n", node->name); -#endif - ctxt->state->node = node; - value = xmlNodeListGetString(node->doc, node->children, 1); - ctxt->state->value = value; - res = xmlRelaxNGValidateValueContent(ctxt, define->content); - if (ctxt->state->value != NULL) - value = ctxt->state->value; - if (value != NULL) - xmlFree(value); - ctxt->state->value = NULL; - if (res == 0) { - ret = xmlRelaxNGEmptyDeriv; + /* + * All the input states are also exit states + */ + if (ctxt->state != NULL) { + xmlRelaxNGAddStates(ctxt, res, + xmlRelaxNGCopyValidState(ctxt, ctxt->state)); + } else { + for (j = 0;j < ctxt->states->nbState;j++) { + xmlRelaxNGAddStates(ctxt, res, + xmlRelaxNGCopyValidState(ctxt, + ctxt->states->tabState[j])); + } + } + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + do { + progress = 0; + base = res->nbState; + + if (ctxt->states != NULL) { + states = ctxt->states; + for (i = 0;i < states->nbState;i++) { + ctxt->state = states->tabState[i]; + ctxt->states = NULL; + ret = xmlRelaxNGValidateDefinitionList(ctxt, + define->content); + if (ret == 0) { + if (ctxt->state != NULL) { + tmp = xmlRelaxNGAddStates(ctxt, res, + ctxt->state); + ctxt->state = NULL; + if (tmp == 1) + progress = 1; + } else if (ctxt->states != NULL) { + for (j = 0;j < ctxt->states->nbState;j++) { + tmp = xmlRelaxNGAddStates(ctxt, res, + ctxt->states->tabState[j]); + if (tmp == 1) + progress = 1; + } + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; + } + } else { + if (ctxt->state != NULL) { + xmlRelaxNGFreeValidState(ctxt->state); + ctxt->state = NULL; + } + } + } } else { - ret = xmlRelaxNGNotAllowedDeriv; + ret = xmlRelaxNGValidateDefinitionList(ctxt, + define->content); + if (ret != 0) { + xmlRelaxNGFreeValidState(ctxt->state); + ctxt->state = NULL; + } else { + base = res->nbState; + if (ctxt->state != NULL) { + tmp = xmlRelaxNGAddStates(ctxt, res, + ctxt->state); + ctxt->state = NULL; + if (tmp == 1) + progress = 1; + } else if (ctxt->states != NULL) { + for (j = 0;j < ctxt->states->nbState;j++) { + tmp = xmlRelaxNGAddStates(ctxt, res, + ctxt->states->tabState[j]); + if (tmp == 1) + progress = 1; + } + if (states == NULL) { + states = ctxt->states; + } else { + xmlRelaxNGFreeStates(ctxt, ctxt->states); + } + ctxt->states = NULL; + } + } } - } else - ret = xmlRelaxNGNotAllowedDeriv; + if (progress) { + /* + * Collect all the new nodes added at that step + * and make them the new node set + */ + if (res->nbState - base == 1) { + ctxt->state = xmlRelaxNGCopyValidState(ctxt, + res->tabState[base]); + } else { + if (states == NULL) { + xmlRelaxNGNewStates(ctxt, res->nbState - base); + } + states->nbState = 0; + for (i = base;i < res->nbState;i++) + xmlRelaxNGAddStates(ctxt, states, + xmlRelaxNGCopyValidState(ctxt, + res->tabState[i])); + ctxt->states = states; + } + } + } while (progress == 1); + if (states != NULL) { + xmlRelaxNGFreeStates(ctxt, states); + } + ctxt->states = res; + ctxt->flags = oldflags; + ret = 0; break; - default: - ret = xmlRelaxNGNotAllowedDeriv; - } - FREE_DERIV(define); - return(ret); -} - -/** - * xmlRelaxNGAttsDeriv: - * @ctxt: a Relax-NG validation context - * @define: the definition to verify - * @nodes: the current attribute list - * - * computes the start tag derivation of a node - * - * Returns the new derivation or NULL in case of error. - */ -static xmlRelaxNGDefinePtr -xmlRelaxNGAttsDeriv(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr define, xmlNodePtr nodes) { - xmlRelaxNGDefinePtr p; + } + case XML_RELAXNG_CHOICE: { + xmlRelaxNGDefinePtr list = define->content; + xmlRelaxNGStatesPtr states = NULL; - if (nodes == NULL) - return(define); - p = define; - while (nodes != NULL) { - if (nodes->type != XML_ATTRIBUTE_NODE) - return(xmlRelaxNGNotAllowedDeriv); - p = xmlRelaxNGAttDeriv(ctxt, p, nodes); - nodes = nodes->next; - } - return(p); -} - -/** - * xmlRelaxNGEndTagDeriv: - * @ctxt: a Relax-NG validation context - * @define: the definition to verify - * @node: the current node - * - * computes the start tag close derivation of a node - * - * Returns the new derivation or NULL in case of error. - */ -static xmlRelaxNGDefinePtr -xmlRelaxNGEndTagDeriv(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr define, xmlNodePtr node) { - xmlRelaxNGDefinePtr ret; + oldflags = ctxt->flags; + errNr = ctxt->errNr; + ctxt->flags |= FLAGS_IGNORABLE; + node = xmlRelaxNGSkipIgnored(ctxt, node); - if ((ctxt == NULL) || (define == NULL) || (node == NULL)) - return(NULL); -#ifdef DEBUG - printf("end_tag: node: %s\ndef : ", node->name); - xmlRelaxNGDumpDefine(stdout, define); -#endif - switch (define->type) { - case XML_RELAXNG_CHOICE: - REF_DERIV(define->content); - REF_DERIV(define->cont2); - ret = choice(ctxt, - xmlRelaxNGEndTagDeriv(ctxt, define->content, node), - xmlRelaxNGEndTagDeriv(ctxt, define->cont2, node)); + while (list != NULL) { + oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state); + ret = xmlRelaxNGValidateDefinition(ctxt, list); + if (ret == 0) { + if (states == NULL) { + states = xmlRelaxNGNewStates(ctxt, 1); + } + if (ctxt->state != NULL) { + xmlRelaxNGAddStates(ctxt, states, ctxt->state); + } else if (ctxt->states != NULL) { + for (i = 0;i < ctxt->states->nbState;i++) { + xmlRelaxNGAddStates(ctxt, states, + ctxt->states->tabState[i]); + } + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; + } + } else { + xmlRelaxNGFreeValidState(ctxt->state); + } + ctxt->state = oldstate; + list = list->next; + } + if (states != NULL) { + xmlRelaxNGFreeValidState(oldstate); + ctxt->states = states; + ctxt->state = NULL; + ret = 0; + } else { + ctxt->states = NULL; + } + ctxt->flags = oldflags; + if (ret != 0) { + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + } else if ((ctxt->flags & FLAGS_IGNORABLE) == 0) { + ctxt->errNr = errNr; + } break; - case XML_RELAXNG_AFTER: - if (xmlRelaxNGIsNullable(define->content)) { - REF_DERIV(define->cont2); - ret = define->cont2; - } else - ret = xmlRelaxNGNotAllowedDeriv; + } + case XML_RELAXNG_DEF: + case XML_RELAXNG_GROUP: + ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content); break; - case XML_RELAXNG_DEF: - case XML_RELAXNG_REF: - case XML_RELAXNG_PARENTREF: - case XML_RELAXNG_EXTERNALREF: - return(xmlRelaxNGEndTagDeriv(ctxt, define->content, node)); - default: - ret = xmlRelaxNGNotAllowedDeriv; - } - FREE_DERIV(define); - return(ret); -} - -/** - * xmlRelaxNGStartTagCloseDeriv: - * @ctxt: a Relax-NG validation context - * @define: the definition to verify - * @node: the current node - * - * computes the start tag close derivation of a node - * - * Returns the new derivation or NULL in case of error. - */ -static xmlRelaxNGDefinePtr -xmlRelaxNGStartTagCloseDeriv(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr define, xmlNodePtr node) { - xmlRelaxNGDefinePtr ret; - - if ((ctxt == NULL) || (define == NULL) || (node == NULL)) - return(NULL); -#ifdef DEBUG - printf("start_tag_close: node: %s\ndef : ", node->name); - xmlRelaxNGDumpDefine(stdout, define); -#endif - switch (define->type) { - case XML_RELAXNG_CHOICE: - REF_DERIV(define->content); - REF_DERIV(define->cont2); - ret = choice(ctxt, - xmlRelaxNGStartTagCloseDeriv(ctxt, define->content, node), - xmlRelaxNGStartTagCloseDeriv(ctxt, define->cont2, node)); + case XML_RELAXNG_INTERLEAVE: + ret = xmlRelaxNGValidateInterleave(ctxt, define); break; - case XML_RELAXNG_INTERLEAVE: - REF_DERIV(define->content); - REF_DERIV(define->cont2); - ret = interleave(ctxt, - xmlRelaxNGStartTagCloseDeriv(ctxt, define->content, node), - xmlRelaxNGStartTagCloseDeriv(ctxt, define->cont2, node)); + case XML_RELAXNG_ATTRIBUTE: + ret = xmlRelaxNGValidateAttribute(ctxt, define); break; - case XML_RELAXNG_AFTER: - REF_DERIV(define->content); - REF_DERIV(define->cont2); - ret = after(ctxt, - xmlRelaxNGStartTagCloseDeriv(ctxt, define->content, node), - define->cont2); + case XML_RELAXNG_NOOP: + case XML_RELAXNG_REF: + case XML_RELAXNG_PARENTREF: + case XML_RELAXNG_EXTERNALREF: + ret = xmlRelaxNGValidateDefinition(ctxt, define->content); break; - case XML_RELAXNG_GROUP: - REF_DERIV(define->content); - REF_DERIV(define->cont2); - ret = group(ctxt, - xmlRelaxNGStartTagCloseDeriv(ctxt, define->content, node), - xmlRelaxNGStartTagCloseDeriv(ctxt, define->cont2, node)); + case XML_RELAXNG_DATATYPE: { + xmlNodePtr child; + xmlChar *content = NULL; + + child = node; + while (child != NULL) { + if (child->type == XML_ELEMENT_NODE) { + VALID_ERR2(XML_RELAXNG_ERR_DATAELEM, + node->parent->name); + ret = -1; + break; + } else if ((child->type == XML_TEXT_NODE) || + (child->type == XML_CDATA_SECTION_NODE)) { + content = xmlStrcat(content, child->content); + } + /* TODO: handle entities ... */ + child = child->next; + } + if (ret == -1) { + if (content != NULL) + xmlFree(content); + break; + } + if (content == NULL) { + content = xmlStrdup(BAD_CAST ""); + if (content == NULL) { + VALID_ERR(XML_RELAXNG_ERR_MEMORY); + ret = -1; + break; + } + } + ret = xmlRelaxNGValidateDatatype(ctxt, content, define); + if (ret == -1) { + VALID_ERR2(XML_RELAXNG_ERR_DATATYPE, define->name); + } else if (ret == 0) { + ctxt->state->seq = NULL; + } + if (content != NULL) + xmlFree(content); + break; + } + case XML_RELAXNG_VALUE: { + xmlChar *content = NULL; + xmlChar *oldvalue; + xmlNodePtr child; + + child = node; + while (child != NULL) { + if (child->type == XML_ELEMENT_NODE) { + VALID_ERR2(XML_RELAXNG_ERR_VALELEM, + node->parent->name); + ret = -1; + break; + } else if ((child->type == XML_TEXT_NODE) || + (child->type == XML_CDATA_SECTION_NODE)) { + content = xmlStrcat(content, child->content); + } + /* TODO: handle entities ... */ + child = child->next; + } + if (ret == -1) { + if (content != NULL) + xmlFree(content); + break; + } + if (content == NULL) { + content = xmlStrdup(BAD_CAST ""); + if (content == NULL) { + VALID_ERR(XML_RELAXNG_ERR_MEMORY); + ret = -1; + break; + } + } + oldvalue = ctxt->state->value; + ctxt->state->value = content; + ret = xmlRelaxNGValidateValue(ctxt, define); + ctxt->state->value = oldvalue; + if (ret == -1) { + VALID_ERR2(XML_RELAXNG_ERR_VALUE, define->name); + } else if (ret == 0) { + ctxt->state->seq = NULL; + } + if (content != NULL) + xmlFree(content); break; - case XML_RELAXNG_ONEORMORE: - REF_DERIV(define->content); - ret = oneormore(ctxt, - xmlRelaxNGStartTagCloseDeriv(ctxt, define->content, node)); + } + case XML_RELAXNG_LIST: { + xmlChar *content; + xmlNodePtr child; + xmlChar *oldvalue, *oldendvalue; + int len; + + /* + * Make sure it's only text nodes + */ + + content = NULL; + child = node; + while (child != NULL) { + if (child->type == XML_ELEMENT_NODE) { + VALID_ERR2(XML_RELAXNG_ERR_LISTELEM, + node->parent->name); + ret = -1; + break; + } else if ((child->type == XML_TEXT_NODE) || + (child->type == XML_CDATA_SECTION_NODE)) { + content = xmlStrcat(content, child->content); + } + /* TODO: handle entities ... */ + child = child->next; + } + if (ret == -1) { + if (content != NULL) + xmlFree(content); + break; + } + if (content == NULL) { + content = xmlStrdup(BAD_CAST ""); + if (content == NULL) { + VALID_ERR(XML_RELAXNG_ERR_MEMORY); + ret = -1; + break; + } + } + len = xmlStrlen(content); + oldvalue = ctxt->state->value; + oldendvalue = ctxt->state->endvalue; + ctxt->state->value = content; + ctxt->state->endvalue = content + len; + ret = xmlRelaxNGValidateValue(ctxt, define); + ctxt->state->value = oldvalue; + ctxt->state->endvalue = oldendvalue; + if (ret == -1) { + VALID_ERR(XML_RELAXNG_ERR_LIST); + } else if ((ret == 0) && (node != NULL)) { + ctxt->state->seq = node->next; + } + if (content != NULL) + xmlFree(content); break; - case XML_RELAXNG_ATTRIBUTE: - ret = xmlRelaxNGNotAllowedDeriv; + } + case XML_RELAXNG_START: + case XML_RELAXNG_EXCEPT: + case XML_RELAXNG_PARAM: + TODO + ret = -1; break; - - case XML_RELAXNG_DEF: - case XML_RELAXNG_REF: - case XML_RELAXNG_PARENTREF: - case XML_RELAXNG_EXTERNALREF: - return(xmlRelaxNGStartTagCloseDeriv(ctxt, define->content, node)); - default: - return(define); } - FREE_DERIV(define); + ctxt->depth--; +#ifdef DEBUG + for (i = 0;i < ctxt->depth;i++) + xmlGenericError(xmlGenericErrorContext, " "); + xmlGenericError(xmlGenericErrorContext, + "Validating %s ", xmlRelaxNGDefName(define)); + if (define->name != NULL) + xmlGenericError(xmlGenericErrorContext, "%s ", define->name); + if (ret == 0) + xmlGenericError(xmlGenericErrorContext, "suceeded\n"); + else + xmlGenericError(xmlGenericErrorContext, "failed\n"); +#endif return(ret); } /** - * xmlRelaxNGChildrenDeriv: + * xmlRelaxNGValidateDefinition: * @ctxt: a Relax-NG validation context * @define: the definition to verify - * @node: the current node * - * computes the children derivation of a node + * Validate the current node lists against the definition * - * Returns the new derivation or NULL in case of error. + * Returns 0 if the validation succeeded or an error code. */ -static xmlRelaxNGDefinePtr -xmlRelaxNGChildrenDeriv(xmlRelaxNGValidCtxtPtr ctxt, - xmlRelaxNGDefinePtr define, xmlNodePtr node) { - xmlRelaxNGDefinePtr res = NULL; - xmlNodePtr nodes; +static int +xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define) { + xmlRelaxNGStatesPtr states, res; + int i, j, k, ret, oldflags; - if ((ctxt == NULL) || (define == NULL) || (node == NULL)) - return(NULL); -#ifdef DEBUG - printf("children: node: %s\ndef : ", node->name); - xmlRelaxNGDumpDefine(stdout, define); -#endif - nodes = node->children; - if (nodes == NULL) { - nodes = xmlNewText(BAD_CAST ""); - nodes->parent = node; - REF_DERIV2(define); - res = xmlRelaxNGChildDeriv(ctxt, define, nodes); - res = choice(ctxt, define, res); - xmlFreeNode(nodes); - } else if (((nodes->type == XML_TEXT_NODE) || - (nodes->type == XML_CDATA_SECTION_NODE)) && - (nodes->next == NULL)) { - REF_DERIV(define); - res = xmlRelaxNGChildDeriv(ctxt, define, nodes); - if (IS_BLANK_NODE(nodes)) { - REF_DERIV(define); - res = choice(ctxt, define, res); + /* + * We should NOT have both ctxt->state and ctxt->states + */ + if ((ctxt->state != NULL) && (ctxt->states != NULL)) { + TODO + xmlRelaxNGFreeValidState(ctxt->state); + ctxt->state = NULL; + } + + if ((ctxt->states == NULL) || (ctxt->states->nbState == 1)) { + if (ctxt->states != NULL) { + ctxt->state = ctxt->states->tabState[0]; + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; } - } else { - res = define; - REF_DERIV(define); - while (nodes != NULL) { - nodes = xmlRelaxNGSkipIgnored(ctxt, nodes); - if (nodes != NULL) { -#ifdef DEBUG - printf("children: node: %s cur %s\ndef : ", - node->name, nodes->name); - xmlRelaxNGDumpDefine(stdout, res); -#endif - res = xmlRelaxNGChildDeriv(ctxt, res, nodes); - if (res == xmlRelaxNGNotAllowedDeriv) - break; - if ((nodes->type == XML_TEXT_NODE) || - (nodes->type == XML_CDATA_SECTION_NODE)) { - /* - * Adjacent text/cdata nodes are collapsed at the - * text node validation test - */ - while ((nodes != NULL) && - (nodes->type != XML_ELEMENT_NODE)) - nodes = nodes->next; + ret = xmlRelaxNGValidateState(ctxt, define); + if ((ctxt->state != NULL) && (ctxt->states != NULL)) { + TODO + xmlRelaxNGFreeValidState(ctxt->state); + ctxt->state = NULL; + } + if ((ctxt->states != NULL) && (ctxt->states->nbState == 1)) { + ctxt->state = ctxt->states->tabState[0]; + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; + } + return(ret); + } + + states = ctxt->states; + ctxt->states = NULL; + res = NULL; + j = 0; + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + for (i = 0;i < states->nbState;i++) { + ctxt->state = states->tabState[i]; + ctxt->states = NULL; + ret = xmlRelaxNGValidateState(ctxt, define); + /* + * We should NOT have both ctxt->state and ctxt->states + */ + if ((ctxt->state != NULL) && (ctxt->states != NULL)) { + TODO + xmlRelaxNGFreeValidState(ctxt->state); + ctxt->state = NULL; + } + if (ret == 0) { + if (ctxt->states == NULL) { + if (res != NULL) { + /* add the state to the container */ + xmlRelaxNGAddStates(ctxt, res, ctxt->state); + ctxt->state = NULL; + } else { + /* add the state directly in states */ + states->tabState[j++] = ctxt->state; + ctxt->state = NULL; + } + } else { + if (res == NULL) { + /* make it the new container and copy other results */ + res = ctxt->states; + ctxt->states = NULL; + for (k = 0;k < j;k++) + xmlRelaxNGAddStates(ctxt, res, states->tabState[k]); } else { - nodes = nodes->next; + /* add all the new results to res and reff the container */ + for (k = 0;k < ctxt->states->nbState;k++) + xmlRelaxNGAddStates(ctxt, res, + ctxt->states->tabState[k]); + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; } } + } else { + if (ctxt->state != NULL) { + xmlRelaxNGFreeValidState(ctxt->state); + ctxt->state = NULL; + } else if (ctxt->states != NULL) { + for (k = 0;k < ctxt->states->nbState;k++) + xmlRelaxNGFreeValidState(ctxt->states->tabState[k]); + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; + } } } - FREE_DERIV(define); - return(res); -} - - -/** - * xmlRelaxNGChildDeriv: - * @ctxt: a Relax-NG validation context - * @define: the definition to verify - * @node: the current node - * - * computes the derivation of a node - * - * Returns the new derivation or NULL in case of error. - */ -static xmlRelaxNGDefinePtr -xmlRelaxNGChildDeriv(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGDefinePtr define, - xmlNodePtr node) { - xmlRelaxNGDefinePtr temp; - - if ((ctxt == NULL) || (define == NULL) || (node == NULL)) - return(NULL); -#ifdef DEBUG - printf("child: node: %s\ndef : ", node->name); - xmlRelaxNGDumpDefine(stdout, define); -#endif - if ((node->type == XML_TEXT_NODE) || - (node->type == XML_CDATA_SECTION_NODE)) - return(xmlRelaxNGTextDeriv(ctxt, define, node)); - else if (node->type == XML_ELEMENT_NODE) { - temp = xmlRelaxNGStartTagOpenDeriv(ctxt, define, node); - temp = xmlRelaxNGAttsDeriv(ctxt, temp, (xmlNodePtr) node->properties); - temp = xmlRelaxNGStartTagCloseDeriv(ctxt, temp, node); - temp = xmlRelaxNGChildrenDeriv(ctxt, temp, node); - temp = xmlRelaxNGEndTagDeriv(ctxt, temp, node); - return(temp); + ctxt->flags = oldflags; + if (res != NULL) { + xmlRelaxNGFreeStates(ctxt, states); + ctxt->states = res; + ret = 0; + } else if (j > 1) { + states->nbState = j; + ctxt->states = states; + ret =0; + } else if (j == 1) { + ctxt->state = states->tabState[0]; + xmlRelaxNGFreeStates(ctxt, states); + ret = 0; + } else { + ret = -1; + xmlRelaxNGFreeStates(ctxt, states); + if (ctxt->states != NULL) { + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; + } + } + if ((ctxt->state != NULL) && (ctxt->states != NULL)) { + TODO + xmlRelaxNGFreeValidState(ctxt->state); + ctxt->state = NULL; } - TODO - return(NULL); -} - -/** - * xmlRelaxNGMatches: - * @ctxt: a Relax-NG validation context - * @define: the definition to verify - * @node: the current node - * - * Check if the node matches the definition - * - * Returns 1 if yes, 0 if no and -1 in case of error - */ -static int -xmlRelaxNGMatches(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGDefinePtr define, - xmlNodePtr node) { - xmlRelaxNGDefinePtr deriv; - int ret; - - deriv = xmlRelaxNGChildDeriv(ctxt, define, node); - ret = xmlRelaxNGIsNullable(deriv); - FREE_DERIV(deriv); return(ret); } -/************************************************************************ - * * - * Validation interfaces * - * * - ************************************************************************/ - /** * xmlRelaxNGValidateDocument: * @ctxt: a Relax-NG validation context @@ -8164,6 +8247,7 @@ xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc) { xmlRelaxNGPtr schema; xmlRelaxNGGrammarPtr grammar; xmlRelaxNGValidStatePtr state; + xmlNodePtr node; if ((ctxt == NULL) || (ctxt->schema == NULL) || (doc == NULL)) return(-1); @@ -8176,32 +8260,48 @@ xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc) { } state = xmlRelaxNGNewValidState(ctxt, NULL); ctxt->state = state; -#if USE_DIRECT ret = xmlRelaxNGValidateDefinition(ctxt, grammar->start); - state = ctxt->state; - if ((state != NULL) && (state->seq != NULL)) { - xmlNodePtr node; - + if ((ctxt->state != NULL) && (state->seq != NULL)) { + state = ctxt->state; node = state->seq; node = xmlRelaxNGSkipIgnored(ctxt, node); if (node != NULL) { - VALID_ERR(XML_RELAXNG_ERR_EXTRADATA); - ret = -1; + if (ret != -1) { + VALID_ERR(XML_RELAXNG_ERR_EXTRADATA); + ret = -1; + } + } + } else if (ctxt->states != NULL) { + int i; + int tmp = -1; + + for (i = 0;i < ctxt->states->nbState;i++) { + state = ctxt->states->tabState[i]; + node = state->seq; + node = xmlRelaxNGSkipIgnored(ctxt, node); + if (node == NULL) + tmp = 0; + xmlRelaxNGFreeValidState(state); + } + if (tmp == -1) { + if (ret != -1) { + VALID_ERR(XML_RELAXNG_ERR_EXTRADATA); + ret = -1; + } } } -#else - ret = xmlRelaxNGMatches(ctxt, grammar->start, xmlDocGetRootElement(doc)); - if (ret == 1) - ret = 0; - else - ret = -1; -#endif xmlRelaxNGFreeValidState(state); - ctxt->state = NULL; + if (ret != 0) + xmlRelaxNGDumpValidError(ctxt); return(ret); } +/************************************************************************ + * * + * Validation interfaces * + * * + ************************************************************************/ /** * xmlRelaxNGNewValidCtxt: * @schema: a precompiled XML RelaxNGs @@ -8217,7 +8317,7 @@ xmlRelaxNGNewValidCtxt(xmlRelaxNGPtr schema) { ret = (xmlRelaxNGValidCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGValidCtxt)); if (ret == NULL) { xmlGenericError(xmlGenericErrorContext, - "Failed to allocate new schama validation context\n"); + "Failed to allocate new schema validation context\n"); return (NULL); } memset(ret, 0, sizeof(xmlRelaxNGValidCtxt)); @@ -8241,6 +8341,8 @@ void xmlRelaxNGFreeValidCtxt(xmlRelaxNGValidCtxtPtr ctxt) { if (ctxt == NULL) return; + if (ctxt->states != NULL) + xmlRelaxNGFreeStates(ctxt, ctxt->states); if (ctxt->errTab != NULL) xmlFree(ctxt->errTab); xmlFree(ctxt); diff --git a/result/relaxng/spec1_err b/result/relaxng/spec1_err index e3b2ee88..b9f01ac3 100644 --- a/result/relaxng/spec1_err +++ b/result/relaxng/spec1_err @@ -1,82 +1,12 @@ RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element element, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element attribute, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element group, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element interleave, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element choice, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element optional, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element zeroOrMore, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element oneOrMore, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element list, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element mixed, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element ref, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element parentRef, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element empty, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element text, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element value, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element data, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element notAllowed, got nothing -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element externalRef, got nothing +Expecting an element , got nothing +RNG validity error: file ./test/relaxng/spec1.rng line 7 element documentation +Invalid sequence in interleave RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting an element grammar, got nothing +Expecting an element , got nothing RNG validity error: file ./test/relaxng/spec1.rng line 7 element documentation Invalid sequence in interleave RNG validity error: file ./test/relaxng/spec1.rng line 7 element documentation Element element failed to validate content -RNG validity error: file ./test/relaxng/spec1.rng line 7 element documentation -Element element has extra content: documentation RNG validity error: file ./test/relaxng/spec1.rng line 6 element element Expecting element attribute, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element group, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element interleave, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element choice, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element optional, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element zeroOrMore, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element oneOrMore, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element list, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element mixed, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element ref, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element parentRef, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element empty, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element text, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element value, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element data, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element notAllowed, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element externalRef, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Expecting element grammar, got element -RNG validity error: file ./test/relaxng/spec1.rng line 6 element element -Extra data in the document diff --git a/result/relaxng/tutor10_1_4.err b/result/relaxng/tutor10_1_4.err index adee0071..862ed3a7 100644 --- a/result/relaxng/tutor10_1_4.err +++ b/result/relaxng/tutor10_1_4.err @@ -1,4 +1,2 @@ RNG validity error: file ./test/relaxng/tutor10_1_4.xml line 1 element foo Expecting a namespace for element foo -RNG validity error: file ./test/relaxng/tutor10_1_4.xml line 1 element foo -Extra data in the document diff --git a/result/relaxng/tutor10_1_5.err b/result/relaxng/tutor10_1_5.err index a985d4d3..73a01855 100644 --- a/result/relaxng/tutor10_1_5.err +++ b/result/relaxng/tutor10_1_5.err @@ -1,4 +1,2 @@ RNG validity error: file ./test/relaxng/tutor10_1_5.xml line 1 element foo Element foo has wrong namespace: expecting http://www.example.com -RNG validity error: file ./test/relaxng/tutor10_1_5.xml line 1 element foo -Extra data in the document diff --git a/result/relaxng/tutor10_1_6.err b/result/relaxng/tutor10_1_6.err index e6c640d3..b072f4bb 100644 --- a/result/relaxng/tutor10_1_6.err +++ b/result/relaxng/tutor10_1_6.err @@ -1,4 +1,2 @@ RNG validity error: file ./test/relaxng/tutor10_1_6.xml line 1 element foo Element foo has wrong namespace: expecting http://www.example.com -RNG validity error: file ./test/relaxng/tutor10_1_6.xml line 1 element foo -Extra data in the document diff --git a/result/relaxng/tutor10_2_3.err b/result/relaxng/tutor10_2_3.err index 90c19cdf..ee88e073 100644 --- a/result/relaxng/tutor10_2_3.err +++ b/result/relaxng/tutor10_2_3.err @@ -1,4 +1,2 @@ RNG validity error: file ./test/relaxng/tutor10_2_3.xml line 1 element foo Expecting no namespace for element foo -RNG validity error: file ./test/relaxng/tutor10_2_3.xml line 1 element foo -Extra data in the document diff --git a/result/relaxng/tutor10_2_4.err b/result/relaxng/tutor10_2_4.err index 6872bea3..e6314402 100644 --- a/result/relaxng/tutor10_2_4.err +++ b/result/relaxng/tutor10_2_4.err @@ -1,4 +1,2 @@ RNG validity error: file ./test/relaxng/tutor10_2_4.xml line 1 element foo Expecting no namespace for element foo -RNG validity error: file ./test/relaxng/tutor10_2_4.xml line 1 element foo -Extra data in the document diff --git a/result/relaxng/tutor10_7_3.err b/result/relaxng/tutor10_7_3.err index 85544c39..8e2d82b5 100644 --- a/result/relaxng/tutor10_7_3.err +++ b/result/relaxng/tutor10_7_3.err @@ -1,8 +1,4 @@ RNG validity error: file ./test/relaxng/tutor10_7_3.xml line 2 element card Element card failed to validate attributes RNG validity error: file ./test/relaxng/tutor10_7_3.xml line 2 element card -Invalid attribute name for element card -RNG validity error: file ./test/relaxng/tutor10_7_3.xml line 2 element card -Invalid attribute email for element card -RNG validity error: file ./test/relaxng/tutor10_7_3.xml line 2 element card Element addressBook has extra content: card diff --git a/result/relaxng/tutor10_8_3.err b/result/relaxng/tutor10_8_3.err index 3b712f35..12cfcb77 100644 --- a/result/relaxng/tutor10_8_3.err +++ b/result/relaxng/tutor10_8_3.err @@ -1,8 +1,4 @@ RNG validity error: file ./test/relaxng/tutor10_8_3.xml line 2 element card Element card failed to validate attributes RNG validity error: file ./test/relaxng/tutor10_8_3.xml line 2 element card -Invalid attribute name for element card -RNG validity error: file ./test/relaxng/tutor10_8_3.xml line 2 element card -Invalid attribute email for element card -RNG validity error: file ./test/relaxng/tutor10_8_3.xml line 2 element card Element addressBook has extra content: card diff --git a/result/relaxng/tutor11_2_3.err b/result/relaxng/tutor11_2_3.err index fed4d2dd..ef91cab0 100644 --- a/result/relaxng/tutor11_2_3.err +++ b/result/relaxng/tutor11_2_3.err @@ -1,2 +1,2 @@ RNG validity error: file ./test/relaxng/tutor11_2_3.xml line 3 element card -Invalid attribute b for element card +Invalid attribute foo for element card diff --git a/result/relaxng/tutor12_1_err b/result/relaxng/tutor12_1_err index 2cdc5e1a..6e5566bd 100644 --- a/result/relaxng/tutor12_1_err +++ b/result/relaxng/tutor12_1_err @@ -1,150 +1,28 @@ +RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element +Expecting an element , got nothing +RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore +Invalid sequence in interleave RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element element, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element attribute, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element group, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element interleave, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element choice, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element optional, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element zeroOrMore, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element oneOrMore, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element list, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element mixed, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element ref, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element parentRef, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element empty, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element text, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element value, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element data, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element notAllowed, got nothing -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element externalRef, got nothing +Expecting an element , got nothing +RNG validity error: file ./test/relaxng/tutor12_1.rng line 4 element documentation +Invalid sequence in interleave RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting an element grammar, got nothing +Expecting an element , got nothing RNG validity error: file ./test/relaxng/tutor12_1.rng line 4 element documentation Invalid sequence in interleave RNG validity error: file ./test/relaxng/tutor12_1.rng line 4 element documentation Element element failed to validate content -RNG validity error: file ./test/relaxng/tutor12_1.rng line 4 element documentation -Element element has extra content: documentation RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element Expecting element attribute, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element group, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element interleave, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element choice, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element optional, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element zeroOrMore, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element oneOrMore, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element list, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element mixed, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element ref, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element parentRef, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element empty, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element text, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element value, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element data, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element notAllowed, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element externalRef, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 3 element element -Expecting element grammar, got element RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore Invalid sequence in interleave RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore Element zeroOrMore failed to validate content RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore Expecting element oneOrMore, got zeroOrMore -RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore -Expecting element list, got zeroOrMore -RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore -Expecting element mixed, got zeroOrMore -RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore -Expecting element ref, got zeroOrMore -RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore -Expecting element parentRef, got zeroOrMore -RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore -Expecting element empty, got zeroOrMore -RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore -Expecting element text, got zeroOrMore -RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore -Expecting element value, got zeroOrMore -RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore -Expecting element data, got zeroOrMore -RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore -Expecting element notAllowed, got zeroOrMore -RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore -Expecting element externalRef, got zeroOrMore -RNG validity error: file ./test/relaxng/tutor12_1.rng line 2 element zeroOrMore -Expecting element grammar, got zeroOrMore RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element Invalid sequence in interleave RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element Element element failed to validate content RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element Expecting element attribute, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element group, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element interleave, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element choice, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element optional, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element zeroOrMore, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element oneOrMore, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element list, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element mixed, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element ref, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element parentRef, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element empty, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element text, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element value, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element data, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element notAllowed, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element externalRef, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Expecting element grammar, got element -RNG validity error: file ./test/relaxng/tutor12_1.rng line 1 element element -Extra data in the document diff --git a/result/relaxng/tutor3_2_1.err b/result/relaxng/tutor3_2_1.err index 615cb87d..83e9a57c 100644 --- a/result/relaxng/tutor3_2_1.err +++ b/result/relaxng/tutor3_2_1.err @@ -2,5 +2,3 @@ RNG validity error: file ./test/relaxng/tutor3_2_1.xml line 1 element email Expecting element name, got email RNG validity error: file ./test/relaxng/tutor3_2_1.xml line 1 element email Element card failed to validate content -RNG validity error: file ./test/relaxng/tutor3_2_1.xml line 1 element email -Element card has extra content: email diff --git a/result/relaxng/tutor3_5_2.err b/result/relaxng/tutor3_5_2.err index 42743a27..5cbf2033 100644 --- a/result/relaxng/tutor3_5_2.err +++ b/result/relaxng/tutor3_5_2.err @@ -1,6 +1,6 @@ -RNG validity error: file ./test/relaxng/tutor3_5_2.xml line 2 element name +RNG validity error: file ./test/relaxng/tutor3_5_2.xml line 2 element email +Expecting element name, got email +RNG validity error: file ./test/relaxng/tutor3_5_2.xml line 2 element email Element card failed to validate content -RNG validity error: file ./test/relaxng/tutor3_5_2.xml line 2 element name -Element card has extra content: name RNG validity error: file ./test/relaxng/tutor3_5_2.xml line 2 element card Element addressBook has extra content: card diff --git a/result/relaxng/tutor3_7_err b/result/relaxng/tutor3_7_err index 89b14002..49948586 100644 --- a/result/relaxng/tutor3_7_err +++ b/result/relaxng/tutor3_7_err @@ -1,80 +1,12 @@ RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element element, got nothing +Expecting an element , got nothing RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element attribute, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element group, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element interleave, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element choice, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element optional, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element zeroOrMore, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element oneOrMore, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element list, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element mixed, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element ref, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element parentRef, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element empty, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element text, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element value, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element data, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element notAllowed, got nothing -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element externalRef, got nothing +Invalid sequence in interleave RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting an element grammar, got nothing +Expecting an element , got nothing RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element Invalid sequence in interleave RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element Element element failed to validate content RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element Expecting element attribute, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element group, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element interleave, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element choice, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element optional, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element zeroOrMore, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element oneOrMore, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element list, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element mixed, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element ref, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element parentRef, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element empty, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element text, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element value, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element data, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element notAllowed, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element externalRef, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Expecting element grammar, got element -RNG validity error: file ./test/relaxng/tutor3_7.rng line 1 element element -Extra data in the document diff --git a/result/relaxng/tutor6_1_3.err b/result/relaxng/tutor6_1_3.err index fa446379..3af31ee0 100644 --- a/result/relaxng/tutor6_1_3.err +++ b/result/relaxng/tutor6_1_3.err @@ -1,4 +1,2 @@ RNG validity error: file ./test/relaxng/tutor6_1_3.xml line 1 element card Element card failed to validate attributes -RNG validity error: file ./test/relaxng/tutor6_1_3.xml line 1 element card -Invalid attribute preferredFormat for element card diff --git a/result/relaxng/tutor6_2_4.err b/result/relaxng/tutor6_2_4.err index 17a825d8..dcba8644 100644 --- a/result/relaxng/tutor6_2_4.err +++ b/result/relaxng/tutor6_2_4.err @@ -1,10 +1,6 @@ RNG validity error: file ./test/relaxng/tutor6_2_4.xml line 4 element text Error validating value RNG validity error: file ./test/relaxng/tutor6_2_4.xml line 4 element text -Error validating value -RNG validity error: file ./test/relaxng/tutor6_2_4.xml line 4 element text Element preferredFormat failed to validate content -RNG validity error: file ./test/relaxng/tutor6_2_4.xml line 4 element text -Element preferredFormat has extra content: text RNG validity error: file ./test/relaxng/tutor6_2_4.xml line 1 element card Element card failed to validate content diff --git a/result/relaxng/tutor6_3_1.err b/result/relaxng/tutor6_3_1.err index 64b75e28..7957caca 100644 --- a/result/relaxng/tutor6_3_1.err +++ b/result/relaxng/tutor6_3_1.err @@ -1,4 +1,2 @@ RNG validity error: file ./test/relaxng/tutor6_3_1.xml line 1 element card Element card failed to validate attributes -RNG validity error: file ./test/relaxng/tutor6_3_1.xml line 1 element card -Invalid attribute preferredFormat for element card diff --git a/result/relaxng/tutor7_1_2.err b/result/relaxng/tutor7_1_2.err index 9b16493f..f5effb6b 100644 --- a/result/relaxng/tutor7_1_2.err +++ b/result/relaxng/tutor7_1_2.err @@ -4,5 +4,3 @@ RNG validity error: file ./test/relaxng/tutor7_1_2.xml line 1 element text Error validating list RNG validity error: file ./test/relaxng/tutor7_1_2.xml line 1 element text Element vector failed to validate content -RNG validity error: file ./test/relaxng/tutor7_1_2.xml line 1 element text -Element vector has extra content: text diff --git a/result/relaxng/tutor7_1_3.err b/result/relaxng/tutor7_1_3.err index b6ec7511..2a048cd2 100644 --- a/result/relaxng/tutor7_1_3.err +++ b/result/relaxng/tutor7_1_3.err @@ -4,5 +4,3 @@ RNG validity error: file ./test/relaxng/tutor7_1_3.xml line 1 element text Error validating list RNG validity error: file ./test/relaxng/tutor7_1_3.xml line 1 element text Element vector failed to validate content -RNG validity error: file ./test/relaxng/tutor7_1_3.xml line 1 element text -Element vector has extra content: text diff --git a/result/relaxng/tutor7_3_4.err b/result/relaxng/tutor7_3_4.err index 852837a8..8754d98c 100644 --- a/result/relaxng/tutor7_3_4.err +++ b/result/relaxng/tutor7_3_4.err @@ -4,5 +4,3 @@ RNG validity error: file ./test/relaxng/tutor7_3_4.xml line 1 element text Error validating list RNG validity error: file ./test/relaxng/tutor7_3_4.xml line 1 element text Element path failed to validate content -RNG validity error: file ./test/relaxng/tutor7_3_4.xml line 1 element text -Element path has extra content: text diff --git a/result/relaxng/tutor7_3_5.err b/result/relaxng/tutor7_3_5.err index 473c58bb..3d68250e 100644 --- a/result/relaxng/tutor7_3_5.err +++ b/result/relaxng/tutor7_3_5.err @@ -4,5 +4,3 @@ RNG validity error: file ./test/relaxng/tutor7_3_5.xml line 1 element text Error validating list RNG validity error: file ./test/relaxng/tutor7_3_5.xml line 1 element text Element path failed to validate content -RNG validity error: file ./test/relaxng/tutor7_3_5.xml line 1 element text -Element path has extra content: text diff --git a/result/relaxng/tutor8_2_4.err b/result/relaxng/tutor8_2_4.err index 2a1364dd..01a9ddb6 100644 --- a/result/relaxng/tutor8_2_4.err +++ b/result/relaxng/tutor8_2_4.err @@ -1,6 +1,4 @@ -RNG validity error: file ./test/relaxng/tutor8_2_4.xml line 5 element title +RNG validity error Extra element title in interleave RNG validity error: file ./test/relaxng/tutor8_2_4.xml line 5 element title Element head failed to validate content -RNG validity error: file ./test/relaxng/tutor8_2_4.xml line 5 element title -Element head has extra content: title diff --git a/result/relaxng/tutor8_2_6.err b/result/relaxng/tutor8_2_6.err index 22f948ab..c1fb4d11 100644 --- a/result/relaxng/tutor8_2_6.err +++ b/result/relaxng/tutor8_2_6.err @@ -1,6 +1,4 @@ -RNG validity error: file ./test/relaxng/tutor8_2_6.xml line 4 element base +RNG validity error Extra element base in interleave RNG validity error: file ./test/relaxng/tutor8_2_6.xml line 4 element base Element head failed to validate content -RNG validity error: file ./test/relaxng/tutor8_2_6.xml line 4 element base -Element head has extra content: base diff --git a/test/relaxng/testsuite.xml b/test/relaxng/testsuite.xml new file mode 100644 index 00000000..fa2b2e64 --- /dev/null +++ b/test/relaxng/testsuite.xml @@ -0,0 +1,779 @@ +<testSuite>
+<author>Daniel Veillard</author>
+<email>daniel@veillard.com</email>
+<documentation>For libxml2 implementation of Relax NG spec.</documentation>
+<testSuite>
+<documentation>Test of indeterminism</documentation>
+<testCase>
+<correct>
+<element name="foo" xmlns="http://relaxng.org/ns/structure/1.0">
+ <zeroOrMore>
+ <element name="bar">
+ <empty/>
+ </element>
+ </zeroOrMore>
+ <element name="baz">
+ <empty/>
+ </element>
+</element>
+</correct>
+<invalid>
+<foo/>
+</invalid>
+<valid>
+<foo>
+ <baz/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <baz/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+ <bar/>
+ <baz/>
+</foo>
+</valid>
+</testCase>
+<testCase>
+<correct>
+<element name="foo" xmlns="http://relaxng.org/ns/structure/1.0">
+ <zeroOrMore>
+ <element name="bar">
+ <empty/>
+ </element>
+ </zeroOrMore>
+ <element name="bar">
+ <empty/>
+ </element>
+</element>
+</correct>
+<invalid>
+<foo/>
+</invalid>
+<valid>
+<foo>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+ <bar/>
+ <bar/>
+</foo>
+</valid>
+</testCase>
+<testCase>
+<correct>
+<element name="foo" xmlns="http://relaxng.org/ns/structure/1.0">
+ <group>
+ <zeroOrMore>
+ <element name="bar">
+ <empty/>
+ </element>
+ </zeroOrMore>
+ <element name="baz">
+ <empty/>
+ </element>
+ </group>
+</element>
+</correct>
+<invalid>
+<foo/>
+</invalid>
+<valid>
+<foo>
+ <baz/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <baz/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+ <bar/>
+ <baz/>
+</foo>
+</valid>
+</testCase>
+<testCase>
+<correct>
+<element name="foo" xmlns="http://relaxng.org/ns/structure/1.0">
+ <group>
+ <zeroOrMore>
+ <element name="bar">
+ <empty/>
+ </element>
+ </zeroOrMore>
+ <element name="bar">
+ <empty/>
+ </element>
+ </group>
+</element>
+</correct>
+<invalid>
+<foo/>
+</invalid>
+<valid>
+<foo>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+ <bar/>
+ <bar/>
+</foo>
+</valid>
+</testCase>
+<testCase>
+<correct>
+<element name="foo" xmlns="http://relaxng.org/ns/structure/1.0">
+ <choice>
+ <zeroOrMore>
+ <element name="bar">
+ <empty/>
+ </element>
+ </zeroOrMore>
+ <element name="baz">
+ <empty/>
+ </element>
+ </choice>
+</element>
+</correct>
+<valid>
+<foo/>
+</valid>
+<valid>
+<foo>
+ <baz/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+ <bar/>
+</foo>
+</valid>
+<invalid>
+<foo>
+ <bar/>
+ <baz/>
+</foo>
+</invalid>
+<invalid>
+<foo>
+ <bar/>
+ <bar/>
+ <bar/>
+ <bar/>
+ <baz/>
+</foo>
+</invalid>
+</testCase>
+<testCase>
+<correct>
+<element name="foo" xmlns="http://relaxng.org/ns/structure/1.0">
+ <choice>
+ <zeroOrMore>
+ <element name="bar">
+ <empty/>
+ </element>
+ </zeroOrMore>
+ <element name="baz">
+ <empty/>
+ </element>
+ </choice>
+ <element name="baz">
+ <empty/>
+ </element>
+</element>
+</correct>
+<invalid>
+<foo/>
+</invalid>
+<valid>
+<foo>
+ <baz/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <baz/>
+ <baz/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+ <bar/>
+ <baz/>
+</foo>
+</valid>
+<invalid>
+<foo>
+ <bar/>
+ <baz/>
+ <baz/>
+</foo>
+</invalid>
+<invalid>
+<foo>
+ <baz/>
+ <bar/>
+ <baz/>
+</foo>
+</invalid>
+</testCase>
+<testCase>
+<correct>
+<element name="foo" xmlns="http://relaxng.org/ns/structure/1.0">
+ <choice>
+ <zeroOrMore>
+ <element name="bar">
+ <empty/>
+ </element>
+ </zeroOrMore>
+ <element name="bar">
+ <empty/>
+ </element>
+ </choice>
+</element>
+</correct>
+<valid>
+<foo/>
+</valid>
+<valid>
+<foo>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+ <bar/>
+ <bar/>
+</foo>
+</valid>
+</testCase>
+<testCase>
+<correct>
+<element name="foo" xmlns="http://relaxng.org/ns/structure/1.0">
+ <choice>
+ <zeroOrMore>
+ <choice>
+ <element name="bar">
+ <empty/>
+ </element>
+ <element name="baz">
+ <empty/>
+ </element>
+ </choice>
+ </zeroOrMore>
+ <element name="bar">
+ <empty/>
+ </element>
+ </choice>
+</element>
+</correct>
+<valid>
+<foo/>
+</valid>
+<valid>
+<foo>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <baz/>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+ <bar/>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <baz/>
+ <baz/>
+ <baz/>
+ <baz/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <baz/>
+ <bar/>
+ <baz/>
+ <bar/>
+</foo>
+</valid>
+</testCase>
+<testCase>
+<correct>
+<element name="foo" xmlns="http://relaxng.org/ns/structure/1.0">
+ <optional>
+ <element name="bar">
+ <empty/>
+ </element>
+ </optional>
+ <element name="baz">
+ <empty/>
+ </element>
+</element>
+</correct>
+<invalid>
+<foo/>
+</invalid>
+<valid>
+<foo>
+ <baz/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <baz/>
+</foo>
+</valid>
+<invalid>
+<foo>
+ <bar/>
+ <bar/>
+ <baz/>
+</foo>
+</invalid>
+</testCase>
+<testCase>
+<correct>
+<element name="foo" xmlns="http://relaxng.org/ns/structure/1.0">
+ <optional>
+ <element name="bar">
+ <empty/>
+ </element>
+ </optional>
+ <element name="bar">
+ <empty/>
+ </element>
+</element>
+</correct>
+<invalid>
+<foo/>
+</invalid>
+<valid>
+<foo>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+</foo>
+</valid>
+<invalid>
+<foo>
+ <bar/>
+ <bar/>
+ <bar/>
+</foo>
+</invalid>
+</testCase>
+<testCase>
+<correct>
+<element name="foo" xmlns="http://relaxng.org/ns/structure/1.0">
+ <optional>
+ <oneOrMore>
+ <element name="bar">
+ <empty/>
+ </element>
+ </oneOrMore>
+ </optional>
+ <element name="baz">
+ <empty/>
+ </element>
+</element>
+</correct>
+<invalid>
+<foo/>
+</invalid>
+<valid>
+<foo>
+ <baz/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <baz/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+ <baz/>
+</foo>
+</valid>
+<invalid>
+<foo>
+ <bar/>
+ <bar/>
+</foo>
+</invalid>
+</testCase>
+<testCase>
+<correct>
+<element name="foo" xmlns="http://relaxng.org/ns/structure/1.0">
+ <optional>
+ <oneOrMore>
+ <element name="bar">
+ <empty/>
+ </element>
+ </oneOrMore>
+ </optional>
+ <element name="bar">
+ <empty/>
+ </element>
+</element>
+</correct>
+<invalid>
+<foo/>
+</invalid>
+<valid>
+<foo>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+ <bar/>
+</foo>
+</valid>
+</testCase>
+<testCase>
+<correct>
+<element name="foo" xmlns="http://relaxng.org/ns/structure/1.0">
+ <group>
+ <zeroOrMore>
+ <choice>
+ <element name="bar">
+ <empty/>
+ </element>
+ <element name="baz">
+ <empty/>
+ </element>
+ </choice>
+ </zeroOrMore>
+ <element name="bar">
+ <empty/>
+ </element>
+ </group>
+</element>
+</correct>
+<invalid>
+<foo/>
+</invalid>
+<valid>
+<foo>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <baz/>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <bar/>
+ <bar/>
+ <bar/>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <baz/>
+ <baz/>
+ <baz/>
+ <bar/>
+</foo>
+</valid>
+<valid>
+<foo>
+ <baz/>
+ <bar/>
+ <baz/>
+ <bar/>
+</foo>
+</valid>
+<invalid>
+<foo>
+ <bar/>
+ <baz/>
+ <bar/>
+ <baz/>
+</foo>
+</invalid>
+</testCase>
+<testCase>
+<correct>
+<element name="list" xmlns="http://relaxng.org/ns/structure/1.0">
+ <oneOrMore>
+ <element name="label">
+ <empty/>
+ </element>
+ <optional>
+ <element name="opt">
+ <empty/>
+ </element>
+ </optional>
+ <element name="item">
+ <empty/>
+ </element>
+ </oneOrMore>
+</element>
+</correct>
+<invalid>
+<list>
+</list>
+</invalid>
+<valid>
+<list>
+ <label/>
+ <item/>
+</list>
+</valid>
+<valid>
+<list>
+ <label/>
+ <item/>
+ <label/>
+ <item/>
+</list>
+</valid>
+<valid>
+<list>
+ <label/>
+ <opt/>
+ <item/>
+ <label/>
+ <opt/>
+ <item/>
+</list>
+</valid>
+<invalid>
+<list>
+ <label/>
+ <item/>
+ <label/>
+ <opt/>
+ <opt/>
+ <item/>
+</list>
+</invalid>
+</testCase>
+<testCase>
+<correct>
+<element name="list" xmlns="http://relaxng.org/ns/structure/1.0">
+ <oneOrMore>
+ <element name="label">
+ <empty/>
+ </element>
+ <zeroOrMore>
+ <element name="opt">
+ <empty/>
+ </element>
+ </zeroOrMore>
+ <element name="item">
+ <empty/>
+ </element>
+ </oneOrMore>
+</element>
+</correct>
+<invalid>
+<list>
+</list>
+</invalid>
+<valid>
+<list>
+ <label/>
+ <item/>
+</list>
+</valid>
+<valid>
+<list>
+ <label/>
+ <item/>
+ <label/>
+ <item/>
+</list>
+</valid>
+<valid>
+<list>
+ <label/>
+ <opt/>
+ <item/>
+ <label/>
+ <opt/>
+ <item/>
+</list>
+</valid>
+<valid>
+<list>
+ <label/>
+ <item/>
+ <label/>
+ <opt/>
+ <opt/>
+ <item/>
+</list>
+</valid>
+</testCase>
+<testCase>
+<correct>
+<element name="list" xmlns="http://relaxng.org/ns/structure/1.0">
+ <oneOrMore>
+ <element name="label">
+ <empty/>
+ </element>
+ <zeroOrMore>
+ <element name="opt">
+ <empty/>
+ </element>
+ <element name="opt2">
+ <empty/>
+ </element>
+ </zeroOrMore>
+ <element name="item">
+ <empty/>
+ </element>
+ </oneOrMore>
+</element>
+</correct>
+<invalid>
+<list>
+</list>
+</invalid>
+<valid>
+<list>
+ <label/>
+ <item/>
+</list>
+</valid>
+<valid>
+<list>
+ <label/>
+ <item/>
+ <label/>
+ <item/>
+</list>
+</valid>
+<valid>
+<list>
+ <label/>
+ <opt/>
+ <opt2/>
+ <item/>
+ <label/>
+ <opt/>
+ <opt2/>
+ <item/>
+</list>
+</valid>
+<valid>
+<list>
+ <label/>
+ <item/>
+ <label/>
+ <opt/>
+ <opt2/>
+ <opt/>
+ <opt2/>
+ <item/>
+</list>
+</valid>
+<invalid>
+<list>
+ <label/>
+ <opt/>
+ <item/>
+ <label/>
+ <item/>
+</list>
+</invalid>
+<invalid>
+<list>
+ <label/>
+ <item/>
+ <label/>
+ <opt2/>
+ <opt/>
+ <item/>
+</list>
+</invalid>
+<invalid>
+<list>
+ <label/>
+ <item/>
+ <label/>
+ <opt/>
+ <opt2/>
+ <opt/>
+ <item/>
+</list>
+</invalid>
+</testCase>
+</testSuite>
+</testSuite>
|