fixing a number of issues raised by xml:id but more generally related to

* SAX2.c tree.c valid.c: fixing a number of issues raised by xml:id
  but more generally related to attributes and ID handling, fixes
  #314358 among other things
Daniel
diff --git a/ChangeLog b/ChangeLog
index 935330b..8943cb7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Sat Sep  3 15:26:31 CEST 2005 Daniel Veillard <daniel@veillard.com>
+
+	* SAX2.c tree.c valid.c: fixing a number of issues raised by xml:id
+	  but more generally related to attributes and ID handling, fixes
+	  #314358 among other things
+
 Fri Sep  2 14:26:43 CEST 2005 Daniel Veillard <daniel@veillard.com>
 
 	* encoding.c parserInternals.c: avoid passing a char[] as snprintf
diff --git a/SAX2.c b/SAX2.c
index a73fa1f..9f7edf6 100644
--- a/SAX2.c
+++ b/SAX2.c
@@ -1316,11 +1316,7 @@
 	 * when validating, the ID registration is done at the attribute
 	 * validation level. Otherwise we have to do specific handling here.
 	 */
-	if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
-	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
-	else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
-	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
-	else if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
+	if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
 	    /*
 	     * Add the xml:id value
 	     *
@@ -1332,7 +1328,10 @@
 			    (const char *) value, NULL);
 	    }
 	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
-	}
+	} else if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
+	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
+	else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
+	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
     }
 
 error:
@@ -2047,16 +2046,7 @@
 	 * when validating, the ID registration is done at the attribute
 	 * validation level. Otherwise we have to do specific handling here.
 	 */
-	if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
-	    /* might be worth duplicate entry points and not copy */
-	    if (dup == NULL)
-	        dup = xmlStrndup(value, valueend - value);
-	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
-	} else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
-	    if (dup == NULL)
-	        dup = xmlStrndup(value, valueend - value);
-	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
-        } else if ((prefix == ctxt->str_xml) &&
+        if ((prefix == ctxt->str_xml) &&
 	           (localname[0] == 'i') && (localname[1] == 'd') &&
 		   (localname[2] == 0)) {
 	    /*
@@ -2074,6 +2064,15 @@
 	    }
 #endif
 	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
+	} else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
+	    /* might be worth duplicate entry points and not copy */
+	    if (dup == NULL)
+	        dup = xmlStrndup(value, valueend - value);
+	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
+	} else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
+	    if (dup == NULL)
+	        dup = xmlStrndup(value, valueend - value);
+	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
 	}
     }
     if (dup != NULL)
diff --git a/tree.c b/tree.c
index 1da8400..3031d50 100644
--- a/tree.c
+++ b/tree.c
@@ -297,6 +297,7 @@
  *
  * returns NULL if it is not a Qualified Name, otherwise, update len
  *         with the lenght in byte of the prefix and return a pointer
+ *         to the start of the name without the prefix
  */
 
 const xmlChar *
@@ -1723,80 +1724,87 @@
 }
 #endif /* LIBXML_TREE_ENABLED */
 
-static xmlAttrPtr xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns, 
-           const xmlChar *name, const xmlChar *value, int eatname) {
+static xmlAttrPtr
+xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
+                   const xmlChar * name, const xmlChar * value,
+                   int eatname)
+{
     xmlAttrPtr cur;
     xmlDocPtr doc = NULL;
 
     if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) {
-		if (eatname == 1)
-			xmlFree((xmlChar *) name);
-		return(NULL);
-	}
+        if (eatname == 1)
+            xmlFree((xmlChar *) name);
+        return (NULL);
+    }
 
     /*
      * Allocate a new property and fill the fields.
      */
     cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
     if (cur == NULL) {
-		if (eatname == 1)
-			xmlFree((xmlChar *) name);
-		xmlTreeErrMemory("building attribute");
-		return(NULL);
+        if (eatname == 1)
+            xmlFree((xmlChar *) name);
+        xmlTreeErrMemory("building attribute");
+        return (NULL);
     }
     memset(cur, 0, sizeof(xmlAttr));
     cur->type = XML_ATTRIBUTE_NODE;
 
-    cur->parent = node; 
+    cur->parent = node;
     if (node != NULL) {
-	doc = node->doc;
-	cur->doc = doc;
+        doc = node->doc;
+        cur->doc = doc;
     }
-	cur->ns = ns;
+    cur->ns = ns;
 
