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
diff --git a/ChangeLog b/ChangeLog
index a9e7e1c..67211c4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 37d399a..1ba320b 100644
--- a/include/libxml/relaxng.h
+++ b/include/libxml/relaxng.h
@@ -67,7 +67,8 @@
     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;
 
 /*
diff --git a/relaxng.c b/relaxng.c
index 91e249b..3f3cd16 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -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 @@
     (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 @@
 
 
 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 @@
     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 @@
 };
 
 /**
+ * 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 @@
 
     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 @@
     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 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 @@
  * 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 @@
     ctxt->defTab[ctxt->defNr++] = ret;
     ret->node = node;
     ret->depth = -1;
-    ret->type = type;
     return (ret);
 }
 
@@ -765,6 +764,105 @@
 }
 
 /**
+ * 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 @@
 }
 
 /**
+ * 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 @@
             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 @@
     return (ret);
 }
 
-
 /**
  * xmlRelaxNGDocumentPush:
  * @ctxt:  the parser context
@@ -1419,6 +1593,7 @@
 #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 @@
         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 @@
  * 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 @@
 	      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 @@
      (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 @@
     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 @@
     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 @@
 		   (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 @@
 		}
 		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 @@
 	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 @@
 	} 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 @@
 	} 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 @@
 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 @@
 		   (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,6 +2964,81 @@
 }
 	                     
 /**
+ * xmlRelaxNGCheckChoiceDeterminism:
+ * @ctxt:  a Relax-NG parser context
+ * @def:  the choice definition
+ *
+ * Also used to find indeterministic pattern in choice
+ */
+static void
+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_CHOICE))
+	return;
+
+    /*
+     * Don't run that check in case of error. Infinite recursion
+     * becomes possible.
+     */
+    if (ctxt->nbErrors != 0)
+	return;
+
+    is_nullable = xmlRelaxNGIsNullable(def);
+
+    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;
+    }
+}
+
+/**
  * xmlRelaxNGCheckGroupAttrs:
  * @ctxt:  a Relax-NG parser context
  * @def:  the group definition
@@ -2746,12 +3048,13 @@
 static void
 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_GROUP) &&
-	 (def->type != XML_RELAXNG_INTERLEAVE)))
+	 (def->type != XML_RELAXNG_ELEMENT)))
 	return;
 
     /*
@@ -2761,44 +3064,90 @@
     if (ctxt->nbErrors != 0)
 	return;
 
-    list[0] = xmlRelaxNGGetElements(ctxt, def->content, 1);
-    list[1] = xmlRelaxNGGetElements(ctxt, def->cont2, 1);
-
-    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");
-
-	}
-	ctxt->nbErrors++;
+    cur = def->attrs;
+    while (cur != NULL) {
+	nbchild++;
+	cur = cur->next;
     }
-    if (list[0] != NULL)
-	xmlFree(list[0]);
-    if (list[1] != NULL)
-	xmlFree(list[1]);
+    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 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);
 }
 
 /**
- * xmlRelaxNGCheckInterleave:
+ * xmlRelaxNGComputeInterleaves:
+ * @def:  the interleave definition
  * @ctxt:  a Relax-NG parser context
- * @def:  the group definition
+ * @name:  the definition name
  *
- * Detects violations of rule 7.3
+ * 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
-xmlRelaxNGCheckInterleave(xmlRelaxNGParserCtxtPtr ctxt,
-	                  xmlRelaxNGDefinePtr def) {
-    xmlRelaxNGDefinePtr *list[2];
-    int ret;
+xmlRelaxNGComputeInterleaves(xmlRelaxNGDefinePtr def,
+	                     xmlRelaxNGParserCtxtPtr ctxt,
+			     xmlChar *name ATTRIBUTE_UNUSED) {
+    xmlRelaxNGDefinePtr cur;
 
-    if ((def == NULL) ||
-	(def->type != XML_RELAXNG_INTERLEAVE))
-	return;
+    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
@@ -2807,21 +3156,94 @@
     if (ctxt->nbErrors != 0)
 	return;
 
-    list[0] = xmlRelaxNGGetElements(ctxt, def->content, 0);
-    list[1] = xmlRelaxNGGetElements(ctxt, def->cont2, 0);
-
-    ret = xmlRelaxNGCompareElemDefLists(ctxt, list[0], list[1]);
-    if (ret == 0) {
-	if (ctxt->error != NULL) {
-	    ctxt->error(ctxt->userData,
-		"Element or text conflicts in interleave\n");
-	}
-	ctxt->nbErrors++;
+#ifdef DEBUG_INTERLEAVE
+    xmlGenericError(xmlGenericErrorContext,
+		    "xmlRelaxNGComputeInterleaves(%s)\n",
+		    name);
+#endif
+    cur = def->content;
+    while (cur != NULL) {
+	nbchild++;
+	cur = cur->next;
     }
-    if (list[0] != NULL)
-	xmlFree(list[0]);
-    if (list[1] != NULL)
-	xmlFree(list[1]);
+    
+#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);
+    }
+    xmlRelaxNGFreePartition(partitions);
 }
 
 /**
@@ -2836,32 +3258,57 @@
 static xmlRelaxNGDefinePtr
 xmlRelaxNGParseInterleave(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
     xmlRelaxNGDefinePtr def = NULL;
+    xmlRelaxNGDefinePtr last = NULL, cur;
     xmlNodePtr child;
 
+    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,
+		"Failed to create interleaves hash table\n");
+	ctxt->nbErrors++;
+    } else {
+	char name[32];
+
+	snprintf(name, 32, "interleave%d", ctxt->nbInterleaves++);
+	if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST name, def) < 0) {
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData,
+		    "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++;
-    } else if (child->next == NULL) {
-	def = xmlRelaxNGParseElement(ctxt, child);
-    } else {
-	def = xmlRelaxNGNewDefine(ctxt, node, XML_RELAXNG_INTERLEAVE);
-	if (def == NULL) {
-	    return(NULL);
-	}
-
-	def->content = xmlRelaxNGParsePattern(ctxt, child);
-	child = child->next;
-	def->cont2 = xmlRelaxNGParsePattern(ctxt, child);
-	child = child->next;
-	if (child != NULL) {
-	    if (ctxt->error != NULL)
-		ctxt->error(ctxt->userData,
-		    "Internal: interleave has more than 2 children");
-	    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 @@
 			    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 @@
 
     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 @@
     } 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 @@
 	    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")) {
-	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);
-	} 
-    } 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")) {
-	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);
-	} 
-    } 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_CHOICE;
+	if (node->children == NULL) {
+	    if (ctxt->error != NULL)
+		ctxt->error(ctxt->userData,
+			    "Element %s is empty\n", node->name);
+	    ctxt->nbErrors++;
+	} else {
+	    def->content = xmlRelaxNGParsePatterns(ctxt, node->children, 0);
+	} 
+    } 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 {
+	    def->content = xmlRelaxNGParsePatterns(ctxt, node->children, 0);
+	} 
+    } else if (IS_RELAXNG(node, "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 @@
     } 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 @@
 	} 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 @@
 	    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 @@
 	    }
 	}
     } 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 @@
     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 @@
 		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 @@
 		"attribute has invalid content\n");
 		    ctxt->nbErrors++;
 		    break;
-#if 0
 		case XML_RELAXNG_NOOP:
 		    TODO
 		    if (ctxt->error != NULL)
@@ -3473,14 +3939,6 @@
 		"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 @@
 	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 @@
 static xmlRelaxNGDefinePtr
 xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,
 	                 xmlRelaxNGDefinePtr def) {
-    xmlRelaxNGDefinePtr ret;
+    xmlRelaxNGDefinePtr ret, tmp;
     xmlChar *val;
 
     ret = def;
@@ -3577,12 +4038,14 @@
         (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 @@
 			       (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 @@
 	    tmp->next = ret;
 	}
     }
-#endif
     return(ret);
 }
 
@@ -3707,9 +4182,10 @@
     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 @@
 		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 @@
 			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 @@
 		"Internal error, noop found\n");
 		    ctxt->nbErrors++;
 		    break;
-#endif
 	    }
 	}
 	child = child->next;
@@ -3819,7 +4297,8 @@
 	    } 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 @@
 	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 @@
 #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 @@
 		/*
 		 * 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 @@
 	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 @@
 #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 @@
 	} 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 @@
 	            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 @@
 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;
-	}
+    xmlRelaxNGDefinePtr prev = 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;
-		}
+    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);
 	    }
-	}
-
-	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;
-
-	    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));
-	    }
-	}
-    } 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;
 	    }
-	} else if (cur->type == XML_RELAXNG_EMPTY){
 	    if ((parent != NULL) &&
-		(parent->type == XML_RELAXNG_ONEORMORE)) {
+		(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_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 @@
  * @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,
+    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++;
-            }
-            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 @@
 		    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 @@
     }
     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 @@
 }
 
 /**
- * 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,6 +5742,300 @@
 		}
 		delete = cur;
 		goto skip_children;
+	    } else {
+		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;
+			}
+		    }
+		    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++;
+			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++;
+			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;
+			    }
+			}
+			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) {
+			    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 "");
+			}
+		    }
+		} 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 (ns != NULL) {
+				break;
+			    }
+			    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;
+
+			/*
+			 * 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 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
+		     */
+
+		    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;
+		}
 	    }
 	}
 	/*
@@ -5371,497 +6097,6 @@
 }
 
 /**
- * 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;
-
-    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;
-		    }
-		}
-		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++;
-		    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++;
-		    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;
-			}
-		    }
-		    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) {
-			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 "");
-		    }
-		}
-	    } 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 (ns != NULL) {
-			    break;
-			}
-			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;
-
-		    /*
-		     * 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 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
-		 */
-
-		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;
-	    }
-
-	    /*
-	     * 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;
-
-		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;
-			    }
-			}
-		    }
-		}
-	    } 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++;
-		    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++;
-		} 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;
-			}
-		    }
-		}
-	    }
-	}
-
-	/*
-	 * 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;
-    }
-}
-
-/**
  * xmlRelaxNGCleanupDoc:
  * @ctxt:  a Relax-NG parser context
  * @doc:  an xmldocPtr document pointer
@@ -5886,19 +6121,7 @@
 	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 @@
     }
 
     /*
+     * 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 @@
 		    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 @@
 	    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 @@
 	    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 @@
 	    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 @@
 	    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 @@
  * 			Validation implementation			*
  * 									*
  ************************************************************************/
