Hi,

libxml2 currently does not handle namespaces correctly in all cases when cloning
nodes.

I have attached a testcase(which demonstrates the bug using libgdome2.0.8.1 on
top of libxml2.2.6.23), and a patch for the issue.

The testcase tests 4 different cases, which you access by compiling with
-DTESTNUMBER=0 through to -DTESTNUMBER=3

Please CC any responses to me, as I am not on the xml@ list.

Best regards,
Andrew Miller


----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.
--- tree.c.orig	2006-02-20 14:51:28.428448035 +1300
+++ tree.c	2006-02-20 16:05:42.781217208 +1300
@@ -3872,7 +3872,10 @@
     if (node->ns != NULL) {
         xmlNsPtr ns;
 
-	ns = xmlSearchNs(doc, ret, node->ns->prefix);
+	if (node->ns->prefix == NULL || node->doc != doc)
+	    ns = NULL;
+	else
+	    ns = xmlSearchNs(doc, ret, node->ns->prefix);
 	if (ns == NULL) {
 	    /*
 	     * Humm, we are copying an element whose namespace is defined
@@ -3883,9 +3886,13 @@
 	    if (ns != NULL) {
 	        xmlNodePtr root = ret;
 
-		while (root->parent != NULL) root = root->parent;
+		while (root->parent != NULL &&
+		       root->parent->type == XML_ELEMENT_NODE)
+		    root = root->parent;
 		ret->ns = xmlNewNs(root, ns->href, ns->prefix);
 	    }
+            else
+              ret->ns = xmlNewNs(NULL, node->ns->href, node->ns->prefix);
 	} else {
 	    /*
 	     * reference the existing namespace definition in our own tree.
#include <libgdome/gdome.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>

#if TESTNUMBER & 1
#define CLONE_WHOLE_DOCUMENT
#endif
#if TESTNUMBER & 2
#define INCLUDE_PREFIX
#endif

int
main(int argc, char** argv)
{
  GdomeException exc;
  GdomeDOMImplementation *impl;
  GdomeDocumentType *dt;
  GdomeDocument *doc1
#ifdef CLONE_WHOLE_DOCUMENT
    , *doc2
#endif
    ;
  GdomeElement *de1, *de2;
  GdomeDOMString *str1, *str2, *str3;

  impl = gdome_di_mkref();
  assert(impl);

  str1 = gdome_str_mkref_own(strdup("foo"));
  str2 = gdome_str_mkref_own(strdup("bar"));
  str3 = gdome_str_mkref_own(strdup("baz"));
  dt = gdome_di_createDocumentType(impl, str1, str2,
                                   str3, &exc);
  gdome_str_unref(str1);
  gdome_str_unref(str2);
  gdome_str_unref(str3);
  assert(GDOME_EXCEPTION_CODE(exc) == GDOME_NOEXCEPTION_ERR);
  assert(dt);
  
  str1 = gdome_str_mkref_own(strdup("http://www.example.org/URN/testcase";));
  str2 = gdome_str_mkref_own(strdup(
#ifdef INCLUDE_PREFIX
                                    "myel:"
#endif
                                    "testelement"));
  doc1 = gdome_di_createDocument(impl, str1, str2, dt, &exc);
  gdome_str_unref(str1);
  gdome_str_unref(str2);
  assert(GDOME_EXCEPTION_CODE(exc) == GDOME_NOEXCEPTION_ERR);
  assert(doc1);

#ifdef CLONE_WHOLE_DOCUMENT
  doc2 = GDOME_DOC(gdome_doc_cloneNode(doc1, TRUE, &exc));
  assert(GDOME_EXCEPTION_CODE(exc) == GDOME_NOEXCEPTION_ERR);
  assert(doc2);
#endif

  de1 = gdome_doc_documentElement(doc1, &exc);
  assert(GDOME_EXCEPTION_CODE(exc) == GDOME_NOEXCEPTION_ERR);
  assert(de1);

#ifdef CLONE_WHOLE_DOCUMENT
  de2 = gdome_doc_documentElement(doc2, &exc);
  assert(GDOME_EXCEPTION_CODE(exc) == GDOME_NOEXCEPTION_ERR);
#else
  de2 = GDOME_EL(gdome_el_cloneNode(de1, TRUE, &exc));
  assert(GDOME_EXCEPTION_CODE(exc) == GDOME_NOEXCEPTION_ERR);
#endif
  assert(de2);

  str1 = gdome_el_namespaceURI(de1, &exc);
  assert(GDOME_EXCEPTION_CODE(exc) == GDOME_NOEXCEPTION_ERR);
  assert(str1);
  assert(str1->str);


  str2 = gdome_el_namespaceURI(de2, &exc);
  assert(GDOME_EXCEPTION_CODE(exc) == GDOME_NOEXCEPTION_ERR);
  assert(str2);
  assert(str2->str);

  printf("de1->namespaceURI() = %s\n"
         "de2->namespaceURI() = %s\n",
         str1->str, str2->str);

  return 0;
}
_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
[email protected]
http://mail.gnome.org/mailman/listinfo/xml

Reply via email to