Release 1.6, lot of fixes, more validation, code cleanup, added namespace
on attributes, Daniel.
diff --git a/tree.c b/tree.c
index 7c61ea5..34c927a 100644
--- a/tree.c
+++ b/tree.c
@@ -3,8 +3,6 @@
  *
  * See Copyright for the status of this software.
  *
- * TODO Cleanup the Dump mechanism.
- *
  * Daniel.Veillard@w3.org
  */
 
@@ -395,6 +393,7 @@
     cur->encoding = NULL;
     cur->standalone = -1;
     cur->compression = xmlCompressMode;
+    cur->ids = NULL;
 #ifndef XML_WITHOUT_CORBA
     cur->_private = NULL;
     cur->vepv = NULL;
@@ -424,6 +423,7 @@
     if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
     if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
     if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
+    if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
     memset(cur, -1, sizeof(xmlDoc));
     free(cur);
 }
@@ -738,6 +738,66 @@
 
     cur->type = XML_ATTRIBUTE_NODE;
     cur->node = node; 
+    cur->ns = NULL;
+    cur->name = xmlStrdup(name);
+    if (value != NULL)
+	cur->val = xmlStringGetNodeList(node->doc, value);
+    else 
+	cur->val = NULL;
+#ifndef XML_WITHOUT_CORBA
+    cur->_private = NULL;
+    cur->vepv = NULL;
+#endif
+
+    /*
+     * Add it at the end to preserve parsing order ...
+     */
+    cur->next = NULL;
+    if (node != NULL) {
+	if (node->properties == NULL) {
+	    node->properties = cur;
+	} else {
+	    xmlAttrPtr prev = node->properties;
+
+	    while (prev->next != NULL) prev = prev->next;
+	    prev->next = cur;
+	}
+    }
+    return(cur);
+}
+
+/**
+ * xmlNewNsProp:
+ * @node:  the holding node
+ * @ns:  the namespace
+ * @name:  the name of the attribute
+ * @value:  the value of the attribute
+ *
+ * Create a new property tagged with a namespace and carried by a node.
+ * Returns a pointer to the attribute
+ */
+xmlAttrPtr
+xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const CHAR *name,
+           const CHAR *value) {
+    xmlAttrPtr cur;
+
+    if (name == NULL) {
+        fprintf(stderr, "xmlNewProp : name == NULL\n");
+	return(NULL);
+    }
+
+    /*
+     * Allocate a new property and fill the fields.
+     */
+    cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
+    if (cur == NULL) {
+        fprintf(stderr, "xmlNewProp : malloc failed\n");
+	return(NULL);
+    }
+
+    cur->type = XML_ATTRIBUTE_NODE;
+    cur->node = node; 
+    cur->ns = ns;
     cur->name = xmlStrdup(name);
     if (value != NULL)
 	cur->val = xmlStringGetNodeList(node->doc, value);
@@ -847,6 +907,54 @@
 }
 
 /**
+ * xmlNewPI:
+ * @name:  the processing instruction name
+ * @content:  the PI content
+ *
+ * Creation of a processing instruction element.
+ * Returns a pointer to the new node object.
+ */
+xmlNodePtr
+xmlNewPI(const CHAR *name, const CHAR *content) {
+    xmlNodePtr cur;
+
+    if (name == NULL) {
+        fprintf(stderr, "xmlNewPI : name == NULL\n");
+	return(NULL);
+    }
+
+    /*
+     * Allocate a new node and fill the fields.
+     */
+    cur = (xmlNodePtr) malloc(sizeof(xmlNode));
+    if (cur == NULL) {
+        fprintf(stderr, "xmlNewPI : malloc failed\n");
+	return(NULL);
+    }
+
+    cur->type = XML_PI_NODE;
+    cur->doc = NULL;
+    cur->parent = NULL; 
+    cur->next = NULL;
+    cur->prev = NULL;
+    cur->childs = NULL;
+    cur->last = NULL;
+    cur->properties = NULL;
+    cur->name = xmlStrdup(name);
+    cur->ns = NULL;
+    cur->nsDef = NULL;
+    if (content != NULL)
+	cur->content = xmlStrdup(content);
+    else
+	cur->content = NULL;
+#ifndef XML_WITHOUT_CORBA
+    cur->_private = NULL;
+    cur->vepv = NULL;
+#endif
+    return(cur);
+}
+
+/**
  * xmlNewNode:
  * @ns:  namespace if any
  * @name:  the node name
@@ -1240,6 +1348,50 @@
 }
 
 /**
+ * xmlAddSibling:
+ * @cur:  the child node
+ * @elem:  the new node
+ *
+ * Add a new element to the list of siblings of @cur
+ * Returns the element or NULL in case of error.
+ */
+xmlNodePtr
+xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
+    xmlNodePtr parent;
+
+    if (cur == NULL) {
+        fprintf(stderr, "xmlAddSibling : cur == NULL\n");
+	return(NULL);
+    }
+
+    if (elem == NULL) {
+        fprintf(stderr, "xmlAddSibling : elem == NULL\n");
+	return(NULL);
+    }
+
+    if ((cur->doc != NULL) && (elem->doc != NULL) &&
+        (cur->doc != elem->doc)) {
+	fprintf(stderr, 
+	        "xmlAddSibling: Elements moved to a different document\n");
+    }
+
+    while (cur->next != NULL) cur = cur->next;
+
+    if (elem->doc == NULL)
+	elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
+
+    parent = cur->parent;
+    elem->prev = cur;
+    elem->next = NULL;
+    elem->parent = parent;
+    cur->next = elem;
+    if (parent != NULL)
+	parent->last = elem;
+
+    return(elem);
+}
+
+/**
  * xmlAddChild:
  * @parent:  the parent node
  * @cur:  the child node
@@ -1451,6 +1603,7 @@
 
 /**
  * xmlCopyProp:
+ * @target:  the element where the attribute will be grafted
  * @cur:  the attribute
  *
  * Do a copy of the attribute.
@@ -1458,7 +1611,7 @@
  * Returns: a new xmlAttrPtr, or NULL in case of error.
  */
 xmlAttrPtr