+static int xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt, 
+	                                xmlRelaxNGDefinePtr define);
 static int xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, 
 	                           xmlRelaxNGDefinePtr define);
 
@@ -6384,8 +6602,8 @@
     }
     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 @@
 	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 @@
 	    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 @@
 	    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 @@
 	    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 @@
 	    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 @@
 }
 
 /**
+ * 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 @@
         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 @@
 }
 
 /**
+ * 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 @@
 	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 @@
 }
 
 /**
- * xmlRelaxNGNsNameMatch:
+ * xmlRelaxNGValidateInterleave:
+ * @ctxt:  a Relax-NG validation context
+ * @define:  the definition to verify
+ *
+ * Validate an interleave definition for a node.
+ *
+ * Returns 0 if the validation succeeded or an error code.
+ */
+static int
+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 {
+	VALID_ERR(XML_RELAXNG_ERR_INTERNODATA);
+	return(-1);
+    }
+
+    /*
+     * 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));
+
+    /*
+     * 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;
+	}
+	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);
+    }
+    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;
+
+	    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;
+	}
+	if (lasts[i] != NULL) {
+	    lasts[i]->next = last;
+	}
+    }
+    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;
+    }
+
+done:
+    /*
+     * builds the next links chain from the prev one
+     */
+    cur = lastchg;
+    while (cur != NULL) {
+	if ((cur == start) || (cur->prev == NULL))
+	    break;
+	cur->prev->next = cur;
+	cur = cur->prev;
+    }
+    if (ret == 0) {
+	ctxt->errNr = errNr;
+    }
+
+    xmlFree(list);
+    xmlFree(lasts);
+    return(ret);
+}
+
+/**
+ * xmlRelaxNGValidateDefinitionList:
+ * @ctxt:  a Relax-NG validation context
+ * @define:  the list of definition to verify
+ *
+ * Validate the given node content against the (list) of definitions
+ *
+ * Returns 0 if the validation succeeded or an error code.
+ */
+static int
+xmlRelaxNGValidateDefinitionList(xmlRelaxNGValidCtxtPtr ctxt, 
+	                  xmlRelaxNGDefinePtr defines) {
+    int ret = 0, res;
+
+
+    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;
+    }
+
+    return(ret);
+}
+
+/**
+ * xmlRelaxNGElementMatch:
  * @ctxt:  a Relax-NG validation context
  * @define:  the definition to check
- * @elem:  the node
- * @eora: element or attribute
+ * @elem:  the element
  *
- * Check if the element/attribute matches the definition nameClass
+ * Check if the element matches the definition nameClass
  *
- * Returns 1 if the node matches, 0 if no, or -1 in case of error
+ * Returns 1 if the element matches, 0 if no, or -1 in case of error
  */
 static int
