- debugXML.c hash.c tree.h valid.c : some changes related to
  the validation suport to improve speed with DocBook
- result/VC/OneID2 result/VC/OneID3 : this slightly changes
  the way validation errors get reported
Daniel
diff --git a/valid.c b/valid.c
index 822adeb..c3a0739 100644
--- a/valid.c
+++ b/valid.c
@@ -161,6 +161,8 @@
 	    (doc->extSubset == NULL)) return(0)
 
 xmlElementPtr xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name);
+static xmlElementPtr xmlGetDtdElementDesc2(xmlDtdPtr dtd, const xmlChar *name,
+	                           int create);
 xmlAttributePtr xmlScanAttributeDecl(xmlDtdPtr dtd, const xmlChar *elem);
 
 /************************************************************************
@@ -507,6 +509,7 @@
 		  xmlElementContentPtr content) {
     xmlElementPtr ret;
     xmlElementTablePtr table;
+    xmlAttributePtr oldAttributes = NULL;
     xmlChar *ns, *uqname;
 
     if (dtd == NULL) {
@@ -575,38 +578,73 @@
         return(NULL);
     }
 
-    ret = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
-    if (ret == NULL) {
-	xmlGenericError(xmlGenericErrorContext,
-		"xmlAddElementDecl: out of memory\n");
-	return(NULL);
+    /*
+     * lookup old attributes inserted on an undefined element in the
+     * internal subset.
+     */
+    if ((dtd->doc != NULL) && (dtd->doc->intSubset != NULL)) {
+	ret = xmlHashLookup2(dtd->doc->intSubset->elements, name, ns);
+	if ((ret != NULL) && (ret->etype == XML_ELEMENT_TYPE_UNDEFINED)) {
+	    oldAttributes = ret->attributes;
+	    ret->attributes = NULL;
+	    xmlHashRemoveEntry2(dtd->doc->intSubset->elements, name, ns, NULL);
+	    xmlFreeElement(ret);
+	}
     }
-    memset(ret, 0, sizeof(xmlElement));
-    ret->type = XML_ELEMENT_DECL;
 
     /*
-     * fill the structure.
+     * The element may already be present if one of its attribute
+     * was registered first
+     */
+    ret = xmlHashLookup2(table, name, ns);
+    if (ret != NULL) {
+	if (ret->etype != XML_ELEMENT_TYPE_UNDEFINED) {
+	    /*
+	     * The element is already defined in this Dtd.
+	     */
+	    VERROR(ctxt->userData, "Redefinition of element %s\n", name);
+	    if (uqname != NULL)
+		xmlFree(uqname);
+	    return(NULL);
+	}
+    } else {
+	ret = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
+	if (ret == NULL) {
+	    xmlGenericError(xmlGenericErrorContext,
+		    "xmlAddElementDecl: out of memory\n");
+	    return(NULL);
+	}
+	memset(ret, 0, sizeof(xmlElement));
+	ret->type = XML_ELEMENT_DECL;
+
+	/*
+	 * fill the structure.
+	 */
+	ret->name = xmlStrdup(name);
+	ret->prefix = ns;
+
+	/*
+	 * Validity Check:
+	 * Insertion must not fail
+	 */
+	if (xmlHashAddEntry2(table, name, ns, ret)) {
+	    /*
+	     * The element is already defined in this Dtd.
+	     */
+	    VERROR(ctxt->userData, "Redefinition of element %s\n", name);
+	    xmlFreeElement(ret);
+	    if (uqname != NULL)
+		xmlFree(uqname);
+	    return(NULL);
+	}
+    }
+
+    /*
+     * Finish to fill the structure.
      */
     ret->etype = type;
-    ret->name = xmlStrdup(name);
-    ret->prefix = ns;
     ret->content = xmlCopyElementContent(content);
-    ret->attributes = xmlScanAttributeDecl(dtd, name);
-
-    /*
-     * Validity Check:
-     * Insertion must not fail
-     */
-    if (xmlHashAddEntry2(table, name, ns, ret)) {
-	/*
-	 * The element is already defined in this Dtd.
-	 */
-	VERROR(ctxt->userData, "Redefinition of element %s\n", name);
-	xmlFreeElement(ret);
-	if (uqname != NULL)
-	    xmlFree(uqname);
-	return(NULL);
-    }
+    ret->attributes = oldAttributes;
 
     /*
      * Link it to the Dtd
@@ -910,7 +948,7 @@
 	    ret ++;
 	    if (ret > 1)
 		VERROR(ctxt->userData, 
-	       "Element %s has too may ID attributes defined : %s\n",
+	       "Element %s has too many ID attributes defined : %s\n",
 		       elem->name, cur->name);
 	}
 	cur = cur->nexth;
@@ -1078,7 +1116,7 @@
      * Validity Check:
      * Multiple ID per element
      */
