more work on name classes, except support augmented/updated the regression

* relaxng: more work on name classes, except support
* test/relaxng/* result/relaxng/*: augmented/updated the
  regression tests
Daniel
diff --git a/ChangeLog b/ChangeLog
index aa3b9f4..1bb3c4c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Mon Feb  3 14:16:59 CET 2003 Daniel Veillard <daniel@veillard.com>
+
+	* relaxng: more work on name classes, except support
+	* test/relaxng/* result/relaxng/*: augmented/updated the
+	  regression tests
+
 Mon Feb  3 11:56:05 CET 2003 Daniel Veillard <daniel@veillard.com>
 
 	* relaxng: more work on name classes, the "validate all" schemas
diff --git a/relaxng.c b/relaxng.c
index 2454dbd..c6953c7 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -95,6 +95,7 @@
 typedef enum {
     XML_RELAXNG_EMPTY = 0,	/* an empty pattern */
     XML_RELAXNG_NOT_ALLOWED,    /* not allowed top */
+    XML_RELAXNG_EXCEPT,    	/* except present in nameclass defs */
     XML_RELAXNG_TEXT,		/* textual content */
     XML_RELAXNG_ELEMENT,	/* an element */
     XML_RELAXNG_DATATYPE,	/* extenal data type definition */
@@ -596,6 +597,8 @@
 	(define->type != XML_RELAXNG_REF) &&
 	(define->type != XML_RELAXNG_EXTERNALREF))
 	xmlRelaxNGFreeDefineList(define->content);
+    if (define->nameClass != NULL)
+	xmlRelaxNGFreeDefineList(define->nameClass);
     if ((define->data != NULL) &&
 	(define->type == XML_RELAXNG_INTERLEAVE))
 	xmlRelaxNGFreePartition((xmlRelaxNGPartitionPtr) define->data);
@@ -2493,6 +2496,7 @@
 		    ret->attrs = cur;
 		    break;
 		case XML_RELAXNG_START:
+		case XML_RELAXNG_EXCEPT:
 		    TODO
 		    break;
 	    }
@@ -2507,15 +2511,56 @@
  * xmlRelaxNGParseExceptNameClass:
  * @ctxt:  a Relax-NG parser context
  * @node:  the except node
+ * @attr:  1 if within an attribute, 0 if within an element
  *
  * parse the content of a RelaxNG nameClass node.
  *
  * Returns the definition pointer or NULL in case of error.
  */
 static xmlRelaxNGDefinePtr
-xmlRelaxNGParseExceptNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
-    TODO
-    return(NULL);
+xmlRelaxNGParseExceptNameClass(xmlRelaxNGParserCtxtPtr ctxt,
+	                       xmlNodePtr node, int attr) {
+    xmlRelaxNGDefinePtr ret, cur, last = NULL;
+    xmlNodePtr child;
+
+    if (!IS_RELAXNG(node, "except"))
+	return(NULL);
+    if (node->children == NULL) {
+	if (ctxt->error != NULL)
+	    ctxt->error(ctxt->userData,
+		"except has no content\n");
+	ctxt->nbErrors++;
+	return(NULL);
+    }
+
+    ret = xmlRelaxNGNewDefine(ctxt, node);
+    if (ret == NULL)
+	return(NULL);
+    ret->type = XML_RELAXNG_EXCEPT;
+    child = node->children;
+    while (child != NULL) {
+	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) {
+	    xmlRelaxNGFreeDefine(cur);
+	} else {
+	    if (last == NULL) {
+		ret->content = cur;
+	    } else {
+		last->next = cur;
+	    }
+	    last = cur;
+	}
+	child = child->next;
+    }
+
+    return(ret);
 }
 
 /**
@@ -2544,7 +2589,8 @@
 	ret->ns = NULL;
 	if (node->children != NULL) {
 	    ret->nameClass =
-		xmlRelaxNGParseExceptNameClass(ctxt, node->children);
+		xmlRelaxNGParseExceptNameClass(ctxt, node->children,
+			       (def->type == XML_RELAXNG_ATTRIBUTE));
 	}
     } else if (IS_RELAXNG(node, "nsName")) {
 	ret->name = NULL;
@@ -2557,7 +2603,8 @@
 	}
 	if (node->children != NULL) {
 	    ret->nameClass =
-		xmlRelaxNGParseExceptNameClass(ctxt, node->children);
+		xmlRelaxNGParseExceptNameClass(ctxt, node->children,
+			       (def->type == XML_RELAXNG_ATTRIBUTE));
 	}
     } else if (IS_RELAXNG(node, "choice")) {
 	TODO
@@ -2657,6 +2704,7 @@
 		    ret->attrs = cur;
 		    break;
 		case XML_RELAXNG_START:
+		case XML_RELAXNG_EXCEPT:
 		    TODO
 		    break;
 	    }
@@ -3842,6 +3890,7 @@
 	    TODO
 	    break;
 	case XML_RELAXNG_START:
+	case XML_RELAXNG_EXCEPT:
 	    TODO
 	    break;
     }
@@ -4281,6 +4330,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
@@ -4334,43 +4434,11 @@
 	xmlGenericError(xmlGenericErrorContext,
                     "xmlRelaxNGValidateAttribute(%s): %d\n", define->name, ret);
 #endif
-    } else if (define->ns != NULL) {
-        for (i = 0;i < ctxt->state->nbAttrs;i++) {
-	    tmp = ctxt->state->attrs[i];
-	    if ((tmp != NULL) && (tmp->ns != NULL) &&
-		(xmlStrEqual(define->ns, tmp->ns->href))) {
-		prop = tmp;
-		break;
-	    }
-	}
-	if (prop != NULL) {
-	    value = xmlNodeListGetString(prop->doc, prop->children, 1);
-	    oldvalue = ctxt->state->value;
-	    ctxt->state->value = value;
-	    ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
-	    value = ctxt->state->value;
-	    ctxt->state->value = oldvalue;
-	    if (value != NULL)
-		xmlFree(value);
-	    if (ret == 0) {
-		/*
-		 * flag the attribute as processed
-		 */
-		ctxt->state->attrs[i] = NULL;
-		ctxt->state->nbAttrLeft--;
-	    }
-	} else {
-	    ret = -1;
-	}
-#ifdef DEBUG
-	xmlGenericError(xmlGenericErrorContext,
-                    "xmlRelaxNGValidateAttribute(nsName ns = %s): %d\n",
-		        define->ns, ret);
-#endif
     } else {
         for (i = 0;i < ctxt->state->nbAttrs;i++) {
 	    tmp = ctxt->state->attrs[i];
-	    if (tmp != NULL) {
+	    if ((tmp != NULL) &&
+		(xmlRelaxNGAttributeMatch(ctxt, define, tmp) == 1)) {
 		prop = tmp;
 		break;
 	    }
@@ -4395,11 +4463,16 @@
 	    ret = -1;
 	}
 #ifdef DEBUG
-	xmlGenericError(xmlGenericErrorContext,
-                    "xmlRelaxNGValidateAttribute(anyName): %d\n",
-		        ret);
+	if (define->ns != NULL) {
+	    xmlGenericError(xmlGenericErrorContext,
+			"xmlRelaxNGValidateAttribute(nsName ns = %s): %d\n",
+			    define->ns, ret);
+	} else {
+	    xmlGenericError(xmlGenericErrorContext,
+			"xmlRelaxNGValidateAttribute(anyName): %d\n",
+			    ret);
+	}
 #endif
-	
     }
     
     return(ret);
@@ -5104,6 +5177,7 @@
 	    break;
         }
 	case XML_RELAXNG_START:
+	case XML_RELAXNG_EXCEPT:
 	    TODO
 	    break;
     }