-xmlRelaxNGNsNameMatch(xmlRelaxNGValidCtxtPtr ctxt,
-                      xmlRelaxNGDefinePtr define,
-                      xmlNodePtr elem, int eora)
-{
+xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt, 
+	               xmlRelaxNGDefinePtr define,
+		       xmlNodePtr elem) {
     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;
-    } else {
-        TODO ret = -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;
-
-    while (nodes != NULL) {
-	if (nodes->type == XML_ELEMENT_NODE) {
-	    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 (define->name != NULL) {
+	if (!xmlStrEqual(elem->name, define->name)) {
+	    VALID_ERR3(XML_RELAXNG_ERR_ELEMNAME, define->name, elem->name);
+	    return(0);
 	}
     }
-    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;
-
-    while (nodes != NULL) {
-	if (nodes->type == XML_ELEMENT_NODE) {
-	    break;
-	} else if ((nodes->type == XML_TEXT_NODE) ||
-		   (nodes->type == XML_CDATA_SECTION_NODE)) {
-	    content = xmlStrcat(content, nodes->content);
+    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);
 	}
-	/* TODO: handle entities ... */
-	nodes = nodes->next;
-    }
-    if (content == NULL) {
-	content = xmlStrdup(BAD_CAST "");
-	if (content == NULL) {
-	    VALID_ERR(XML_RELAXNG_ERR_MEMORY);
-	    return(-1);
-	}
-    }
-    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 (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) {
-	    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);
-	}
-    }
-    ctxt->state->value = NULL;
-    ret = xmlRelaxNGValidateDatatype(ctxt, content, define);
-    if (ret == -1) {
-	VALID_ERR2(XML_RELAXNG_ERR_DATATYPE, define->name);
-    }
-    if (content != NULL)
-	xmlFree(content);
-    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
- *
- * 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)
+    } 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);
+    }
+
+    if (define->nameClass == NULL)
+	return(1);
+
+    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 {
+	TODO
+	ret = -1;
+    }
+    return(ret);
+}
+
+/**
+ * xmlRelaxNGValidateElementEnd:
+ * @ctxt:  a Relax-NG validation context
+ *
+ * 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 0 if the validation succeeded or an error code.
+ */
+static int
+xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt) {
+    int ret = 0, i;
+    xmlRelaxNGValidStatePtr state;
+
+    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;
+	}
+    }
+    return(ret);
+}
+
+/**
+ * xmlRelaxNGValidateState:
+ * @ctxt:  a Relax-NG validation context
+ * @define:  the definition to verify
+ *
+ * Validate the current state against the definition
+ *
+ * Returns 0 if the validation succeeded or an error code.
+ */
+static int
+xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, 
+	                xmlRelaxNGDefinePtr define) {
+    xmlNodePtr node;
+    int ret = 0, i, tmp, oldflags, errNr;
+    xmlRelaxNGValidStatePtr oldstate, state;
+
+    if (define == NULL) {
+	VALID_ERR(XML_RELAXNG_ERR_NODEFINE);
+	return(-1);
+    }
+
+    if (ctxt->state != NULL) {
+	node = ctxt->state->seq;
+    } else {
+	node = NULL;
+    }
+#ifdef DEBUG
+    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_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);
+	    node = xmlRelaxNGSkipIgnored(ctxt, node);
+	    ret = 0;
 	    break;