-    elemDef = xmlGetDtdElementDesc(dtd, elem);
+    elemDef = xmlGetDtdElementDesc2(dtd, elem, 1);
     if (elemDef != NULL) {
         if ((type == XML_ATTRIBUTE_ID) &&
 	    (xmlScanIDAttributeDecl(NULL, elemDef) != 0))
@@ -1999,16 +2037,80 @@
     xmlChar *uqname = NULL, *prefix = NULL;
 
     if (dtd == NULL) return(NULL);
-    if (dtd->elements == NULL) return(NULL);
+    if (dtd->elements == NULL)
+	return(NULL);
     table = (xmlElementTablePtr) dtd->elements;
 
     uqname = xmlSplitQName2(name, &prefix);
-    if (uqname != NULL) {
-	cur = xmlHashLookup2(table, uqname, prefix);
-	if (prefix != NULL) xmlFree(prefix);
-	if (uqname != NULL) xmlFree(uqname);
-    } else
-	cur = xmlHashLookup2(table, name, NULL);
+    if (uqname != NULL)
+        name = uqname;
+    cur = xmlHashLookup2(table, name, prefix);
+    if (prefix != NULL) xmlFree(prefix);
+    if (uqname != NULL) xmlFree(uqname);
+    return(cur);
+}
+/**
+ * xmlGetDtdElementDesc2:
+ * @dtd:  a pointer to the DtD to search
+ * @name:  the element name
+ * @create:  create an empty description if not found
+ *
+ * Search the Dtd for the description of this element
+ *
+ * returns the xmlElementPtr if found or NULL
+ */
+
+xmlElementPtr
+xmlGetDtdElementDesc2(xmlDtdPtr dtd, const xmlChar *name, int create) {
+    xmlElementTablePtr table;
+    xmlElementPtr cur;
+    xmlChar *uqname = NULL, *prefix = NULL;
+
+    if (dtd == NULL) return(NULL);
+    if (dtd->elements == NULL) {
+	if (!create) 
+	    return(NULL);
+	/*
+	 * Create the Element table if needed.
+	 */
+	table = (xmlElementTablePtr) dtd->elements;
+	if (table == NULL) {
+	    table = xmlCreateElementTable();
+	    dtd->elements = (void *) table;
+	}
+	if (table == NULL) {
+	    xmlGenericError(xmlGenericErrorContext,
+		    "xmlGetDtdElementDesc: Table creation failed!\n");
+	    return(NULL);
+	}
+    }
+    table = (xmlElementTablePtr) dtd->elements;
+
+    uqname = xmlSplitQName2(name, &prefix);
+    if (uqname != NULL)
+        name = uqname;
+    cur = xmlHashLookup2(table, name, prefix);
+    if ((cur == NULL) && (create)) {
+	cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
+	if (cur == NULL) {
+	    xmlGenericError(xmlGenericErrorContext,
+		    "xmlGetDtdElementDesc: out of memory\n");
+	    return(NULL);
+	}
+	memset(cur, 0, sizeof(xmlElement));
+	cur->type = XML_ELEMENT_DECL;
+
+	/*
+	 * fill the structure.
+	 */
+	cur->name = xmlStrdup(name);
+	cur->prefix = xmlStrdup(prefix);
+	cur->etype = XML_ELEMENT_TYPE_UNDEFINED;
+
+	xmlHashAddEntry2(table, name, prefix, cur);
+    }
+    if (prefix != NULL) xmlFree(prefix);
+    if (uqname != NULL) xmlFree(uqname);
     return(cur);
 }
 
@@ -2169,6 +2271,8 @@
 	elemDecl = xmlGetDtdElementDesc(doc->extSubset, name);
     if (elemDecl == NULL) return(-1);
     switch (elemDecl->etype) {
+	case XML_ELEMENT_TYPE_UNDEFINED:
+	    return(-1);
 	case XML_ELEMENT_TYPE_ELEMENT:
 	    return(0);
         case XML_ELEMENT_TYPE_EMPTY:
@@ -2788,22 +2892,25 @@
 
     /* VC: Unique Element Type Declaration */
     tst = xmlGetDtdElementDesc(doc->intSubset, elem->name);
-    if ((tst != NULL ) && (tst != elem)) {
+    if ((tst != NULL ) && (tst != elem) &&
+	(tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
 	VERROR(ctxt->userData, "Redefinition of element %s\n",
 	       elem->name);
 	ret = 0;
     }
     tst = xmlGetDtdElementDesc(doc->extSubset, elem->name);
-    if ((tst != NULL ) && (tst != elem)) {
+    if ((tst != NULL ) && (tst != elem) &&
+	(tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
 	VERROR(ctxt->userData, "Redefinition of element %s\n",
 	       elem->name);
 	ret = 0;
     }
 
-    /* One ID per Element Type */
+    /* One ID per Element Type
+     * already done when registering the attribute
     if (xmlScanIDAttributeDecl(ctxt, elem) > 1) {
 	ret = 0;
-    }
+    } */
     return(ret);
 }
 
@@ -3426,6 +3533,10 @@
 
     /* Check taht the element content matches the definition */
     switch (elemDecl->etype) {
+        case XML_ELEMENT_TYPE_UNDEFINED:
+	    VERROR(ctxt->userData, "No declaration for element %s\n",
+		   elem->name);
+	    return(0);
         case XML_ELEMENT_TYPE_EMPTY:
 	    if (elem->children != NULL) {
 		VERROR(ctxt->userData,