Simplified usage of the internal xmlNsMap. Added a "strict" lookup for

* tree.c: Simplified usage of the internal xmlNsMap. Added a
  "strict" lookup for namespaces based on a prefix. Fixed a
  namespace processing issue in the clone-node function, which
  occured if a @ctxt argument was given.
diff --git a/tree.c b/tree.c
index 82b9014..ff3cb75 100644
--- a/tree.c
+++ b/tree.c
@@ -119,6 +119,9 @@
 	(n)->last = ulccur;						\
 }}
 
+#define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \
+  (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))
+
 /* #define DEBUG_BUFFER */
 /* #define DEBUG_TREE */
 
@@ -7207,65 +7210,131 @@
     int depth;
 };
 
+typedef struct xmlNsMap *xmlNsMapPtr;
+struct xmlNsMap {
+    xmlNsMapItemPtr first;
+    xmlNsMapItemPtr last;
+    xmlNsMapItemPtr pool;
+};
+
+#define XML_NSMAP_NOTEMPTY(m) (((m) != NULL) && ((m)->first != NULL))
+#define XML_NSMAP_FOREACH(m, i) for (i = (m)->first; i != NULL; i = (i)->next)
+#define XML_NSMAP_POP(m, i) \
+    i = (m)->last; \
+    (m)->last = (i)->prev; \
+    if ((m)->last == NULL) \
+	(m)->first = NULL; \
+    else \
+	(m)->last->next = NULL; \
+    (i)->next = (m)->pool; \
+    (m)->pool = i;
+
 /*
-* xmlTreeAddNsMapItem:
+* xmlDOMWrapNsMapFree:
+* @map: the ns-map
+* 
+* Frees the ns-map
+*/
+static void
+xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap)
+{
+    xmlNsMapItemPtr cur, tmp;
+
+    if (nsmap == NULL)
+	return;
+    cur = nsmap->pool;
+    while (cur != NULL) {
+	tmp = cur;
+	cur = cur->next;
+	xmlFree(tmp);
+    }
+    cur = nsmap->first;
+    while (cur != NULL) {
+	tmp = cur;
+	cur = cur->next;
+	xmlFree(tmp);
+    }
+    xmlFree(nsmap);
+}
+
+/*
+* xmlDOMWrapNsMapAddItem:
 * @map: the ns-map
 * @cur: the current map entry to append a new entry to
 * @oldNs: the old ns-struct
 * @newNs: the new ns-struct
 * @depth: depth and ns-kind information
 * 
-* Frees the ns-map
+* Adds an ns-mapping item.
 */
 static xmlNsMapItemPtr