-        case XML_RELAXNG_EXCEPT:
         case XML_RELAXNG_NOT_ALLOWED:
+	    ret = -1;
+	    break;
+        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:
-        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);
+	    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);
+		}
+	    }
+	    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;
+
+		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;
+	    }
+
+#ifdef DEBUG
+	    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
+	    break;
+        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;
+	    }
+	    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_ONEORMORE:
+	    ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content);
+	    if (ret != 0) {
+		break;
+	    }
+	    /* 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;
+	    }
+	    /*
+	     * 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 = 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;
+			}
+		    }
+		}
+		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;
+	}
+        case XML_RELAXNG_CHOICE: {
+	    xmlRelaxNGDefinePtr list = define->content;
+	    xmlRelaxNGStatesPtr states = NULL;
+
+
+	    oldflags = ctxt->flags;
+	    errNr = ctxt->errNr;
+	    ctxt->flags |= FLAGS_IGNORABLE;
+	    node = xmlRelaxNGSkipIgnored(ctxt, 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_DEF:
+        case XML_RELAXNG_GROUP:
+	    ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content);
 	    break;
         case XML_RELAXNG_INTERLEAVE:
-        case XML_RELAXNG_GROUP:
-	    ret = xmlRelaxNGIsNullable(define->content);
-	    if (ret != 0)
-		ret = xmlRelaxNGIsNullable(define->cont2);
+	    ret = xmlRelaxNGValidateInterleave(ctxt, define);
 	    break;
-	default:
-	    return(-1);
-    }
-    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);
-}
-#endif
-
-/**
- * xmlRelaxNGNewDeriv:
- * @ctxt:  a Relax-NG validation context
- * @type:  the derivation type
- * @c1:  the first children
- * @c2:  the second children
- *
- * Build a new derivated definition at runtime.
- *
- * Returns the new definition or NULL
- */
-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
-
-    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 ((def->cont2 != NULL) && (def->cont2->flags & IS_DYNAMIC)) {
-	def->cont2->depth--;
-	if (def->cont2->depth <= 0)
-	    xmlRelaxNGFreeDeriv(ctxt, def->cont2);
-    }
-    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 (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));
-    } else {
-	fprintf(stderr, "apply_after called on %s\n", xmlRelaxNGDefName(arg));
-    }
-    FREE_DERIV(f_arg2);
-    FREE_DERIV(arg);
-    return(ret);
-}
-	  
-/**
- * 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
-xmlRelaxNGTextDeriv(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGDefinePtr define,
-	            xmlNodePtr node) {
-    xmlRelaxNGDefinePtr d1, d2, ret;
-
-    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_ATTRIBUTE:
+	    ret = xmlRelaxNGValidateAttribute(ctxt, define);
+	    break;
+	case XML_RELAXNG_NOOP:
+        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;
+	    ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
+	    break;
+        case XML_RELAXNG_DATATYPE: {
+	    xmlNodePtr child;
+	    xmlChar *content = NULL;
 
-	       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;
-    }
-    FREE_DERIV(define);
-    return(ret);
-}
-
-/**
- * xmlRelaxNGStartTagOpenDeriv:
- * @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
-xmlRelaxNGStartTagOpenDeriv(xmlRelaxNGValidCtxtPtr ctxt,
-	                    xmlRelaxNGDefinePtr define, xmlNodePtr node) {
-    xmlRelaxNGDefinePtr d1, d2, ret;
-
-    if ((ctxt == NULL) || (define == NULL) || (node == NULL))
-	return(NULL);
-#ifdef DEBUG
-    printf("start_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,
-		    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);
-	    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;
-	    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));
-	    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);
-		}
-	    } 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);
-}
-
-/**
- * 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;
-
-    if ((ctxt == NULL) || (define == NULL) || (node == NULL))
-	return(NULL);
-#ifdef DEBUG
-    printf("att: node: %s\ndef : ", node->name);
-    xmlRelaxNGDumpDefine(stdout, define);
-#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)));
-	    }
-	    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);
-	    }
-	    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)));
-	    }
-	    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));
-	    }
-	    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;
-		} else {
-		    ret = xmlRelaxNGNotAllowedDeriv;
-		}
-	    } else
-		ret = xmlRelaxNGNotAllowedDeriv;
-	    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;
-
-    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;
-
-    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));
-	    break;
-	case XML_RELAXNG_AFTER:
-	    if (xmlRelaxNGIsNullable(define->content)) {
-		REF_DERIV(define->cont2);
-		ret = define->cont2;
-	    } else
-		ret = xmlRelaxNGNotAllowedDeriv;
-	    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));
-	    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));
-	    break;
-	case XML_RELAXNG_AFTER:
-	    REF_DERIV(define->content);
-	    REF_DERIV(define->cont2);
-	    ret = after(ctxt,
-		    xmlRelaxNGStartTagCloseDeriv(ctxt, define->content, node),
-		    define->cont2);
-	    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));
-	    break;
-	case XML_RELAXNG_ONEORMORE:
-	    REF_DERIV(define->content);
-	    ret = oneormore(ctxt,
-		    xmlRelaxNGStartTagCloseDeriv(ctxt, define->content, node));
-	    break;
-	case XML_RELAXNG_ATTRIBUTE:
-	    ret = xmlRelaxNGNotAllowedDeriv;
-	    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);
-    return(ret);
-}
-
-/**
- * xmlRelaxNGChildrenDeriv:
- * @ctxt:  a Relax-NG validation context
- * @define:  the definition to verify
- * @node:  the current node
- *
- * computes the children derivation of a node
- *
- * Returns the new derivation or NULL in case of error.
- */
-static xmlRelaxNGDefinePtr
-xmlRelaxNGChildrenDeriv(xmlRelaxNGValidCtxtPtr ctxt,
-	             xmlRelaxNGDefinePtr define, xmlNodePtr node) {
-    xmlRelaxNGDefinePtr res = NULL;
-    xmlNodePtr nodes;
-
-    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);
-	}
-    } 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)
+	    child = node;
+	    while (child != NULL) {
+		if (child->type == XML_ELEMENT_NODE) {
+		    VALID_ERR2(XML_RELAXNG_ERR_DATAELEM,
+				 node->parent->name);
+		    ret = -1;
 		    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;
-		} else {
-		    nodes = nodes->next;
+		} 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;
 	}