diff --git a/result/relaxng/tutor10_1_4.err b/result/relaxng/tutor10_1_4.err
index 99a3cc9..f44dee7 100644
--- a/result/relaxng/tutor10_1_4.err
+++ b/result/relaxng/tutor10_1_4.err
@@ -1,2 +1,2 @@
-error detected at relaxng.c:4847
-error detected at relaxng.c:5149
+error detected at relaxng.c:4920
+error detected at relaxng.c:5223
diff --git a/result/relaxng/tutor10_1_5.err b/result/relaxng/tutor10_1_5.err
index 83d207c..485b5f9 100644
--- a/result/relaxng/tutor10_1_5.err
+++ b/result/relaxng/tutor10_1_5.err
@@ -1,2 +1,2 @@
-error detected at relaxng.c:4852
-error detected at relaxng.c:5149
+error detected at relaxng.c:4925
+error detected at relaxng.c:5223
diff --git a/result/relaxng/tutor10_1_6.err b/result/relaxng/tutor10_1_6.err
index 83d207c..485b5f9 100644
--- a/result/relaxng/tutor10_1_6.err
+++ b/result/relaxng/tutor10_1_6.err
@@ -1,2 +1,2 @@
-error detected at relaxng.c:4852
-error detected at relaxng.c:5149
+error detected at relaxng.c:4925
+error detected at relaxng.c:5223
diff --git a/result/relaxng/tutor10_2_3.err b/result/relaxng/tutor10_2_3.err
index ced2b6d..df2b554 100644
--- a/result/relaxng/tutor10_2_3.err
+++ b/result/relaxng/tutor10_2_3.err
@@ -1,2 +1,2 @@
-error detected at relaxng.c:4859
-error detected at relaxng.c:5149
+error detected at relaxng.c:4932
+error detected at relaxng.c:5223
diff --git a/result/relaxng/tutor10_2_4.err b/result/relaxng/tutor10_2_4.err
index ced2b6d..df2b554 100644
--- a/result/relaxng/tutor10_2_4.err
+++ b/result/relaxng/tutor10_2_4.err
@@ -1,2 +1,2 @@
-error detected at relaxng.c:4859
-error detected at relaxng.c:5149
+error detected at relaxng.c:4932
+error detected at relaxng.c:5223
diff --git a/result/relaxng/tutor10_7_3.err b/result/relaxng/tutor10_7_3.err
index f400083..e6e8943 100644
--- a/result/relaxng/tutor10_7_3.err
+++ b/result/relaxng/tutor10_7_3.err
@@ -1,5 +1,5 @@
 xmlRelaxNGValidateAttribute(email): -1
 xmlRelaxNGValidateAttribute(name): -1
 xmlRelaxNGValidateDefinition(): validated card : -1
-error detected at relaxng.c:4887
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated addressBook : -1
diff --git a/result/relaxng/tutor10_8_3.err b/result/relaxng/tutor10_8_3.err
index f400083..e6e8943 100644
--- a/result/relaxng/tutor10_8_3.err
+++ b/result/relaxng/tutor10_8_3.err
@@ -1,5 +1,5 @@
 xmlRelaxNGValidateAttribute(email): -1
 xmlRelaxNGValidateAttribute(name): -1
 xmlRelaxNGValidateDefinition(): validated card : -1
-error detected at relaxng.c:4887
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated addressBook : -1
diff --git a/result/relaxng/tutor11_2_1 b/result/relaxng/tutor11_2_1
new file mode 100644
index 0000000..eec60ec
--- /dev/null
+++ b/result/relaxng/tutor11_2_1
@@ -0,0 +1 @@
+./test/relaxng/tutor11_2_1.xml validates
diff --git a/result/relaxng/tutor11_2_1.err b/result/relaxng/tutor11_2_1.err
new file mode 100644
index 0000000..766e04d
--- /dev/null
+++ b/result/relaxng/tutor11_2_1.err
@@ -0,0 +1,3 @@
+xmlRelaxNGValidateAttribute(anyName): 0
+xmlRelaxNGValidateAttribute(anyName): 0
+xmlRelaxNGValidateDefinition(): validated card : 0
diff --git a/result/relaxng/tutor11_2_2 b/result/relaxng/tutor11_2_2
new file mode 100644
index 0000000..15e59f7
--- /dev/null
+++ b/result/relaxng/tutor11_2_2
@@ -0,0 +1,2 @@
+Invalid attribute foo for element card
+./test/relaxng/tutor11_2_2.xml validation generated an internal error
diff --git a/result/relaxng/tutor11_2_2.err b/result/relaxng/tutor11_2_2.err
new file mode 100644
index 0000000..e7c8b3b
--- /dev/null
+++ b/result/relaxng/tutor11_2_2.err
@@ -0,0 +1,4 @@
+xmlRelaxNGValidateAttribute(anyName): 0
+xmlRelaxNGValidateAttribute(anyName): -1
+error detected at relaxng.c:4968
+xmlRelaxNGValidateDefinition(): validated card : -1
diff --git a/result/relaxng/tutor11_2_3 b/result/relaxng/tutor11_2_3
new file mode 100644
index 0000000..eb79139
--- /dev/null
+++ b/result/relaxng/tutor11_2_3
@@ -0,0 +1,2 @@
+Invalid attribute b for element card
+./test/relaxng/tutor11_2_3.xml validation generated an internal error
diff --git a/result/relaxng/tutor11_2_3.err b/result/relaxng/tutor11_2_3.err
new file mode 100644
index 0000000..e7c8b3b
--- /dev/null
+++ b/result/relaxng/tutor11_2_3.err
@@ -0,0 +1,4 @@
+xmlRelaxNGValidateAttribute(anyName): 0
+xmlRelaxNGValidateAttribute(anyName): -1
+error detected at relaxng.c:4968
+xmlRelaxNGValidateDefinition(): validated card : -1
diff --git a/result/relaxng/tutor3_2_1.err b/result/relaxng/tutor3_2_1.err
index 5794e13..57dfd09 100644
--- a/result/relaxng/tutor3_2_1.err
+++ b/result/relaxng/tutor3_2_1.err
@@ -1,3 +1,3 @@
-error detected at relaxng.c:4839
-error detected at relaxng.c:4887
+error detected at relaxng.c:4912
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated card : -1
diff --git a/result/relaxng/tutor3_5_2.err b/result/relaxng/tutor3_5_2.err
index f7c7c03..64104fc 100644
--- a/result/relaxng/tutor3_5_2.err
+++ b/result/relaxng/tutor3_5_2.err
@@ -1,4 +1,4 @@
 xmlRelaxNGValidateDefinition(): validated email : 0
 xmlRelaxNGValidateDefinition(): validated card : -1