-xmlDOMWrapNSNormAddNsMapItem(xmlNsMapItemPtr *map,
-			     xmlNsMapItemPtr *cur,
-			     xmlNsPtr oldNs,
-			     xmlNsPtr newNs,
-			     int depth)
+xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position, /* xmlNsMapItemPtr *cur, */
+		       xmlNsPtr oldNs, xmlNsPtr newNs, int depth)
 {
     xmlNsMapItemPtr ret;
-     
-    if ((cur != NULL) && (*cur != NULL) && ((*cur)->next != NULL)) {
+    xmlNsMapPtr map;
+
+    if (nsmap == NULL)
+	return(NULL);
+    if ((position != -1) && (position != 0))
+	return(NULL);
+    map = *nsmap;
+
+    if (map == NULL) {
 	/*
-	* Reuse.
+	* Create the ns-map.
 	*/
-	ret = (*cur)->next;
-	*cur = ret;
+	map = (xmlNsMapPtr) xmlMalloc(sizeof(struct xmlNsMap));
+	if (map == NULL) {
+	    xmlTreeErrMemory("allocating namespace map");
+	    return (NULL);
+	}
+	memset(map, 0, sizeof(struct xmlNsMap));
+	*nsmap = map;
+    }
+    
+    if (map->pool != NULL) {
+	/*
+	* Reuse an item from the pool.
+	*/
+	ret = map->pool;
+	map->pool = ret->next;
+	memset(ret, 0, sizeof(struct xmlNsMapItem));
     } else {
+	/*
+	* Create a new item.
+	*/
 	ret = (xmlNsMapItemPtr) xmlMalloc(sizeof(struct xmlNsMapItem));
 	if (ret == NULL) {
 	    xmlTreeErrMemory("allocating namespace map item");
 	    return (NULL);
 	}
 	memset(ret, 0, sizeof(struct xmlNsMapItem));
-	if (*map == NULL) {
-	    /*
-	    * First ever.
-	    */
-	    *map = ret;
-	    ret->prev = ret;
-	    if (cur != NULL)
-		*cur = ret;
-	} else {
-	    if (cur) {
-		/*
-		* Append.
-		*/
-		(*cur)->next = ret;
-		ret->prev = *cur;
-		*cur = ret;
-	    } else {
-		/*
-		* Set on first position.
-		*/
-		ret->next = (*map);
-		ret->prev = (*map)->prev;
-		(*map)->prev = ret;
-		*map = ret;
-	    }
-	}
     }
+    
+    if (map->first == NULL) {
+	/*
+	* First ever.
+	*/	 
+	map->first = ret;
+	map->last = ret;
+    } else if (position == -1) {
+	/*
+	* Append.
+	*/
+	ret->prev = map->last;
+	map->last->next = ret;
+	map->last = ret;		
+    } else if (position == 0) {
+	/*
+	* Set on first position.
+	*/
+	map->first->prev = ret;
+	ret->next = map->first;		
+	map->first = ret;		
+    } else
+	return(NULL);
+
     ret->oldNs = oldNs;
     ret->newNs = newNs;
     ret->shadowDepth = -1;
@@ -7274,24 +7343,6 @@
 }
 
 /*
-* xmlTreeFreeNsMap:
-* @map: the ns-map
-* 
-* Frees the ns-map
-*/
-static void
-xmlDOMWrapNSNormFreeNsMap(xmlNsMapItemPtr map)
-{    
-    xmlNsMapItemPtr mi = map, miprev;
-
-    while (mi != NULL) {
-	miprev = mi;
-	mi = mi->next;
-	xmlFree(miprev);
-    }
-}
-
-/*
 * xmlTreeEnsureXMLDecl:
 * @doc: the doc
 * 
@@ -7406,7 +7457,7 @@
 * Returns 0 on success, -1 on API or internal errors.
 */
 static int
-xmlDOMWrapNSNormGatherInScopeNs(xmlNsMapItemPtr *map,
+xmlDOMWrapNSNormGatherInScopeNs(xmlNsMapPtr *map,
 				xmlNodePtr node)
 {
     xmlNodePtr cur;
@@ -7426,11 +7477,11 @@
 		ns = cur->nsDef;
 		do {
 		    shadowed = 0;
-		    if (*map != NULL) {
+		    if (XML_NSMAP_NOTEMPTY(*map)) {
 			/*
 			* Skip shadowed prefixes.
 			*/
-			for (mi = *map; mi != NULL; mi = mi->next) {
+			XML_NSMAP_FOREACH(*map, mi) {
 			    if ((ns->prefix == mi->newNs->prefix) ||
 				xmlStrEqual(ns->prefix, mi->newNs->prefix)) {
 				shadowed = 1;
@@ -7441,7 +7492,7 @@
 		    /*
 		    * Insert mapping.
 		    */
-		    mi = xmlDOMWrapNSNormAddNsMapItem(map, NULL, NULL,
+		    mi = xmlDOMWrapNsMapAddItem(map, 0, NULL,
 			ns, XML_TREE_NSMAP_PARENT);
 		    if (mi == NULL)
 			return (-1);
@@ -7659,7 +7710,7 @@
 }
 
 /*
-* xmlSearchNsByHrefStrict:
+* xmlSearchNsByNamespaceStrict:
 * @doc: the document
 * @node: the start node
 * @nsName: the searched namespace name
@@ -7673,8 +7724,9 @@
 *         and internal errors.
 */
 static int
-xmlSearchNsByHrefStrict(xmlDocPtr doc, xmlNodePtr node, const xmlChar* nsName,
-			 xmlNsPtr *retNs, int prefixed)
+xmlSearchNsByNamespaceStrict(xmlDocPtr doc, xmlNodePtr node,
+			     const xmlChar* nsName,
+			     xmlNsPtr *retNs, int prefixed)
 {
     xmlNodePtr cur, prev = NULL, out = NULL;
     xmlNsPtr ns, prevns;
@@ -7750,9 +7802,72 @@
 		out = prev;
 		prev = cur;
 	    }
-	} else if ((node->type == XML_ENTITY_REF_NODE) ||
-            (node->type == XML_ENTITY_NODE) ||
-            (node->type == XML_ENTITY_DECL))
+	} else if ((cur->type == XML_ENTITY_NODE) ||
+            (cur->type == XML_ENTITY_DECL))
+	    return (0);
+	cur = cur->parent;
+    } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur));
+    return (0);
+}
+
+/*
+* xmlSearchNsByPrefixStrict:
+* @doc: the document
+* @node: the start node
+* @prefix: the searched namespace prefix
+* @retNs: the resulting ns-decl
+* @prefixed: if the found ns-decl must have a prefix (for attributes)
+*
+* Dynamically searches for a ns-declaration which matches
+* the given @nsName in the ancestor-or-self axis of @node.
+*
+* Returns 1 if a ns-decl was found, 0 if not and -1 on API
+*         and internal errors.
+*/
+static int
+xmlSearchNsByPrefixStrict(xmlDocPtr doc, xmlNodePtr node,
+			  const xmlChar* prefix,
+			  xmlNsPtr *retNs)
+{
+    xmlNodePtr cur;
+    xmlNsPtr ns;
+
+    if ((doc == NULL) || (node == NULL))
+	return (-1);
+
+    if (retNs)
+	*retNs = NULL;
+    if (IS_STR_XML(prefix)) {
+	if (retNs) {
+	    *retNs = xmlTreeEnsureXMLDecl(doc);
+	    if (*retNs == NULL)
+		return (-1);
+	}
+	return (1);
+    }
+    cur = node;
+    do {
+	if (cur->type == XML_ELEMENT_NODE) {
+	    if (cur->nsDef != NULL) {
+		ns = cur->nsDef;
+		do {		
+		    if ((prefix == ns->prefix) ||
+			xmlStrEqual(prefix, ns->prefix))
+		    {
+			/*
+			* Disabled namespaces, e.g. xmlns:abc="".
+			*/
+			if (ns->href == NULL)
+			    return(0);
+			if (retNs)
+			    *retNs = ns;
+			return (1);
+		    }
+		    ns = ns->next;
+		} while (ns != NULL);	
+	    }
+	} else if ((cur->type == XML_ENTITY_NODE) ||
+            (cur->type == XML_ENTITY_DECL))
 	    return (0);
 	cur = cur->parent;
     } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur));
@@ -7802,7 +7917,7 @@
 	    /*
 	    * Does it shadow ancestor ns-decls?
 	    */
-	    if (xmlSearchNs(doc, elem->parent, pref) != NULL)
+	    if (xmlSearchNsByPrefixStrict(doc, elem->parent, pref, NULL) == 1)
 		goto ns_next_prefix;
 	}
 	ret = xmlNewNs(NULL, nsName, pref);
@@ -7856,8 +7971,8 @@
 				   xmlNodePtr elem,
 				   xmlNsPtr ns,
 				   xmlNsPtr *retNs,
-				   xmlNsMapItemPtr *nsMap,
-				   xmlNsMapItemPtr *topmi,
+				   xmlNsMapPtr *nsMap,
+				   
 				   int depth,
 				   int ancestorsOnly,
 				   int prefixed)
