Added copy operations for node/tree/documents, Daniel.
diff --git a/ChangeLog b/ChangeLog
index 15040f5..b40957e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Fri Nov 27 01:36:54 EST 1998 Daniel Veillard <Daniel.Veillard@w3.org>
+
+	* entities.[ch], tree.[ch], tester.c: added copy interfaces
+	  for node/trees/documents/... Biggest problem is namespace
+	  support when copying subtrees.
+
 Sun Nov 15 19:59:47 EST 1998 Daniel Veillard <Daniel.Veillard@w3.org>
 
 	* parser.c, entities.c: improve entities and char ref encoding,
diff --git a/entities.c b/entities.c
index 28a3582..30506cb 100644
--- a/entities.c
+++ b/entities.c
@@ -31,6 +31,9 @@
 
 /*
  * A buffer used for converting entities to their equivalent and back.
+ *
+ * TODO: remove this, this helps performances but forbid reentrancy in a 
+ *       stupid way.
  */
 static int buffer_size = 0;
 static CHAR *buffer = NULL;
@@ -47,7 +50,6 @@
 /*
  * xmlFreeEntity : clean-up an entity record.
  */
-
 void xmlFreeEntity(xmlEntityPtr entity) {
     if (entity == NULL) return;
 
@@ -63,12 +65,13 @@
 }
 
 /*
- * xmlAddDocEntity : register a new entity for an entities table.
+ * xmlAddEntity : register a new entity for an entities table.
  *
  * TODO !!! We should check here that the combination of type
  *          ExternalID and SystemID is valid.
  */