-error detected at relaxng.c:4887
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated addressBook : -1
diff --git a/result/relaxng/tutor5_3_1.err b/result/relaxng/tutor5_3_1.err
index 0064d80..cbe216a 100644
--- a/result/relaxng/tutor5_3_1.err
+++ b/result/relaxng/tutor5_3_1.err
@@ -1,3 +1,3 @@
-error detected at relaxng.c:5032
+error detected at relaxng.c:5105
 xmlRelaxNGValidateDefinition(): validated note : 0
 xmlRelaxNGValidateDefinition(): validated bad : -1
diff --git a/result/relaxng/tutor6_1_3.err b/result/relaxng/tutor6_1_3.err
index 36519cf..079f7f1 100644
--- a/result/relaxng/tutor6_1_3.err
+++ b/result/relaxng/tutor6_1_3.err
@@ -1,5 +1,5 @@
 xmlRelaxNGValidateAttribute(preferredFormat): -1
 xmlRelaxNGValidateAttribute(email): 0
 xmlRelaxNGValidateAttribute(name): 0
-error detected at relaxng.c:4895
+error detected at relaxng.c:4968
 xmlRelaxNGValidateDefinition(): validated card : -1
diff --git a/result/relaxng/tutor6_2_4.err b/result/relaxng/tutor6_2_4.err
index bcfffcd..ad2cde7 100644
--- a/result/relaxng/tutor6_2_4.err
+++ b/result/relaxng/tutor6_2_4.err
@@ -1,5 +1,5 @@
 xmlRelaxNGValidateDefinition(): validated name : 0
 xmlRelaxNGValidateDefinition(): validated email : 0
-error detected at relaxng.c:4887
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated preferredFormat : -1
 xmlRelaxNGValidateDefinition(): validated card : -1
diff --git a/result/relaxng/tutor6_3_1.err b/result/relaxng/tutor6_3_1.err
index 36519cf..079f7f1 100644
--- a/result/relaxng/tutor6_3_1.err
+++ b/result/relaxng/tutor6_3_1.err
@@ -1,5 +1,5 @@
 xmlRelaxNGValidateAttribute(preferredFormat): -1
 xmlRelaxNGValidateAttribute(email): 0
 xmlRelaxNGValidateAttribute(name): 0
-error detected at relaxng.c:4895
+error detected at relaxng.c:4968
 xmlRelaxNGValidateDefinition(): validated card : -1
diff --git a/result/relaxng/tutor7_1_2.err b/result/relaxng/tutor7_1_2.err
index 178c355..b401034 100644
--- a/result/relaxng/tutor7_1_2.err
+++ b/result/relaxng/tutor7_1_2.err
@@ -1,5 +1,5 @@
 Unimplemented block at xmlschemastypes.c:1132