-xmlCopyProp(xmlAttrPtr cur) {
+xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
     xmlAttrPtr ret;
 
     if (cur == NULL) return(NULL);
@@ -1467,6 +1620,15 @@
     else
 	ret = xmlNewDocProp(NULL, cur->name, NULL);
     if (ret == NULL) return(NULL);
+    
+    if ((cur->ns != NULL) && (target != NULL)) {
+        xmlNsPtr ns;
+
+	ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
+	ret->ns = ns;
+    } else
+        ret->ns = NULL;
+
     if (cur->val != NULL)
 	ret->val = xmlCopyNodeList(cur->val);
     return(ret);
@@ -1474,6 +1636,7 @@
 
 /**
  * xmlCopyPropList:
+ * @target:  the element where the attributes will be grafted
  * @cur:  the first attribute
  *
  * Do a copy of an attribute list.
@@ -1481,12 +1644,12 @@
  * Returns: a new xmlAttrPtr, or NULL in case of error.
  */
 xmlAttrPtr
-xmlCopyPropList(xmlAttrPtr cur) {
+xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
     xmlAttrPtr ret = NULL;
     xmlAttrPtr p = NULL,q;
 
     while (cur != NULL) {
-        q = xmlCopyProp(cur);
+        q = xmlCopyProp(target, cur);
 	if (p == NULL) {
 	    ret = p = q;
 	} else {
@@ -1557,8 +1720,6 @@
         xmlAddChild(parent, ret);
     
     if (!recursive) return(ret);
-    if (node->properties != NULL)
-        ret->properties = xmlCopyPropList(node->properties);
     if (node->nsDef != NULL)
         ret->nsDef = xmlCopyNamespaceList(node->nsDef);
 
@@ -1586,6 +1747,8 @@
 	    ret->ns = ns;
 	}
     }
+    if (node->properties != NULL)
+        ret->properties = xmlCopyPropList(ret, node->properties);
     if (node->childs != NULL)
         ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
     UPDATE_LAST_CHILD(ret)
@@ -1699,9 +1862,6 @@
     if (dtd->attributes != NULL)
         ret->attributes = (void *) xmlCopyAttributeTable(
 	                    (xmlAttributeTablePtr) dtd->attributes);
-    /*
-     * TODO: support for Element definitions.
-     */
     return(ret);
 }
 
@@ -1746,6 +1906,44 @@
  ************************************************************************/
  
 /**
+ * xmlNodeSetLang:
+ * @cur:  the node being changed
+ * @lang:  the langage description
+ *
+ * Searches the language of a node, i.e. the values of the xml:lang
+ * attribute or the one carried by the nearest ancestor.
+ *
+ * Returns a pointer to the lang value, or NULL if not found
+ */
+void
+xmlNodeSetLang(xmlNodePtr cur, const CHAR *lang) {
+    /* TODO xmlNodeSetLang check against the production [33] LanguageID */
+    xmlSetProp(cur, BAD_CAST "xml:lang", lang);
+}
+ 
+/**
+ * xmlNodeGetLang:
+ * @cur:  the node being checked
+ *
+ * Searches the language of a node, i.e. the values of the xml:lang
+ * attribute or the one carried by the nearest ancestor.
+ *
+ * Returns a pointer to the lang value, or NULL if not found
+ */
+const CHAR *
+xmlNodeGetLang(xmlNodePtr cur) {
+    const CHAR *lang;
+
+    while (cur != NULL) {
+        lang = xmlGetProp(cur, BAD_CAST "xml:lang");
+	if (lang != NULL)
+	    return(lang);
+	cur = cur->parent;
+    }
+    return(NULL);
+}
+ 
+/**
  * xmlNodeGetContent:
  * @cur:  the node being read
  *
@@ -1764,10 +1962,20 @@
         case XML_ELEMENT_NODE:
             return(xmlNodeListGetString(cur->doc, cur->childs, 1));
 	    break;
-        case XML_ATTRIBUTE_NODE:
+        case XML_ATTRIBUTE_NODE: {
+	    xmlAttrPtr attr = (xmlAttrPtr) cur;
+	    if (attr->node != NULL)
+		return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
+	    else
+		return(xmlNodeListGetString(NULL, attr->val, 1));
+	    break;
+	}
+        case XML_PI_NODE:
+	    if (cur->content != NULL)
+	        return(xmlStrdup(cur->content));
+	    return(NULL);
         case XML_ENTITY_REF_NODE:
         case XML_ENTITY_NODE:
-        case XML_PI_NODE:
         case XML_COMMENT_NODE:
         case XML_DOCUMENT_NODE:
         case XML_DOCUMENT_TYPE_NODE:
@@ -1821,6 +2029,7 @@
 		cur->content = xmlStrdup(content);
 	    else 
 		cur->content = NULL;
+	    break;
         case XML_DOCUMENT_NODE:
         case XML_DOCUMENT_TYPE_NODE:
 	    break;
@@ -1869,6 +2078,7 @@
 		cur->content = xmlStrndup(content, len);
 	    else 
 		cur->content = NULL;
+	    break;
         case XML_DOCUMENT_NODE:
         case XML_DOCUMENT_TYPE_NODE:
 	    break;
@@ -1985,6 +2195,60 @@
 }
 
 /**
+ * xmlGetNsList:
+ * @doc:  the document
+ * @node:  the current node
+ *
+ * Search all the namespace applying to a given element.
+ * Returns an NULL terminated array of all the xmlNsPtr found
+ *         that need to be freed by the caller or NULL if no
+ *         namespace if defined
+ */
+xmlNsPtr *
+xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
+    xmlNsPtr cur;
+    xmlNsPtr *ret = NULL;
+    int nbns = 0;
+    int maxns = 10;
+    int i;
+
+    while (node != NULL) {
+	cur = node->nsDef;
+	while (cur != NULL) {
+	    if (ret == NULL) {
+	        ret = (xmlNsPtr *) malloc((maxns + 1) * sizeof(xmlNsPtr));
+		if (ret == NULL) {
+		    fprintf(stderr, "xmlGetNsList : out of memory!\n");
+		    return(NULL);
+		}
+		ret[nbns] = NULL;
+	    }
+	    for (i = 0;i < nbns;i++) {
+	        if ((cur->prefix == ret[i]->prefix) ||
+		    (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
+	    }
+	    if (i >= nbns) {
+	        if (nbns >= maxns) {
+		    maxns *= 2;
+		    ret = (xmlNsPtr *) realloc(ret,
+		                         (maxns + 1) * sizeof(xmlNsPtr));
+		    if (ret == NULL) {
+			fprintf(stderr, "xmlGetNsList : realloc failed!\n");
+			return(NULL);
+		    }
+		}
+		ret[nbns++] = cur;
+		ret[nbns] = NULL;
+	    }
+
+	    cur = cur->next;
+	}
+	node = node->parent;
+    }
+    return(ret);
+}
+
+/**
  * xmlSearchNs:
  * @doc:  the document
  * @node:  the current node
@@ -2077,7 +2341,7 @@
 	    CHAR *ret;
 
 	    ret = xmlNodeListGetString(node->doc, prop->val, 1);
-	    if (ret == NULL) return(xmlStrdup(""));
+	    if (ret == NULL) return(xmlStrdup((CHAR *)""));
 	    return(ret);
         }
 	prop = prop->next;
@@ -2401,11 +2665,8 @@
  */
 void
 xmlBufferWriteQuotedString(xmlBufferPtr buf, const CHAR *string) {
-    /*
-     * TODO: fix strchr by xmlStrchr to work coreectly on UTF-8 !!!
-     */
-    if (strchr(string, '"')) {
-        if (strchr(string, '\'')) {
+    if (xmlStrchr(string, '"')) {
+        if (xmlStrchr(string, '\'')) {
 	    fprintf(stderr,
  "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
 	}
@@ -2546,7 +2807,6 @@
 	xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
     xmlBufferWriteChar(buf, "]");
 
-    /* TODO !!! a lot more things to dump ... */
     xmlBufferWriteChar(buf, ">\n");
 }
 
@@ -2567,6 +2827,10 @@
 	return;
     }
     xmlBufferWriteChar(buf, " ");
+    if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+        xmlBufferWriteCHAR(buf, cur->ns->prefix);
+	xmlBufferWriteChar(buf, ":");
+    }
     xmlBufferWriteCHAR(buf, cur->name);
     value = xmlNodeListGetString(doc, cur->val, 0);
     if (value) {
@@ -2663,11 +2927,23 @@
 	}
 	return;
     }
+    if (cur->type == XML_PI_NODE) {
+	if (cur->content != NULL) {
+	    xmlBufferWriteChar(buf, "<?");
+	    xmlBufferWriteCHAR(buf, cur->name);
+	    if (cur->content != NULL) {
+		xmlBufferWriteChar(buf, " ");
+		xmlBufferWriteCHAR(buf, cur->content);
+	    }
+	    xmlBufferWriteChar(buf, "?>\n");
+	}
+	return;
+    }
     if (cur->type == XML_COMMENT_NODE) {
 	if (cur->content != NULL) {
 	    xmlBufferWriteChar(buf, "<!--");
 	    xmlBufferWriteCHAR(buf, cur->content);
-	    xmlBufferWriteChar(buf, "-->");
+	    xmlBufferWriteChar(buf, "-->\n");
 	}
 	return;
     }
@@ -2757,12 +3033,18 @@
     if (cur->intSubset != NULL)
         xmlDtdDump(buf, cur);
     if (cur->root != NULL) {
+        xmlNodePtr child = cur->root;
+
 	/* global namespace definitions, the old way */
 	if (oldXMLWDcompatibility)
 	    xmlGlobalNsListDump(buf, cur->oldNs);
 	else 
 	    xmlUpgradeOldNs(cur);
-        xmlNodeDump(buf, cur, cur->root, 0);
+	
+	while (child != NULL) {
+	    xmlNodeDump(buf, cur, child, 0);
+	    child = child->next;
+	}
     }
 }