[xml] xmlReconciliateNs problem



Hi Daniel, All,

I'm trying to make XML::LibXML perl module work with 2.6. After examining one of the self tests that broke after upgrade, I suspect that xmlReconciliateNs doesn't do its right job (if at all). The documentation says:

"This function checks that all the namespaces declared within the given
tree are properly declared. This is needed for example after Copy or Cut
and then paste operations. ..."

Now, I have a document like this:
<?xml version="1.0"?>
<foo><x:a xmlns:x="http://foo.bar";><x:b/></x:a></foo>

and try either:
a) move <x:b/> one level up, into <foo>
b) move <x:b/> into another document

in both cases, expecting xmlReconciliateNs to create xmlns:x="http://foo.bar"; on <x:b/>. This is at least what it used to do with libxml2-2.5.x.

The attached file is my lame attempt of rewriting of the test case into C. It demonstrates the problem in the following way:

1) run it without parameters to check for a)
2) run it with 1 parameter (arbitrary) to check for b)
3) run it with 2 parameter (-"-) to check for b), freeing the original document as soon as <x:b> was moved and namespaces reconciliated.

I compile it with:
gcc -I /usr/include/libxml2 -L /usr/lib -lxml2 -o testns testns.c

with 2.6, I get
1) ./testns
<?xml version="1.0"?>
<foo><x:a xmlns:x="http://foo.bar"/><x:b/></foo>
(bad: x:b has prefix but no namespace declared)

2) ./testns x
<?xml version="1.0"?>
<x:b/>
(bad)

3) ./testns x x
<?xml version="1.0"?>
<b/>
(even worse - maybe because of the new string reusing code?)

while with 2.5.3:

1) ./testns
<?xml version="1.0"?>
<foo><x:a xmlns:x="http://foo.bar"/><x:b xmlns:x="http://foo.bar"/></foo>
2) ./testns x
<?xml version="1.0"?>
<x:b xmlns:x="http://foo.bar"/>
3) ./testns x x
<?xml version="1.0"?>
<x:b xmlns:x="http://foo.bar"/>

which all look well.

I looked into the corresponding tree.c code. It appears, that xmlReconciliateNs simply does nothing, being fooled by xmlSearchNsByHref which returns node->ns even though it failed to find a corresponding nsDef.

If the behavior of 2.6 is intended, is there a workaround?
Thanks,

-- Petr
#include <libxml/tree.h>
#include <libxml/parser.h>

#define COPY_BETWEEN_DOCUMENTS 1

/*
 * The document
 */
static xmlChar buffer[] = 
"<?xml version=\"1.0\"?>\n\
<foo><x:a xmlns:x=\"http://foo.bar\";><x:b/></x:a></foo>\n";

int main(int argc, char **argv) {
    xmlDocPtr doc1 = NULL;
    xmlDocPtr doc2 = NULL;
    xmlNodePtr node = NULL;
    xmlNodePtr foo = NULL;
    xmlChar *buf = NULL;
    int len = 0;
    int copy_between_documents=0;
    int free_doc1_soon=0;

    if (argc>1) copy_between_documents = 1;
    if (argc>2) free_doc1_soon = 1;

    doc1 = xmlParseDoc(buffer);
    foo=xmlDocGetRootElement(doc1); /* foo */
    node=foo->children->children;   /* x:b */

    if (copy_between_documents) {
      /* move x:b to a new document */
      doc2 = xmlNewDoc((const xmlChar*) "1.0");      
      xmlSetTreeDoc(node, doc2);    /* doc2 adopts node */
      node->doc=doc2;
      xmlDocSetRootElement( doc2, node );
      xmlReconciliateNs(doc2, node); /* fix namespaces */
      if (free_doc1_soon) {  /* free doc1 now?*/
        if (doc1) xmlFreeDoc(doc1);
        doc1=NULL;
      }
      xmlDocDumpMemory(doc2, &buf, &len);
    } else {
      /* raise x:b 1 level into foo */
      xmlUnlinkNode( node );
      xmlAddChild( foo, node );
      xmlReconciliateNs(doc1, node); /* fix namespaces */
      xmlDocDumpMemory(doc1, &buf, &len);
    }
    printf("%s",buf);

    if (buf) xmlFree(buf);
    if (doc1) xmlFreeDoc(doc1);
    if (doc2) xmlFreeDoc(doc2);
    xmlCleanupParser();
    xmlMemoryDump();

    return(0);
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]