-error detected at relaxng.c:4029
-error detected at relaxng.c:5086
-error detected at relaxng.c:4887
+error detected at relaxng.c:4078
+error detected at relaxng.c:5159
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated vector : -1
diff --git a/result/relaxng/tutor7_1_3.err b/result/relaxng/tutor7_1_3.err
index 50e749e..ea5baa2 100644
--- a/result/relaxng/tutor7_1_3.err
+++ b/result/relaxng/tutor7_1_3.err
@@ -1,6 +1,6 @@
 Unimplemented block at xmlschemastypes.c:1132
 Unimplemented block at xmlschemastypes.c:1132
-error detected at relaxng.c:4217
-error detected at relaxng.c:5086
-error detected at relaxng.c:4887
+error detected at relaxng.c:4266
+error detected at relaxng.c:5159
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated vector : -1
diff --git a/result/relaxng/tutor7_2_4.err b/result/relaxng/tutor7_2_4.err
index 33444ae..7be81f1 100644
--- a/result/relaxng/tutor7_2_4.err
+++ b/result/relaxng/tutor7_2_4.err
@@ -1,3 +1,3 @@
-error detected at relaxng.c:4192
-error detected at relaxng.c:5086
+error detected at relaxng.c:4241
+error detected at relaxng.c:5159
 xmlRelaxNGValidateDefinition(): validated vector : -1
diff --git a/result/relaxng/tutor7_3_4.err b/result/relaxng/tutor7_3_4.err
index 510d749..0d0056d 100644
--- a/result/relaxng/tutor7_3_4.err
+++ b/result/relaxng/tutor7_3_4.err
@@ -1,7 +1,7 @@
 Unimplemented block at xmlschemastypes.c:1135
 Unimplemented block at xmlschemastypes.c:1135
 Unimplemented block at xmlschemastypes.c:1135
-error detected at relaxng.c:4217
-error detected at relaxng.c:5086
-error detected at relaxng.c:4887
+error detected at relaxng.c:4266
+error detected at relaxng.c:5159
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated path : -1
diff --git a/result/relaxng/tutor7_3_5.err b/result/relaxng/tutor7_3_5.err
index e9f10c1..3d48e84 100644
--- a/result/relaxng/tutor7_3_5.err
+++ b/result/relaxng/tutor7_3_5.err
@@ -1,5 +1,5 @@
 Unimplemented block at xmlschemastypes.c:1135
-error detected at relaxng.c:4029
-error detected at relaxng.c:5086
-error detected at relaxng.c:4887
+error detected at relaxng.c:4078
+error detected at relaxng.c:5159
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated path : -1
diff --git a/result/relaxng/tutor8_2_4.err b/result/relaxng/tutor8_2_4.err
index e36b37a..bbea200 100644
--- a/result/relaxng/tutor8_2_4.err
+++ b/result/relaxng/tutor8_2_4.err
@@ -3,5 +3,5 @@
   6 groups
 xmlRelaxNGValidateDefinition(): validated title : 0
 xmlRelaxNGValidateDefinition(): validated title : 0
-error detected at relaxng.c:4887
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated head : -1
diff --git a/result/relaxng/tutor8_2_5.err b/result/relaxng/tutor8_2_5.err
index 60bd650..2a84fea 100644
--- a/result/relaxng/tutor8_2_5.err
+++ b/result/relaxng/tutor8_2_5.err
@@ -1,6 +1,6 @@
 xmlRelaxNGComputeInterleaves(interleave0)
   6 child
   6 groups
-error detected at relaxng.c:4833
-error detected at relaxng.c:4887
+error detected at relaxng.c:4906
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated head : -1
diff --git a/result/relaxng/tutor8_2_6.err b/result/relaxng/tutor8_2_6.err
index fdaab03..0393fd4 100644
--- a/result/relaxng/tutor8_2_6.err
+++ b/result/relaxng/tutor8_2_6.err
@@ -4,5 +4,5 @@
 xmlRelaxNGValidateDefinition(): validated title : 0
 xmlRelaxNGValidateDefinition(): validated base : 0
 xmlRelaxNGValidateDefinition(): validated base : 0
