Search code examples
c++xml-parsingtinyxml2

Why can't I copy the contents of an XMLDocument to another XMLDocument using TinyXml2?


I do not understand why the below code doesn't work as intended to copy the one element from doc1 to doc2:

void test_xml(){
using namespace tinyxml2;
XMLDocument doc1, doc2;
XMLPrinter printer;

doc1.LoadFile("./res/xml/basic.xml");
if(doc1.Error())
    std::cout << doc1.ErrorName();
doc1.Print(&printer);
std::cout << printer.CStr(); // prints "</atag>" without quotes
printer.ClearBuffer();

doc2.InsertFirstChild(doc1.RootElement());
if(doc2.Error())
    std::cout << doc2.ErrorName(); // doesn't run, there's no error
doc2.Print(&printer);
std::cout << printer.CStr(); // prints nothing, no child got inserted to doc2
std::cout << doc2.NoChildren(); //prints "1" meaning we didn't insert anything
}

Can someone point out how this can be improved?


Solution

  • From the TinyXml2 documentation:

    InsertFirstChild ... Returns the addThis argument or 0 if the node does not belong to the same document.

    Basically you can only add a node to a document if the node was manufactured by that document (with NewElement, NewText etc).

    You have to walk through doc1 creating corresponding nodes as you go (with ShallowClone, and adding them to doc2. It appears there is no DeepClone to do it all for you.

    At http://sourceforge.net/p/tinyxml/discussion/42748/thread/820b0377/, "practisevoodoo" suggests:

    XMLNode *deepCopy( XMLNode *src, XMLDocument *destDoc )
    {
        XMLNode *current = src->ShallowClone( destDoc );
        for( XMLNode *child=src->FirstChild(); child; child=child->NextSibling() )
        {
            current->InsertEndChild( deepCopy( child, destDoc ) );
        }
    
        return current;
    }