@@ -7865,18 +7980,14 @@
     xmlNsMapItemPtr mi;    
 
     if ((doc == NULL) || (ns == NULL) || (retNs == NULL) ||
-	(nsMap == NULL) || (topmi == NULL))
+	(nsMap == NULL))
 	return (-1);
 
     *retNs = NULL;
     /*
     * Handle XML namespace.
     */
-    if ((ns->prefix) &&
-	(ns->prefix[0] == 'x') &&
-	(ns->prefix[1] == 'm') &&
-	(ns->prefix[2] == 'l') &&
-	(ns->prefix[3] == 0)) {
+    if (IS_STR_XML(ns->prefix)) {
 	/*
 	* Insert XML namespace mapping.
 	*/
@@ -7889,20 +8000,18 @@
     * If the search should be done in ancestors only and no
     * @elem (the first ancestor) was specified, then skip the search.
     */
-    if ((! (ancestorsOnly && (elem == NULL))) &&
-	(*nsMap != NULL)) {
-	
+    if ((! (ancestorsOnly && (elem == NULL))) && (XML_NSMAP_NOTEMPTY(*nsMap)))
+    {	
 	/*
 	* Try to find an equal ns-name in in-scope ns-decls.
 	*/
-	for (mi = *nsMap; mi != (*topmi)->next; mi = mi->next) {
-	    
+	XML_NSMAP_FOREACH(*nsMap, mi) {
 	    if ((mi->depth >= XML_TREE_NSMAP_PARENT) && 				
 		/* 
-		* This should be turned on to gain speed, if one knows
-		* that the branch itself was already ns-wellformed and no
-		* stale references existed. I.e. it searches in the ancestor
-		* axis only.
+		* ancestorsOnly: This should be turned on to gain speed,
+		* if one knows that the branch itself was already
+		* ns-wellformed and no stale references existed.
+		* I.e. it searches in the ancestor axis only.
 		*/
 		((! ancestorsOnly) || (mi->depth == XML_TREE_NSMAP_PARENT)) &&
 		/* Skip shadowed prefixes. */
@@ -7937,7 +8046,7 @@
 	/*
 	* Insert mapping.
 	*/	
-	if (xmlDOMWrapNSNormAddNsMapItem(nsMap, NULL, ns,
+	if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns,
 		tmpns, XML_TREE_NSMAP_DOC) == NULL) {
 	    xmlFreeNs(tmpns);
 	    return (-1);
@@ -7954,8 +8063,8 @@
 	if (*nsMap != NULL) {
 	    /*
 	    * Does it shadow ancestor ns-decls?
-	    */		
-	    for (mi = *nsMap; mi != (*topmi)->next; mi = mi->next) {
+	    */
+	    XML_NSMAP_FOREACH(*nsMap, mi) {
 		if ((mi->depth < depth) &&
 		    (mi->shadowDepth == -1) &&
 		    ((ns->prefix == mi->newNs->prefix) ||
@@ -7968,8 +8077,7 @@
 		}
 	    }
 	}
-	if (xmlDOMWrapNSNormAddNsMapItem(nsMap, topmi, ns,
-		tmpns, depth) == NULL) {
+	if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns, tmpns, depth) == NULL) {
 	    xmlFreeNs(tmpns);
 	    return (-1);
 	}
@@ -8007,7 +8115,8 @@
     xmlNsPtr ns, prevns;
     xmlDocPtr doc;
     xmlNodePtr cur, curElem = NULL;
-    xmlNsMapItemPtr nsMap = NULL, topmi = NULL, mi;
+    xmlNsMapPtr nsMap = NULL;
+    xmlNsMapItemPtr /* topmi = NULL, */ mi;
     /* @ancestorsOnly should be set by an option flag. */
     int ancestorsOnly = 0;
     int optRemoveDedundantNS = 
@@ -8043,8 +8152,6 @@
 				if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
 				    elem->parent) == -1)
 				    goto internal_error;
-				if (nsMap != NULL)
-				    topmi = nsMap->prev;
 			    }
 			    parnsdone = 1;
 			}
@@ -8052,8 +8159,8 @@
 			/*
 			* Lookup the ns ancestor-axis for equal ns-decls in scope.
 			*/
-			if (optRemoveDedundantNS && nsMap) {
-			    for (mi = nsMap; mi != topmi->next; mi = mi->next) {
+			if (optRemoveDedundantNS && XML_NSMAP_NOTEMPTY(nsMap)) {
+			    XML_NSMAP_FOREACH(nsMap, mi) {
 				if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
 				    (mi->shadowDepth == -1) &&
 				    ((ns->prefix == mi->newNs->prefix) ||
@@ -8089,8 +8196,8 @@
 			/*
 			* Does it shadow any ns-decl?
 			*/
-			if (nsMap) {
-			    for (mi = nsMap; mi != topmi->next; mi = mi->next) {
+			if (XML_NSMAP_NOTEMPTY(nsMap)) {
+			    XML_NSMAP_FOREACH(nsMap, mi) {
 				if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
 				    (mi->shadowDepth == -1) &&
 				    ((ns->prefix == mi->newNs->prefix) ||
@@ -8103,7 +8210,7 @@
 			/*
 			* Push mapping.
 			*/
-			if (xmlDOMWrapNSNormAddNsMapItem(&nsMap, &topmi, ns, ns,
+			if (xmlDOMWrapNsMapAddItem(&nsMap, -1, ns, ns,
 			    depth) == NULL)
 			    goto internal_error;			
 
@@ -8126,8 +8233,6 @@
 			if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
 				elem->parent) == -1)
 			    goto internal_error;
-			if (nsMap != NULL)
-			    topmi = nsMap->prev;
 		    }
 		    parnsdone = 1;
 		}
@@ -8145,11 +8250,11 @@
 		/*
 		* Adopt ns-references.
 		*/
-		if (nsMap != NULL) {
+		if (XML_NSMAP_NOTEMPTY(nsMap)) {
 		    /*
 		    * Search for a mapping.
 		    */
-		    for (mi = nsMap; mi != topmi->next; mi = mi->next) {
+		    XML_NSMAP_FOREACH(nsMap, mi) {
 			if ((mi->shadowDepth == -1) &&
 			    (cur->ns == mi->oldNs)) {
 
@@ -8163,7 +8268,7 @@
 		*/
 		if (xmlDOMWrapNSNormAquireNormalizedNs(doc, curElem,
 			cur->ns, &ns,
-			&nsMap, &topmi, depth,
+			&nsMap, depth,
 			ancestorsOnly,
 			(cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
 		    goto internal_error;
@@ -8195,19 +8300,23 @@
 	if (cur == elem)
 	    break;
 	if (cur->type == XML_ELEMENT_NODE) {
-	    if (nsMap != NULL) {
+	    if (XML_NSMAP_NOTEMPTY(nsMap)) {	    
 		/*
 		* Pop mappings.
 		*/
-		while ((topmi->depth >= 0) && (topmi->depth >= depth))
-		    topmi = topmi->prev;
+		while ((nsMap->last != NULL) &&
+		    (nsMap->last->depth >= depth))
+		{
+		    XML_NSMAP_POP(nsMap, mi)		    
+		}
 		/*
 		* Unshadow.
 		*/
-		for (mi = nsMap; mi != topmi->next; mi = mi->next)
+		XML_NSMAP_FOREACH(nsMap, mi) {
 		    if (mi->shadowDepth >= depth)
 			mi->shadowDepth = -1;
-	    }
+		}
+	    }	    
 	    depth--;
 	}
 	if (cur->next != NULL)
@@ -8234,7 +8343,7 @@
 	xmlFree(listRedund);
     }
     if (nsMap != NULL)
-	xmlDOMWrapNSNormFreeNsMap(nsMap);
+	xmlDOMWrapNsMapFree(nsMap);
     return (ret);
 }
 
@@ -8268,7 +8377,8 @@
 {
     int ret = 0;
     xmlNodePtr cur, curElem = NULL;
-    xmlNsMapItemPtr nsMap = NULL, topmi = NULL, mi;
+    xmlNsMapPtr nsMap = NULL;
+    xmlNsMapItemPtr mi;
     xmlNsPtr ns;
     int depth = -1, adoptStr = 1;
     /* gather @parent's ns-decls. */
@@ -8328,9 +8438,7 @@
 			    */
 			    if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
 				destParent) == -1)
-				goto internal_error;
-			    if (nsMap != NULL)
-				topmi = nsMap->prev;
+				goto internal_error;			    
 			}
 			parnsdone = 1;
 		    }
@@ -8343,9 +8451,8 @@
 			/*
 			* Does it shadow any ns-decl?
 			*/			
-			if (nsMap) {
-			    for (mi = nsMap; mi != topmi->next;
-			    mi = mi->next) {
+			if (XML_NSMAP_NOTEMPTY(nsMap)) {
+			    XML_NSMAP_FOREACH(nsMap, mi) {			    
 				if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
 				    (mi->shadowDepth == -1) &&
 				    ((ns->prefix == mi->newNs->prefix) ||
@@ -8359,7 +8466,7 @@
 			/*
 			* Push mapping.
 			*/
-			if (xmlDOMWrapNSNormAddNsMapItem(&nsMap, &topmi,
+			if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
 			    ns, ns, depth) == NULL)
 			    goto internal_error;
 		    }
@@ -8373,20 +8480,18 @@
 		    if (destParent && (ctxt == NULL)) {
 			if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
 			    destParent) == -1)
-			    goto internal_error;
-			if (nsMap != NULL)
-			    topmi = nsMap->prev;
+			    goto internal_error;			
 		    }
 		    parnsdone = 1;
 		}
 		/*
 		* Adopt ns-references.
 		*/
-		if (nsMap != NULL) {
+		if (XML_NSMAP_NOTEMPTY(nsMap)) {			    		
 		    /*
 		    * Search for a mapping.
 		    */
-		    for (mi = nsMap; mi != topmi->next; mi = mi->next) {
+		    XML_NSMAP_FOREACH(nsMap, mi) {		    
 			if ((mi->shadowDepth == -1) &&
 			    (cur->ns == mi->oldNs)) {
 
@@ -8409,7 +8514,7 @@
 		    * Insert mapping if ns is available; it's the users fault
 		    * if not.
 		    */
-		    if (xmlDOMWrapNSNormAddNsMapItem(&nsMap, &topmi,
+		    if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
 			    ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL)
 			goto internal_error;
 		    cur->ns = ns;
@@ -8421,7 +8526,7 @@
 			/* ns-decls on curElem or on destDoc->oldNs */			
 			destParent ? curElem : NULL,
 			cur->ns, &ns,
-			&nsMap, &topmi, depth,
+			&nsMap, depth,
 			ancestorsOnly,
 			/* ns-decls must be prefixed for attributes. */
 			(cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
@@ -8513,18 +8618,22 @@
 	    /*
 	    * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
 	    */
-	    if (nsMap != NULL) {
+	    if (XML_NSMAP_NOTEMPTY(nsMap)) {	    
 		/*
 		* Pop mappings.
 		*/
-		while (topmi->depth >= depth)
-		    topmi = topmi->prev;
+		while ((nsMap->last != NULL) &&
+		    (nsMap->last->depth >= depth))
+		{
+		    XML_NSMAP_POP(nsMap, mi)		    
+		}		
 		/*
 		* Unshadow.
 		*/
-		for (mi = nsMap; mi != topmi->next; mi = mi->next)
+		XML_NSMAP_FOREACH(nsMap, mi) {
 		    if (mi->shadowDepth >= depth)
 			mi->shadowDepth = -1;
+		}
 	    }
 	    depth--;
 	}
@@ -8535,16 +8644,19 @@
 	    goto leave_node;
 	}
     }
+    
+    goto exit;
+
+internal_error:    
+    ret = -1;
+
+exit:
     /*
     * Cleanup.
     */
     if (nsMap != NULL)
-	xmlDOMWrapNSNormFreeNsMap(nsMap);
-    return (ret);
-internal_error:
-    if (nsMap != NULL)
-	xmlDOMWrapNSNormFreeNsMap(nsMap);
-    return (-1);
+	xmlDOMWrapNsMapFree(nsMap);
+    return(ret);
 }
 
 /*
@@ -8592,7 +8704,8 @@
 {
     int ret = 0;
     xmlNodePtr cur, curElem = NULL;
-    xmlNsMapItemPtr nsMap = NULL, topmi = NULL, mi;
+    xmlNsMapPtr nsMap = NULL;
+    xmlNsMapItemPtr mi;
     xmlNsPtr ns;
     int depth = -1;
     /* int adoptStr = 1; */
@@ -8602,7 +8715,7 @@
     int ancestorsOnly = 0;
     xmlNodePtr resultClone = NULL, clone = NULL, parentClone = NULL, prevClone = NULL;
     xmlNsPtr cloneNs = NULL, *cloneNsDefSlot = NULL;    
-        
+
     if ((node == NULL) || (resNode == NULL) ||
 	(sourceDoc == NULL) || (destDoc == NULL))
 	return(-1);
@@ -8610,10 +8723,10 @@
     * TODO: Initially we support only element-nodes.
     */
     if (node->type != XML_ELEMENT_NODE)
-	return(1);    
+	return(1);
     /*
     * Check node->doc sanity.
-    */    
+    */
     if ((node->doc != NULL) && (sourceDoc != NULL) &&
 	(node->doc != sourceDoc)) {
 	/*
@@ -8622,13 +8735,10 @@
 	return (-1);
     }
     if (sourceDoc == NULL)
-	sourceDoc = node->doc;
-    if (sourceDoc == destDoc)
-	return (-1);        
+	sourceDoc = node->doc;    
 
     *resNode = NULL;
-    
-    deep = 1;
+   
     cur = node;
     while (cur != NULL) {
 	if (cur->doc != sourceDoc) {
@@ -8740,7 +8850,7 @@
 		/*
 		* Namespace declarations.
 		*/
-		if ((ctxt == NULL) && (cur->nsDef != NULL)) {
+		if (cur->nsDef != NULL) {
 		    if (! parnsdone) {
 			if (destParent && (ctxt == NULL)) {
 			    /*
@@ -8748,9 +8858,7 @@
 			    */
 			    if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
 				destParent) == -1)
-				goto internal_error;
-			    if (nsMap != NULL)
-				topmi = nsMap->prev;
+				goto internal_error;			    
 			}
 			parnsdone = 1;
 		    }
@@ -8779,28 +8887,32 @@
 			*cloneNsDefSlot = cloneNs;
 			cloneNsDefSlot = &(cloneNs->next);
 
-			/*
-			* Does it shadow any ns-decl?
-			*/
-			if (nsMap) {
-			    for (mi = nsMap; mi != topmi->next;
-			    mi = mi->next) {
-				if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
-				    (mi->shadowDepth == -1) &&
-				    ((ns->prefix == mi->newNs->prefix) ||
-				     xmlStrEqual(ns->prefix,
+			if (ctxt == NULL) {
+			    /*
+			    * Does it shadow any ns-decl?
+			    */
+			    if (XML_NSMAP_NOTEMPTY(nsMap)) {
+				XML_NSMAP_FOREACH(nsMap, mi) {				
+				    if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
+					(mi->shadowDepth == -1) &&
+					((ns->prefix == mi->newNs->prefix) ||
+					xmlStrEqual(ns->prefix,
 					mi->newNs->prefix))) {
-				    /* Mark as shadowed at the current depth. */
-				    mi->shadowDepth = depth;
+					/*
+					* Mark as shadowed at the current
+					* depth.
+					*/
+					mi->shadowDepth = depth;
+				    }
 				}
 			    }
+			    /*
+			    * Push mapping.
+			    */
+			    if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
+				ns, cloneNs, depth) == NULL)
+				goto internal_error;
 			}
-			/*
-			* Push mapping.
-			*/
-			if (xmlDOMWrapNSNormAddNsMapItem(&nsMap, &topmi,
-			    ns, cloneNs, depth) == NULL)
-			    goto internal_error;
 		    }
 		}
 		/* cur->ns will be processed further down. */
@@ -8814,12 +8926,15 @@
 		if (cur->content)
 		    clone->content = xmlStrdup(cur->content);
 		goto leave_node;
+	    case XML_ENTITY_NODE:
+		/* TODO: What to do here? */
+		goto leave_node;
 	    case XML_ENTITY_REF_NODE:		
 		if (sourceDoc != destDoc) {
 		    if ((destDoc->intSubset) || (destDoc->extSubset)) {
 			xmlEntityPtr ent;
 			/*
-			* Assign new entity-node if available.
+			* Different doc: Assign new entity-node if available.
 			*/
 			ent = xmlGetDocEntity(destDoc, cur->name);
 			if (ent != NULL) {
@@ -8830,12 +8945,13 @@
 		    }
 		} else {
 		    /*
-		    * Use the current node's entity declaration and value.
+		    * Same doc: Use the current node's entity declaration
+		    * and value.
 		    */
 		    clone->content = cur->content;
 		    clone->children = cur->children;
 		    clone->last = cur->last;
-		}
+		}		
 		goto leave_node;
 	    case XML_PI_NODE:
 		if (cur->content)
@@ -8860,22 +8976,19 @@
 	*/
 	if (! parnsdone) {
 	    if (destParent && (ctxt == NULL)) {
-		if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
-		    destParent) == -1)
-		    goto internal_error;
-		if (nsMap != NULL)
-		    topmi = nsMap->prev;
+		if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, destParent) == -1)
+		    goto internal_error;		
 	    }
 	    parnsdone = 1;
 	}
 	/*
 	* Adopt ns-references.
 	*/
-	if (nsMap != NULL) {
+	if (XML_NSMAP_NOTEMPTY(nsMap)) {
 	    /*
 	    * Search for a mapping.
 	    */
-	    for (mi = nsMap; mi != topmi->next; mi = mi->next) {
+	    XML_NSMAP_FOREACH(nsMap, mi) {	    
 		if ((mi->shadowDepth == -1) &&
 		    (cur->ns == mi->oldNs)) {
 		    /*
@@ -8899,7 +9012,7 @@
 	    /*
 	    * Add user's mapping.
 	    */
-	    if (xmlDOMWrapNSNormAddNsMapItem(&nsMap, &topmi,
+	    if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
 		cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL)
 		goto internal_error;
 	    clone->ns = ns;
@@ -8911,7 +9024,7 @@
 		/* ns-decls on curElem or on destDoc->oldNs */			
 		destParent ? curElem : NULL,
 		cur->ns, &ns,
-		&nsMap, &topmi, depth,
+		&nsMap, depth,
 		ancestorsOnly,
 		/* ns-decls must be prefixed for attributes. */
 		(cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
@@ -8961,10 +9074,12 @@
 	* Descend into child-nodes.
 	*/
 	if (cur->children != NULL) {
-	    prevClone = NULL;
-	    parentClone = clone;
-	    cur = cur->children;
-	    continue;
+	    if (deep || (cur->type == XML_ATTRIBUTE_NODE)) {
+		prevClone = NULL;
+		parentClone = clone;
+		cur = cur->children;
+		continue;
+	    }
 	}
 
 leave_node:
@@ -8980,20 +9095,23 @@
 	    /*
 	    * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
 	    */
-	    if (nsMap != NULL) {
+	    if (XML_NSMAP_NOTEMPTY(nsMap)) {	    
 		/*
 		* Pop mappings.
 		*/
-		while (topmi->depth >= depth)
-		    topmi = topmi->prev;
+		while ((nsMap->last != NULL) &&
+		    (nsMap->last->depth >= depth))
+		{
+		    XML_NSMAP_POP(nsMap, mi)		    
+		}
 		/*
 		* Unshadow.
-		* TODO: How to optimize this?
 		*/
-		for (mi = nsMap; mi != topmi->next; mi = mi->next)
+		XML_NSMAP_FOREACH(nsMap, mi) {
 		    if (mi->shadowDepth >= depth)
 			mi->shadowDepth = -1;
-	    }
+		}
+	    }	    
 	    depth--;
 	}
 	if (cur->next != NULL) {
@@ -9032,7 +9150,7 @@
     * Cleanup.
     */
     if (nsMap != NULL)
-	xmlDOMWrapNSNormFreeNsMap(nsMap);
+	xmlDOMWrapNsMapFree(nsMap);
     /*
     * TODO: Should we try a cleanup of the cloned node in case of a
     * fatal error?
@@ -9079,8 +9197,7 @@
 	    /* TODO: User defined. */
 	}
 	/* XML Namespace. */
-	if ((attr->ns->prefix[0] == 'x') && (attr->ns->prefix[1] == 'm') &&
-	    (attr->ns->prefix[2] == 'l') && (attr->ns->prefix[3] == 0)) {
+	if (IS_STR_XML(attr->ns->prefix)) {
 	    ns = xmlTreeEnsureXMLDecl(destDoc);
 	} else if (destParent == NULL) {
 	    /*
@@ -9091,7 +9208,7 @@
 	    /*
 	    * Declare on @destParent.
 	    */
-	    if (xmlSearchNsByHrefStrict(destDoc, destParent, attr->ns->href,
+	    if (xmlSearchNsByNamespaceStrict(destDoc, destParent, attr->ns->href,
 		&ns, 1) == -1)
 		goto internal_error;
 	    if (ns == NULL) {
@@ -9290,6 +9407,5 @@
     return (0);
 }
 
-
 #define bottom_tree
 #include "elfgcchack.h"