-error detected at relaxng.c:4887
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated head : -1
diff --git a/result/relaxng/tutor9_5_2.err b/result/relaxng/tutor9_5_2.err
index d5c7a2d..3a61cca 100644
--- a/result/relaxng/tutor9_5_2.err
+++ b/result/relaxng/tutor9_5_2.err
@@ -4,5 +4,5 @@
   2 groups
 xmlRelaxNGValidateAttribute(name): 0
 xmlRelaxNGValidateDefinition(): validated card : -1
-error detected at relaxng.c:4887
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated addressBook : -1
diff --git a/result/relaxng/tutor9_5_3.err b/result/relaxng/tutor9_5_3.err
index e9ef2d0..5dbf9a3 100644
--- a/result/relaxng/tutor9_5_3.err
+++ b/result/relaxng/tutor9_5_3.err
@@ -5,5 +5,5 @@
 xmlRelaxNGValidateAttribute(name): 0
 xmlRelaxNGValidateAttribute(email): 0
 xmlRelaxNGValidateDefinition(): validated card : -1
-error detected at relaxng.c:4887
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated addressBook : -1
diff --git a/result/relaxng/tutor9_6_2.err b/result/relaxng/tutor9_6_2.err
index fc02523..856cc70 100644
--- a/result/relaxng/tutor9_6_2.err
+++ b/result/relaxng/tutor9_6_2.err
@@ -1,4 +1,4 @@
 xmlRelaxNGValidateAttribute(name): 0
 xmlRelaxNGValidateDefinition(): validated card : -1
-error detected at relaxng.c:4887
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated addressBook : -1
diff --git a/result/relaxng/tutor9_6_3.err b/result/relaxng/tutor9_6_3.err
index 2737910..fa908fc 100644
--- a/result/relaxng/tutor9_6_3.err
+++ b/result/relaxng/tutor9_6_3.err
@@ -1,5 +1,5 @@
 xmlRelaxNGValidateAttribute(name): 0
 xmlRelaxNGValidateAttribute(email): 0
 xmlRelaxNGValidateDefinition(): validated card : -1
-error detected at relaxng.c:4887
+error detected at relaxng.c:4960
 xmlRelaxNGValidateDefinition(): validated addressBook : -1
diff --git a/test/relaxng/tutor11_2.rng b/test/relaxng/tutor11_2.rng
new file mode 100644
index 0000000..038ac48
--- /dev/null
+++ b/test/relaxng/tutor11_2.rng
@@ -0,0 +1,14 @@
+<element name="card" ns="http://www.example.com"
+         xmlns="http://relaxng.org/ns/structure/1.0">
+  <zeroOrMore>
+    <attribute>
+      <anyName>
+        <except>
+          <nsName/>
+          <nsName ns=""/>
+        </except>
+      </anyName>
+    </attribute>
+  </zeroOrMore>
+  <text/>
+</element>
diff --git a/test/relaxng/tutor11_2_1.xml b/test/relaxng/tutor11_2_1.xml
new file mode 100644
index 0000000..2b84ebb
--- /dev/null
+++ b/test/relaxng/tutor11_2_1.xml
@@ -0,0 +1,5 @@
+<card xmlns="http://www.example.com"
+     xmlns:a="http://www.example.com/a" a:foo="works"
+     xmlns:b="http://www.example.com/b" b:foo="works">
+   This should work
+</card>
diff --git a/test/relaxng/tutor11_2_2.xml b/test/relaxng/tutor11_2_2.xml
new file mode 100644
index 0000000..b06b4e7
--- /dev/null
+++ b/test/relaxng/tutor11_2_2.xml
@@ -0,0 +1,5 @@
+<card xmlns="http://www.example.com"
+     xmlns:a="http://www.example.com/a" a:foo="works"
+     xmlns:b="http://www.example.com" b:foo="fails">
+   This should fail
+</card>
diff --git a/test/relaxng/tutor11_2_3.xml b/test/relaxng/tutor11_2_3.xml
new file mode 100644
index 0000000..c849c03
--- /dev/null
+++ b/test/relaxng/tutor11_2_3.xml
@@ -0,0 +1,5 @@
+<card xmlns="http://www.example.com"
+     xmlns:a="http://example.com/a" a:foo="works"
+     b="fails">
+   This should fail
+</card>