-    }
-    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;
+        case XML_RELAXNG_VALUE: {
+	    xmlChar *content = NULL;
+	    xmlChar *oldvalue;
+	    xmlNodePtr child;
 
-    if ((ctxt == NULL) || (define == NULL) || (node == NULL))
-	return(NULL);
+	    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_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_START:
+	case XML_RELAXNG_EXCEPT:
+	case XML_RELAXNG_PARAM:
+	    TODO
+	    ret = -1;
+	    break;
+    }
+    ctxt->depth--;
 #ifdef DEBUG
-    printf("child: node: %s\ndef : ", node->name);
-    xmlRelaxNGDumpDefine(stdout, define);
+    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
-    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);
-    }
-    TODO
-    return(NULL);
+    return(ret);
 }
 
 /**
- * xmlRelaxNGMatches:
+ * xmlRelaxNGValidateDefinition:
  * @ctxt:  a Relax-NG validation context
  * @define:  the definition to verify
- * @node:  the current node
  *
- * Check if the node matches the definition
+ * Validate the current node lists against the definition
  *
- * 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
-xmlRelaxNGMatches(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGDefinePtr define,
-	          xmlNodePtr node) {
-    xmlRelaxNGDefinePtr deriv;
-    int ret;
+xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt, 
+	                     xmlRelaxNGDefinePtr define) {
+    xmlRelaxNGStatesPtr states, res;
+    int i, j, k, ret, oldflags;
 
-    deriv = xmlRelaxNGChildDeriv(ctxt, define, node);
-    ret = xmlRelaxNGIsNullable(deriv);
-    FREE_DERIV(deriv);
+    /*
+     * 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;
+	}
+	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 {
+		    /* 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;
+	    }
+	}
+    }
+    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;
+    }
     return(ret);
 }
 
-/************************************************************************
- * 									*
- * 			Validation interfaces				*
- * 									*
- ************************************************************************/
-
 /**
  * xmlRelaxNGValidateDocument:
  * @ctxt:  a Relax-NG validation context
@@ -8164,6 +8247,7 @@
     xmlRelaxNGPtr schema;
     xmlRelaxNGGrammarPtr grammar;
     xmlRelaxNGValidStatePtr state;
+    xmlNodePtr node;
 
     if ((ctxt == NULL) || (ctxt->schema == NULL) || (doc == NULL))
 	return(-1);
@@ -8176,32 +8260,48 @@
     }
     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 @@
     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 @@
 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 e3b2ee8..b9f01ac 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
+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 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
-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 adee007..862ed3a 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 a985d4d..73a0185 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 e6c640d..b072f4b 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 90c19cd..ee88e07 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 6872bea..e631440 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 85544c3..8e2d82b 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 3b712f3..12cfcb7 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 fed4d2d..ef91cab 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 2cdc5e1..6e5566b 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
+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 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
-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 615cb87..83e9a57 100644
--- a/result/relaxng/tutor3_2_1.err
+++ b/result/relaxng/tutor3_2_1.err
@@ -2,5 +2,3 @@
 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 42743a2..5cbf203 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 89b1400..4994858 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
+Invalid sequence in interleave
 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
-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 fa44637..3af31ee 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 17a825d..dcba864 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 64b75e2..7957cac 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 9b16493..f5effb6 100644
--- a/result/relaxng/tutor7_1_2.err
+++ b/result/relaxng/tutor7_1_2.err
@@ -4,5 +4,3 @@
 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 b6ec751..2a048cd 100644
--- a/result/relaxng/tutor7_1_3.err
+++ b/result/relaxng/tutor7_1_3.err
@@ -4,5 +4,3 @@
 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 852837a..8754d98 100644
--- a/result/relaxng/tutor7_3_4.err
+++ b/result/relaxng/tutor7_3_4.err
@@ -4,5 +4,3 @@
 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 473c58b..3d68250 100644
--- a/result/relaxng/tutor7_3_5.err
+++ b/result/relaxng/tutor7_3_5.err
@@ -4,5 +4,3 @@
 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 2a1364d..01a9ddb 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 22f948a..c1fb4d1 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 0000000..fa2b2e6
--- /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>