-	if (eatname == 0) {
-		if ((doc != NULL) && (doc->dict != NULL))
-			cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1);
-		else
-			cur->name = xmlStrdup(name);
-	} else
-		cur->name = name;
+    if (eatname == 0) {
+        if ((doc != NULL) && (doc->dict != NULL))
+            cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1);
+        else
+            cur->name = xmlStrdup(name);
+    } else
+        cur->name = name;
 
     if (value != NULL) {
-	xmlChar *buffer;
-	xmlNodePtr tmp;
+        xmlChar *buffer;
+        xmlNodePtr tmp;
 
-	buffer = xmlEncodeEntitiesReentrant(doc, value);
-	cur->children = xmlStringGetNodeList(doc, buffer);
-	cur->last = NULL;
-	tmp = cur->children;
-	while (tmp != NULL) {
-	    tmp->parent = (xmlNodePtr) cur;
-	    if (tmp->next == NULL)
-		cur->last = tmp;
-	    tmp = tmp->next;
-	}
-	xmlFree(buffer);
-    }	
+        buffer = xmlEncodeEntitiesReentrant(doc, value);
+        cur->children = xmlStringGetNodeList(doc, buffer);
+        cur->last = NULL;
+        tmp = cur->children;
+        while (tmp != NULL) {
+            tmp->parent = (xmlNodePtr) cur;
+            if (tmp->next == NULL)
+                cur->last = tmp;
+            tmp = tmp->next;
+        }
+        xmlFree(buffer);
+    }
 
     /*
      * Add it at the end to preserve parsing order ...
      */
     if (node != NULL) {
-	if (node->properties == NULL) {
-	    node->properties = cur;
-	} else {
-	    xmlAttrPtr prev = node->properties;
+        if (node->properties == NULL) {
+            node->properties = cur;
+        } else {
+            xmlAttrPtr prev = node->properties;
 
-	    while (prev->next != NULL) prev = prev->next;
-	    prev->next = cur;
-	    cur->prev = prev;
-	}
+            while (prev->next != NULL)
+                prev = prev->next;
+            prev->next = cur;
+            cur->prev = prev;
+        }
     }
 
+    if (xmlIsID((node == NULL) ? NULL : node->doc, node, cur) == 1)
+        xmlAddID(NULL, node->doc, value, cur);
+
     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
-	xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
-    return(cur);
+        xmlRegisterNodeDefaultValue((xmlNodePtr) cur);
+    return (cur);
 }
 
 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
@@ -6316,16 +6324,36 @@
 xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
     xmlAttrPtr prop;
     xmlDocPtr doc;
+    int len;
+    const xmlChar *nqname;
 
     if ((node == NULL) || (name == NULL) || (node->type != XML_ELEMENT_NODE))
 	return(NULL);
+
+    /*
+     * handle QNames
+     */
+    nqname = xmlSplitQName3(name, &len);
+    if (nqname != NULL) {
+        xmlNsPtr ns;
+	xmlChar *prefix = xmlStrndup(name, len);
+	ns = xmlSearchNs(node->doc, node, prefix);
+	if (prefix != NULL)
+	    xmlFree(prefix);
+	if (ns != NULL)
+	    return(xmlSetNsProp(node, ns, nqname, value));
+    }
+
     doc = node->doc;
     prop = node->properties;
     while (prop != NULL) {
         if ((xmlStrEqual(prop->name, name)) &&
 	    (prop->ns == NULL)){
 	    xmlNodePtr oldprop = prop->children;
+	    int id = xmlIsID(node->doc, node, prop);
 
+	    if (id == 1)
+	        xmlRemoveID(node->doc, prop);
 	    prop->children = NULL;
 	    prop->last = NULL;
 	    if (value != NULL) {
@@ -6348,6 +6376,8 @@
 	    }
 	    if (oldprop != NULL) 
 	        xmlFreeNodeList(oldprop);
+	    if (id)
+	        xmlAddID(NULL, node->doc, value, prop);
 	    return(prop);
 	}
 	prop = prop->next;
@@ -6390,6 +6420,10 @@
 	 */
         if ((xmlStrEqual(prop->name, name)) &&
 	    (prop->ns != NULL) && (xmlStrEqual(prop->ns->href, ns->href))) {
+	    int id = xmlIsID(node->doc, node, prop);
+
+	    if (id == 1)
+	        xmlRemoveID(node->doc, prop);
 	    if (prop->children != NULL) 
 	        xmlFreeNodeList(prop->children);
 	    prop->children = NULL;
@@ -6411,6 +6445,8 @@
 		}
 		xmlFree(buffer);
 	    }	
+	    if (id)
+	        xmlAddID(NULL, node->doc, value, prop);
 	    return(prop);
         }
 	prop = prop->next;
diff --git a/valid.c b/valid.c
index c0141ff..3ee5630 100644
--- a/valid.c
+++ b/valid.c
@@ -2703,8 +2703,12 @@
  */
 int
 xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
+    if ((attr == NULL) || (attr->name == NULL)) return(0);
+    if ((attr->ns != NULL) && (attr->ns->prefix != NULL) &&
+        (!strcmp((char *) attr->name, "id")) &&
+        (!strcmp((char *) attr->ns->prefix, "xml")))
+	return(1);
     if (doc == NULL) return(0);
-    if (attr == NULL) return(0);
     if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) {
 	return(0);
     } else if (doc->type == XML_HTML_DOCUMENT_NODE) {