applied patch from Brent Hendricks adding namespace removal at the python

* python/libxml.c python/libxml.py: applied patch from Brent Hendricks
  adding namespace removal at the python level #300209
* python/tests/Makefile.am python/tests/nsdel.py: added the regression
  test
Daniel
diff --git a/ChangeLog b/ChangeLog
index 7a9b6fd..1434bbc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Tue Apr 12 04:03:32 CEST 2005 Daniel Veillard <daniel@veillard.com>
+
+	* python/libxml.c python/libxml.py: applied patch from Brent Hendricks
+	  adding namespace removal at the python level #300209
+	* python/tests/Makefile.am python/tests/nsdel.py: added the regression
+	  test
+
 Sun Apr 10 09:03:22 HKT 2005 William Brack <wbrack@mmm.com.hk>
 
 	* xpath.c: fixed several places where memory cleanup was not
diff --git a/python/libxml.c b/python/libxml.c
index b18f887..8fc63f8 100644
--- a/python/libxml.c
+++ b/python/libxml.c
@@ -2661,6 +2661,55 @@
 }
 
 PyObject *
+libxml_xmlNodeRemoveNsDef(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
+{
+    PyObject *py_retval;
+    xmlNsPtr ns, prev;
+    xmlNodePtr node;
+    PyObject *pyobj_node;
+    xmlChar *href;
+    xmlNsPtr c_retval;
+    
+    if (!PyArg_ParseTuple
+        (args, (char *) "Oz:xmlNodeRemoveNsDef", &pyobj_node, &href))
+        return (NULL);
+    node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
+    ns = NULL;
+
+    if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) {
+        Py_INCREF(Py_None);
+        return (Py_None);
+    }
+
+    if (href == NULL) {
+	ns = node->nsDef;
+	node->nsDef = NULL;
+	c_retval = 0;
+    }
+    else {
+	prev = NULL;
+	ns = node->nsDef;
+	while (ns != NULL) {
+	    if (xmlStrEqual(ns->href, href)) {
+		if (prev != NULL)
+		    prev->next = ns->next;
+		else
+		    node->nsDef = ns->next;
+		ns->next = NULL;
+		c_retval = 0;
+		break;
+	    }
+	    prev = ns;
+	    ns = ns->next;
+	}
+    }
+
+    c_retval = ns;
+    py_retval = libxml_xmlNsPtrWrap((xmlNsPtr) c_retval);
+    return (py_retval);
+}
+
+PyObject *
 libxml_xmlNodeGetNs(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
 {
     PyObject *py_retval;
@@ -3640,6 +3689,7 @@
     {(char *) "type", libxml_type, METH_VARARGS, NULL},
     {(char *) "doc", libxml_doc, METH_VARARGS, NULL},
     {(char *) "xmlNewNode", libxml_xmlNewNode, METH_VARARGS, NULL},
+    {(char *) "xmlNodeRemoveNsDef", libxml_xmlNodeRemoveNsDef, METH_VARARGS, NULL},
     {(char *)"xmlSetValidErrors", libxml_xmlSetValidErrors, METH_VARARGS, NULL},
     {(char *)"xmlFreeValidCtxt", libxml_xmlFreeValidCtxt, METH_VARARGS, NULL},
 #ifdef LIBXML_OUTPUT_ENABLED
diff --git a/python/libxml.py b/python/libxml.py
index 2eca71e..86bdd92 100644
--- a/python/libxml.py
+++ b/python/libxml.py
@@ -429,6 +429,27 @@
     def xpathEval2(self, expr):
         return self.xpathEval(expr)
 
+    # Remove namespaces
+    def removeNsDef(self, href):
+        """
+        Remove a namespace definition from a node.  If href is None,
+        remove all of the ns definitions on that node.  The removed
+        namespaces are returned as a linked list.
+
+        Note: If any child nodes referred to the removed namespaces,
+        they will be left with dangling links.  You should call
+        renciliateNs() to fix those pointers.
+
+        Note: This method does not free memory taken by the ns
+        definitions.  You will need to free it manually with the
+        freeNsList() method on the returns xmlNs object.
+        """
+
+        ret = libxml2mod.xmlNodeRemoveNsDef(self._o, href)
+        if ret is None:return None
+        __tmp = xmlNs(_obj=ret)
+        return __tmp
+
     # support for python2 iterators
     def walk_depth_first(self):
         return xmlCoreDepthFirstItertor(self)
diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am
index c6d03e9..3571abf 100644
--- a/python/tests/Makefile.am
+++ b/python/tests/Makefile.am
@@ -30,6 +30,7 @@
     reader8.py	\
     readernext.py	\
     walker.py	\
+    nsdel.py	\
     ctxterror.py\
     readererr.py\
     relaxng.py	\
diff --git a/python/tests/nsdel.py b/python/tests/nsdel.py
new file mode 100755
index 0000000..c06ded3
--- /dev/null
+++ b/python/tests/nsdel.py
@@ -0,0 +1,62 @@
+#!/usr/bin/python -u
+#
+# this test exercise the XPath basic engine, parser, etc, and
+# allows to detect memory leaks
+#
+import sys
+import libxml2
+
+instance="""<?xml version="1.0"?>
+<tag xmlns:foo='urn:foo' xmlns:bar='urn:bar' xmlns:baz='urn:baz' />"""
+
+def namespaceDefs(node):
+    n = node.nsDefs()
+    while n:
+        yield n
+        n = n.next
+
+def checkNamespaceDefs(node, count):
+    nsList = list(namespaceDefs(node))
+    #print nsList
+    if len(nsList) != count :
+        raise Exception, "Error: saw %d namespace declarations.  Expected %d" % (len(nsList), count)
+    
+# Memory debug specific
+libxml2.debugMemory(1)
+
+# Remove single namespace
+doc = libxml2.parseDoc(instance)
+node = doc.getRootElement()
+checkNamespaceDefs(node, 3)
+ns = node.removeNsDef('urn:bar')
+checkNamespaceDefs(node, 2)
+ns.freeNsList()
+doc.freeDoc()
+
+# Remove all namespaces
+doc = libxml2.parseDoc(instance)
+node = doc.getRootElement()
+checkNamespaceDefs(node, 3)
+ns = node.removeNsDef(None)
+checkNamespaceDefs(node, 0)
+ns.freeNsList()
+doc.freeDoc()
+
+# Remove a namespace refered to by a child
+doc = libxml2.newDoc("1.0")
+root = doc.newChild(None, "root", None)
+namespace = root.newNs("http://example.com/sample", "s")
+child = root.newChild(namespace, "child", None)
+root.removeNsDef("http://example.com/sample")
+doc.reconciliateNs(root)
+namespace.freeNsList()
+doc.serialize() # This should not segfault
+doc.freeDoc()
+
+# Memory debug specific
+libxml2.cleanupParser()
+if libxml2.debugMemory(1) == 0:
+    print "OK"
+else:
+    print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+    libxml2.dumpMemory()