-static void xmlAddEntity(xmlEntitiesTablePtr table, const CHAR *name, int type,
+static void
+xmlAddEntity(xmlEntitiesTablePtr table, const CHAR *name, int type,
               const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
     int i;
     xmlEntityPtr cur;
@@ -116,8 +119,10 @@
     table->nb_entities++;
 }
 
-/*
- * Set up xmlPredefinedEntities from xmlPredefinedEntityValues.
+/**
+ * xmlInitializePredefinedEntities:
+ *
+ * Set up the predefined entities.
  */
 void xmlInitializePredefinedEntities(void) {
     int i;
@@ -165,12 +170,19 @@
     return(NULL);
 }
 
-
-
-/*
- * xmlAddDtdEntity : register a new entity for this DTD.
+/**
+ * xmlAddDtdEntity:
+ * @doc:  the document
+ * @name:  the entity name
+ * @type:  the entity type XML_xxx_yyy_ENTITY
+ * @ExternalID:  the entity external ID if available
+ * @SystemID:  the entity system ID if available
+ * @content:  the entity content
+ *
+ * Register a new entity for this document DTD.
  */
-void xmlAddDtdEntity(xmlDocPtr doc, const CHAR *name, int type,
+void
+xmlAddDtdEntity(xmlDocPtr doc, const CHAR *name, int type,
               const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
     xmlEntitiesTablePtr table;
 
@@ -186,10 +198,19 @@
     xmlAddEntity(table, name, type, ExternalID, SystemID, content);
 }
 
-/*
- * xmlAddDocEntity : register a new entity for this document.
+/**
+ * xmlAddDocEntity:
+ * @doc:  the document
+ * @name:  the entity name
+ * @type:  the entity type XML_xxx_yyy_ENTITY
+ * @ExternalID:  the entity external ID if available
+ * @SystemID:  the entity system ID if available
+ * @content:  the entity content
+ *
+ * Register a new entity for this document.
  */
-void xmlAddDocEntity(xmlDocPtr doc, const CHAR *name, int type,
+void
+xmlAddDocEntity(xmlDocPtr doc, const CHAR *name, int type,
               const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
     xmlEntitiesTablePtr table;
 
@@ -201,11 +222,18 @@
     xmlAddEntity(doc->entities, name, type, ExternalID, SystemID, content);
 }
 
-/*
- * xmlGetDtdEntity : do an entity lookup in the Dtd entity hash table and
- *       returns the corrsponding entity, if found, NULL otherwise.
+/**
+ * xmlGetDtdEntity:
+ * @doc:  the document referencing the entity
+ * @name:  the entity name
+ *
+ * Do an entity lookup in the Dtd entity hash table and
+ * returns the corresponding entity, if found.
+ * 
+ * return values: A pointer to the entity structure or NULL if not found.
  */
-xmlEntityPtr xmlGetDtdEntity(xmlDocPtr doc, const CHAR *name) {
+xmlEntityPtr
+xmlGetDtdEntity(xmlDocPtr doc, const CHAR *name) {
     int i;
     xmlEntityPtr cur;
     xmlEntitiesTablePtr table;
@@ -220,12 +248,19 @@
     return(NULL);
 }
 
-/*
- * xmlGetDocEntity : do an entity lookup in the document entity hash table and
- *       returns the corrsponding entity, otherwise a lookup is done
- *       in the predefined entities too.
+/**
+ * xmlGetDocEntity:
+ * @doc:  the document referencing the entity
+ * @name:  the entity name
+ *
+ * Do an entity lookup in the document entity hash table and
+ * returns the corrsponding entity, otherwise a lookup is done
+ * in the predefined entities too.
+ * 
+ * return values: A pointer to the entity structure or NULL if not found.
  */
-xmlEntityPtr xmlGetDocEntity(xmlDocPtr doc, const CHAR *name) {
+xmlEntityPtr
+xmlGetDocEntity(xmlDocPtr doc, const CHAR *name) {
     int i;
     xmlEntityPtr cur;
     xmlEntitiesTablePtr table;
@@ -257,15 +292,24 @@
     (((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) ||			\
      (((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF)))
 
-/*
- * xmlEncodeEntities : do a global encoding of a string, replacing the
- *                     predefined entities and non ASCII values with their
- *                     entities and CharRef counterparts.
+/**
+ * xmlEncodeEntities:
+ * @doc:  the document containing the string
+ * @input:  A string to convert to XML.
+ *
+ * Do a global encoding of a string, replacing the predefined entities
+ * and non ASCII values with their entities and CharRef counterparts.
+ *
  * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
  *           get erroneous.
+ *
+ * TODO This routine is not reentrant and this will be changed, the interface
+ *      should not be modified though.
+ * 
+ * return values: A newly allocated string with the substitution done.
  */
-
-CHAR *xmlEncodeEntities(xmlDocPtr doc, const CHAR *input) {
+CHAR *
+xmlEncodeEntities(xmlDocPtr doc, const CHAR *input) {
     const CHAR *cur = input;
     CHAR *out = buffer;
 
@@ -363,10 +407,15 @@
     return(buffer);
 }
 
-/*
- * xmlCreateEntitiesTable : create and initialize an enmpty hash table
+/**
+ * xmlCreateEntitiesTable:
+ *
+ * create and initialize an empty entities hash table.
+ *
+ * return values: the xmlEntitiesTablePtr just created or NULL in case of error.
  */
-xmlEntitiesTablePtr xmlCreateEntitiesTable(void) {
+xmlEntitiesTablePtr
+xmlCreateEntitiesTable(void) {
     xmlEntitiesTablePtr ret;
 
     ret = (xmlEntitiesTablePtr) 
@@ -389,10 +438,14 @@
     return(ret);
 }
 
-/*
- * xmlFreeEntitiesTable : clean up and free an entities hash table.
+/**
+ * xmlFreeEntitiesTable:
+ * @table:  An entity table
+ *
+ * Deallocate the memory used by an entities hash table.
  */
-void xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
+void
+xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
     int i;
 
     if (table == NULL) return;
@@ -404,10 +457,70 @@
     free(table);
 }
 
-/*
- * Dump the content of an entity table to the document output.
+/**
+ * xmlCopyEntitiesTable:
+ * @table:  An entity table
+ *
+ * Build a copy of an entity table.
+ * 
+ * return values: the new xmlEntitiesTablePtr or NULL in case of error.
  */
-void xmlDumpEntitiesTable(xmlEntitiesTablePtr table) {
+xmlEntitiesTablePtr
+xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
+    xmlEntitiesTablePtr ret;
+    xmlEntityPtr cur, ent;
+    int i;
+
+    ret = (xmlEntitiesTablePtr) malloc(sizeof(xmlEntitiesTable));
+    if (ret == NULL) {
+        fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
+	return(NULL);
+    }
+    ret->table = (xmlEntityPtr) malloc(table->max_entities *
+                                         sizeof(xmlEntity));
+    if (ret->table == NULL) {
+        fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
+	free(ret);
+	return(NULL);
+    }
+    ret->max_entities = table->max_entities;
+    ret->nb_entities = table->nb_entities;
+    for (i = 0;i < ret->nb_entities;i++) {
+	cur = &ret->table[i];
+	ent = &table->table[i];
+	cur->len = ent->len;
+	cur->type = ent->type;
+	if (ent->name != NULL)
+	    cur->name = xmlStrdup(ent->name);
+	else
+	    cur->name = NULL;
+	if (ent->ExternalID != NULL)
+	    cur->ExternalID = xmlStrdup(ent->ExternalID);
+	else
+	    cur->ExternalID = NULL;
+	if (ent->SystemID != NULL)
+	    cur->SystemID = xmlStrdup(ent->SystemID);
+	else
+	    cur->SystemID = NULL;
+	if (ent->content != NULL)
+	    cur->content = xmlStrdup(ent->content);
+	else
+	    cur->content = NULL;
+    }
+    return(ret);
+}
+
+/**
+ * xmlDumpEntitiesTable:
+ * @table:  An entity table
+ *
+ * This will dump the content of the entity table as an XML DTD definition
+ *
+ * NOTE: TODO an extra parameter allowing a reentant implementation will
+ *       be added.
+ */
+void
+xmlDumpEntitiesTable(xmlEntitiesTablePtr table) {
     int i;
     xmlEntityPtr cur;
 
diff --git a/entities.h b/entities.h
index f6b03c3..0830101 100644
--- a/entities.h
+++ b/entities.h
@@ -46,7 +46,7 @@
 typedef struct xmlEntitiesTable {
     int nb_entities;		/* number of elements stored */
     int max_entities;		/* maximum number of elements */
-    xmlEntityPtr table;		/* the table of entities */
+    xmlEntityPtr table;	        /* the table of entities */
 } xmlEntitiesTable, *xmlEntitiesTablePtr;
 
 
@@ -63,10 +63,12 @@
 extern xmlEntityPtr xmlGetDtdEntity(xmlDocPtr doc, const CHAR *name);
 extern CHAR *xmlEncodeEntities(xmlDocPtr doc, const CHAR *input);
 extern xmlEntitiesTablePtr xmlCreateEntitiesTable(void);
+extern xmlEntitiesTablePtr xmlCopyEntitiesTable(xmlEntitiesTablePtr table);
 extern void xmlFreeEntitiesTable(xmlEntitiesTablePtr table);
 extern void xmlDumpEntitiesTable(xmlEntitiesTablePtr table);
 extern xmlParserInputPtr xmlNewEntityInputStream(xmlParserCtxtPtr ctxt,
                                                  xmlEntityPtr entity);
+extern xmlEntitiesTablePtr xmlCopyEntitiesTable(xmlEntitiesTablePtr table);
 
 #ifdef __cplusplus
 }
diff --git a/include/libxml/entities.h b/include/libxml/entities.h
index f6b03c3..0830101 100644
--- a/include/libxml/entities.h
+++ b/include/libxml/entities.h
@@ -46,7 +46,7 @@
 typedef struct xmlEntitiesTable {
     int nb_entities;		/* number of elements stored */
     int max_entities;		/* maximum number of elements */
-    xmlEntityPtr table;		/* the table of entities */
+    xmlEntityPtr table;	        /* the table of entities */
 } xmlEntitiesTable, *xmlEntitiesTablePtr;
 
 
@@ -63,10 +63,12 @@
 extern xmlEntityPtr xmlGetDtdEntity(xmlDocPtr doc, const CHAR *name);
 extern CHAR *xmlEncodeEntities(xmlDocPtr doc, const CHAR *input);
 extern xmlEntitiesTablePtr xmlCreateEntitiesTable(void);
+extern xmlEntitiesTablePtr xmlCopyEntitiesTable(xmlEntitiesTablePtr table);
 extern void xmlFreeEntitiesTable(xmlEntitiesTablePtr table);
 extern void xmlDumpEntitiesTable(xmlEntitiesTablePtr table);
 extern xmlParserInputPtr xmlNewEntityInputStream(xmlParserCtxtPtr ctxt,
                                                  xmlEntityPtr entity);
+extern xmlEntitiesTablePtr xmlCopyEntitiesTable(xmlEntitiesTablePtr table);
 
 #ifdef __cplusplus
 }
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
index e3764d8..3921f7e 100644
--- a/include/libxml/tree.h
+++ b/include/libxml/tree.h
@@ -155,7 +155,7 @@
     int             standalone; /* standalone document (no external refs) */
     struct xmlDtd  *dtd;	/* the document DTD if available */
     struct xmlNs   *oldNs;	/* Global namespace, the old way */
-    void          *entities;    /* Hash table for general entities if any */
+    void           *entities;   /* Hash table for general entities if any */
     struct xmlNode *root;	/* the document tree */
 } xmlDoc, *xmlDocPtr;
 
@@ -183,6 +183,10 @@
                              const CHAR *value);
 extern void xmlFreePropList(xmlAttrPtr cur);
 extern void xmlFreeProp(xmlAttrPtr cur);
+extern xmlAttrPtr xmlCopyProp(xmlAttrPtr cur);
+extern xmlAttrPtr xmlCopyPropList(xmlAttrPtr cur);
+extern xmlDtdPtr xmlCopyDtd(xmlDtdPtr dtd);
+extern xmlDocPtr xmlCopyDoc(xmlDocPtr doc, int recursive);
 
 /*
  * Creating new nodes
@@ -199,6 +203,8 @@
 extern xmlNodePtr xmlNewDocComment(xmlDocPtr doc, CHAR *content);
 extern xmlNodePtr xmlNewComment(CHAR *content);
 extern xmlNodePtr xmlNewReference(xmlDocPtr doc, const CHAR *name);
+extern xmlNodePtr xmlCopyNode(xmlNodePtr node, int recursive);
+extern xmlNodePtr xmlCopyNodeList(xmlNodePtr node);
 
 /*
  * Navigating
@@ -226,6 +232,8 @@
 extern xmlNsPtr xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node,
                                   const CHAR *href);
 extern void xmlSetNs(xmlNodePtr node, xmlNsPtr ns);
+extern xmlNsPtr xmlCopyNamespace(xmlNsPtr cur);
+extern xmlNsPtr xmlCopyNamespaceList(xmlNsPtr cur);
 
 /*
  * Changing the content.
diff --git a/tester.c b/tester.c
index 56d74be..6830917 100644
--- a/tester.c
+++ b/tester.c
@@ -31,6 +31,7 @@
 #include "debugXML.h"
 
 static int debug = 0;
+static int copy = 0;
 
 /*
  * Note: there is a couple of errors introduced on purpose.
@@ -63,12 +64,12 @@
  ************************************************************************/
 
 int treeTest(void) {
+    xmlDocPtr doc, tmp;
+    xmlNodePtr tree, subtree;
+
     /*
      * build a fake XML document
      */
-    xmlDocPtr doc;
-    xmlNodePtr tree, subtree;
-
     doc = xmlNewDoc("1.0");
     doc->root = xmlNewDocNode(doc, NULL, "EXAMPLE", NULL);
     xmlSetProp(doc->root, "prop1", "gnome is great");
@@ -82,6 +83,15 @@
     xmlSetProp(subtree, "href", "linus.gif");
 
     /*
+     * test intermediate copy if needed.
+     */
+    if (copy) {
+        tmp = doc;
+	doc = xmlCopyDoc(doc, 1);
+	xmlFreeDoc(tmp);
+    }
+
+    /*
      * print it.
      */
     xmlDocDump(stdout, doc);
@@ -94,7 +104,7 @@
 }
 
 void parseAndPrintFile(char *filename) {
-    xmlDocPtr doc;
+    xmlDocPtr doc, tmp;
 
     /*
      * build an XML tree from a string;
@@ -102,6 +112,15 @@
     doc = xmlParseFile(filename);
 
     /*
+     * test intermediate copy if needed.
+     */
+    if (copy) {
+        tmp = doc;
+	doc = xmlCopyDoc(doc, 1);
+	xmlFreeDoc(tmp);
+    }
+
+    /*
      * print it.
      */
     if (!debug)
@@ -116,7 +135,7 @@
 }
 
 void parseAndPrintBuffer(CHAR *buf) {
-    xmlDocPtr doc;
+    xmlDocPtr doc, tmp;
 
     /*
      * build an XML tree from a string;
@@ -124,6 +143,15 @@
     doc = xmlParseDoc(buf);
 
     /*
+     * test intermediate copy if needed.
+     */
+    if (copy) {
+        tmp = doc;
+	doc = xmlCopyDoc(doc, 1);
+	xmlFreeDoc(tmp);
+    }
+
+    /*
      * print it.
      */
     if (!debug)
@@ -139,15 +167,21 @@
 
 int main(int argc, char **argv) {
     int i;
+    int files = 0;
 
-    if (argc > 1) {
-        for (i = 1; i < argc ; i++) {
-	    if ((strcmp(argv[i], "-debug")) && (strcmp(argv[i], "--debug")))
-		parseAndPrintFile(argv[i]);
-	    else
-	        debug++;
+    for (i = 1; i < argc ; i++) {
+	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
+	    debug++;
+	else if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
+	    copy++;
+    }
+    for (i = 1; i < argc ; i++) {
+	if (argv[i][0] != '-') {
+	    parseAndPrintFile(argv[i]);
+	    files ++;
 	}
-    } else {
+    }
+    if (files == 0) {
 	printf("\nFirst test for the parser, with errors\n");
         parseAndPrintBuffer(buffer);
 	printf("\nBuilding a tree from scratch and printing it\n");
diff --git a/tree.c b/tree.c
index 9e71b4d..8251775 100644
--- a/tree.c
+++ b/tree.c
@@ -133,7 +133,7 @@
      */
     cur = (xmlNsPtr) malloc(sizeof(xmlNs));
     if (cur == NULL) {
-        fprintf(stderr, "xmlNewNs : malloc failed\n");
+        fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
 	return(NULL);
     }
 
@@ -234,7 +234,7 @@
                     const CHAR *ExternalID, const CHAR *SystemID) {
     xmlDtdPtr cur;
 
-    if (doc->dtd != NULL) {
+    if ((doc != NULL) && (doc->dtd != NULL)) {
         fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
 	/* !!! */ (char *) name, doc->name, /* !!! */ (char *)doc->dtd->name);
     }
@@ -244,7 +244,7 @@
      */
     cur = (xmlDtdPtr) malloc(sizeof(xmlDtd));
     if (cur == NULL) {
-        fprintf(stderr, "xmlNewNs : malloc failed\n");
+        fprintf(stderr, "xmlNewDtd : malloc failed\n");
 	return(NULL);
     }
 
@@ -262,7 +262,8 @@
         cur->SystemID = NULL;
     cur->elements = NULL;
     cur->entities = NULL;
-    doc->dtd = cur;
+    if (doc != NULL)
+	doc->dtd = cur;
 
     return(cur);
 }
@@ -349,6 +350,7 @@
     if (cur->encoding != NULL) free((char *) cur->encoding);
     if (cur->root != NULL) xmlFreeNode(cur->root);
     if (cur->dtd != NULL) xmlFreeDtd(cur->dtd);
+    if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
     if (cur->entities != NULL)
         xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
     memset(cur, -1, sizeof(xmlDoc));
@@ -1272,6 +1274,347 @@
 
 /************************************************************************
  *									*
+ *		Copy operations						*
+ *									*
+ ************************************************************************/
+ 
+/**
+ * xmlCopyNamespace:
+ * @cur:  the namespace
+ *
+ * Do a copy of the namespace.
+ *
+ * Returns: a new xmlNsPtr, or NULL in case of error.
+ */
+xmlNsPtr
+xmlCopyNamespace(xmlNsPtr cur) {
+    xmlNsPtr ret;
+
+    if (cur == NULL) return(NULL);
+    switch (cur->type) {
+        case XML_GLOBAL_NAMESPACE:
+	    ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
+	    break;
+	case XML_LOCAL_NAMESPACE:
+	    ret = xmlNewNs(NULL, cur->href, cur->prefix);
+	    break;
+	default:
+	    fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
+	    return(NULL);
+    }
+    return(ret);
+}
+
+/**
+ * xmlCopyNamespaceList:
+ * @cur:  the first namespace
+ *
+ * Do a copy of an namespace list.
+ *
+ * Returns: a new xmlNsPtr, or NULL in case of error.
+ */
+xmlNsPtr
+xmlCopyNamespaceList(xmlNsPtr cur) {
+    xmlNsPtr ret = NULL;
+    xmlNsPtr p = NULL,q;
+
+    while (cur != NULL) {
+        q = xmlCopyNamespace(cur);
+	if (p == NULL) {
+	    ret = p = q;
+	} else {
+	    p->next = q;
+	    p = q;
+	}
+	cur = cur->next;
+    }
+    return(ret);
+}
+
+/**
+ * xmlCopyProp:
+ * @cur:  the attribute
+ *
+ * Do a copy of the attribute.
+ *
+ * Returns: a new xmlAttrPtr, or NULL in case of error.
+ */
+xmlAttrPtr
+xmlCopyProp(xmlAttrPtr cur) {
+    xmlAttrPtr ret;
+
+    if (cur == NULL) return(NULL);
+    if (cur->val != NULL)
+	ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
+    else
+	ret = xmlNewDocProp(NULL, cur->name, NULL);
+    if (ret == NULL) return(NULL);
+    if (cur->val != NULL)
+	ret->val = xmlCopyNodeList(cur->val);
+    return(ret);
+}
+
+/**
+ * xmlCopyPropList:
+ * @cur:  the first attribute
+ *
+ * Do a copy of an attribute list.
+ *
+ * Returns: a new xmlAttrPtr, or NULL in case of error.
+ */
+xmlAttrPtr
+xmlCopyPropList(xmlAttrPtr cur) {
+    xmlAttrPtr ret = NULL;
+    xmlAttrPtr p = NULL,q;
+
+    while (cur != NULL) {
+        q = xmlCopyProp(cur);
+	if (p == NULL) {
+	    ret = p = q;
+	} else {
+	    p->next = q;
+	    p = q;
+	}
+	cur = cur->next;
+    }
+    return(ret);
+}
+
+/*
+ * NOTE about the CopyNode operations !
+ *
+ * They are splitted into external and internal parts for one
+ * tricky reason: namespaces. Doing a direct copy of a node
+ * say RPM:Copyright without changing the namespace pointer to
+ * something else can produce stale links. One way to do it is
+ * to keep a reference counter but this doesn't work as soon
+ * as one move the element or the subtree out of the scope of
+ * the existing namespace. The actual solution seems to add
+ * a copy of the namespace at the top of the copied tree if
+ * not available in the subtree.
+ * Hence two functions, the public front-end call the inner ones
+ */
+
+static xmlNodePtr
+xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
+
+static xmlNodePtr
+xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
+                  int recursive) {
+    xmlNodePtr ret;
+
+    if (node == NULL) return(NULL);
+    /*
+     * Allocate a new node and fill the fields.
+     */
+    ret = (xmlNodePtr) malloc(sizeof(xmlNode));
+    if (ret == NULL) {
+        fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
+	return(NULL);
+    }
+
+    ret->type = node->type;
+    ret->doc = doc;
+    ret->parent = parent; 
+    ret->next = NULL;
+    ret->prev = NULL;
+    ret->childs = NULL;
+    ret->properties = NULL;
+    if (node->name != NULL)
+	ret->name = xmlStrdup(node->name);
+    else
+        ret->name = NULL;
+    ret->ns = NULL;
+    ret->nsDef = NULL;
+    if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE))
+	ret->content = xmlStrdup(node->content);
+    else
+	ret->content = NULL;
+#ifndef WITHOUT_CORBA
+    ret->_private = NULL;
+    ret->vepv = NULL;
+#endif
+    if (parent != NULL)
+        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);
+
+    if (node->ns != NULL) {
+        xmlNsPtr ns;
+
+	ns = xmlSearchNs(doc, ret, node->ns->prefix);
+	if (ns == NULL) {
+	    /*
+	     * Humm, we are copying an element whose namespace is defined
+	     * out of the new tree scope. Search it in the original tree
+	     * and add it at the top of the new tree
+	     */
+	    ns = xmlSearchNs(node->doc, node, node->ns->prefix);
+	    if (ns != NULL) {
+	        xmlNodePtr root = ret;
+
+		while (root->parent != NULL) root = root->parent;
+		xmlNewNs(root, ns->href, ns->prefix);
+	    }
+	} else {
+	    /*
+	     * reference the existing namespace definition in our own tree.
+	     */
+	    ret->ns = ns;
+	}
+    }
+    if (node->childs != NULL)
+        ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
+    return(ret);
+}
+
+static xmlNodePtr
+xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
+    xmlNodePtr ret = NULL;
+    xmlNodePtr p = NULL,q;
+
+    while (node != NULL) {
+        q = xmlStaticCopyNode(node, doc, parent, 1);
+	if (parent == NULL) {
+	    if (ret == NULL) ret = q;
+	} else {
+	    if (ret == NULL) {
+		q->prev = NULL;
+		ret = p = q;
+	    } else {
+		p->next = q;
+		q->prev = p;
+		p = q;
+	    }
+	}
+	node = node->next;
+    }
+    return(ret);
+}
+
+/**
+ * xmlCopyNode:
+ * @node:  the node
+ * @recursive:  if 1 do a recursive copy.
+ *
+ * Do a copy of the node.
+ *
+ * Returns: a new xmlNodePtr, or NULL in case of error.
+ */
+xmlNodePtr
+xmlCopyNode(xmlNodePtr node, int recursive) {
+    xmlNodePtr ret;
+
+    ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
+    return(ret);
+}
+
+/**
+ * xmlCopyNodeList:
+ * @node:  the first node in the list.
+ *
+ * Do a recursive copy of the node list.
+ *
+ * Returns: a new xmlNodePtr, or NULL in case of error.
+ */
+xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
+    xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
+    return(ret);
+}
+
+/**
+ * xmlCopyElement:
+ * @elem:  the element
+ *
+ * Do a copy of the element definition.
+ *
+ * Returns: a new xmlElementPtr, or NULL in case of error.
+xmlElementPtr
+xmlCopyElement(xmlElementPtr elem) {
+    xmlElementPtr ret;
+
+    if (elem == NULL) return(NULL);
+    ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
+    if (ret == NULL) return(NULL);
+    if (!recursive) return(ret);
+    if (elem->properties != NULL)
+        ret->properties = xmlCopyPropList(elem->properties);
+    
+    if (elem->nsDef != NULL)
+        ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
+    if (elem->childs != NULL)
+        ret->childs = xmlCopyElementList(elem->childs);
+    return(ret);
+}
+ */
+
+/**
+ * xmlCopyDtd:
+ * @dtd:  the dtd
+ *
+ * Do a copy of the dtd.
+ *
+ * Returns: a new xmlDtdPtr, or NULL in case of error.
+ */
+xmlDtdPtr
+xmlCopyDtd(xmlDtdPtr dtd) {
+    xmlDtdPtr ret;
+
+    if (dtd == NULL) return(NULL);
+    ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
+    if (ret == NULL) return(NULL);
+    if (dtd->entities != NULL)
+        ret->entities = (void *) xmlCopyEntitiesTable(
+	                    (xmlEntitiesTablePtr) dtd->entities);
+    /*
+     * TODO: support for Element definitions.
+     */
+    return(ret);
+}
+
+/**
+ * xmlCopyDoc:
+ * @doc:  the document
+ * @recursive:  if 1 do a recursive copy.
+ *
+ * Do a copy of the document info. If recursive, the content tree will
+ * be copied too as well as Dtd, namespaces and entities.
+ *
+ * Returns: a new xmlDocPtr, or NULL in case of error.
+ */
+xmlDocPtr
+xmlCopyDoc(xmlDocPtr doc, int recursive) {
+    xmlDocPtr ret;
+
+    if (doc == NULL) return(NULL);
+    ret = xmlNewDoc(doc->version);
+    if (ret == NULL) return(NULL);
+    if (doc->name != NULL)
+        ret->name = strdup(doc->name);
+    if (doc->encoding != NULL)
+        ret->encoding = xmlStrdup(doc->encoding);
+    ret->compression = doc->compression;
+    ret->standalone = doc->standalone;
+    if (!recursive) return(ret);
+
+    if (doc->dtd != NULL)
+        ret->dtd = xmlCopyDtd(doc->dtd);
+    if (doc->entities != NULL)
+        ret->entities = (void *) xmlCopyEntitiesTable(
+	                    (xmlEntitiesTablePtr) doc->entities);
+    if (doc->oldNs != NULL)
+        ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
+    if (doc->root != NULL)
+        ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
+    return(ret);
+}
+
+/************************************************************************
+ *									*
  *		Content access functions				*
  *									*
  ************************************************************************/
diff --git a/tree.h b/tree.h
index e3764d8..3921f7e 100644
--- a/tree.h
+++ b/tree.h
@@ -155,7 +155,7 @@
     int             standalone; /* standalone document (no external refs) */
     struct xmlDtd  *dtd;	/* the document DTD if available */
     struct xmlNs   *oldNs;	/* Global namespace, the old way */
-    void          *entities;    /* Hash table for general entities if any */
+    void           *entities;   /* Hash table for general entities if any */
     struct xmlNode *root;	/* the document tree */
 } xmlDoc, *xmlDocPtr;
 
@@ -183,6 +183,10 @@
                              const CHAR *value);
 extern void xmlFreePropList(xmlAttrPtr cur);
 extern void xmlFreeProp(xmlAttrPtr cur);
+extern xmlAttrPtr xmlCopyProp(xmlAttrPtr cur);
+extern xmlAttrPtr xmlCopyPropList(xmlAttrPtr cur);
+extern xmlDtdPtr xmlCopyDtd(xmlDtdPtr dtd);
+extern xmlDocPtr xmlCopyDoc(xmlDocPtr doc, int recursive);
 
 /*
  * Creating new nodes
@@ -199,6 +203,8 @@
 extern xmlNodePtr xmlNewDocComment(xmlDocPtr doc, CHAR *content);
 extern xmlNodePtr xmlNewComment(CHAR *content);
 extern xmlNodePtr xmlNewReference(xmlDocPtr doc, const CHAR *name);
+extern xmlNodePtr xmlCopyNode(xmlNodePtr node, int recursive);
+extern xmlNodePtr xmlCopyNodeList(xmlNodePtr node);
 
 /*
  * Navigating
@@ -226,6 +232,8 @@
 extern xmlNsPtr xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node,
                                   const CHAR *href);
 extern void xmlSetNs(xmlNodePtr node, xmlNsPtr ns);
+extern xmlNsPtr xmlCopyNamespace(xmlNsPtr cur);
+extern xmlNsPtr xmlCopyNamespaceList(xmlNsPtr cur);
 
 /*
  * Changing the content.