mirror of https://github.com/AxioDL/tinyxml2.git
Merge pull request #558 from leethomason/clone
Support clone (deep copy) of XMLDocument and XMLNode
This commit is contained in:
commit
bc527554e8
25
tinyxml2.cpp
25
tinyxml2.cpp
|
@ -772,6 +772,18 @@ void XMLNode::SetValue( const char* str, bool staticMem )
|
|||
}
|
||||
}
|
||||
|
||||
XMLNode* XMLNode::DeepClone(XMLDocument* document) const
|
||||
{
|
||||
XMLNode* clone = this->ShallowClone(document);
|
||||
if (!clone) return 0;
|
||||
|
||||
for (const XMLNode* child = this->FirstChild(); child; child = child->NextSibling()) {
|
||||
XMLNode* childClone = child->DeepClone(document);
|
||||
TIXMLASSERT(childClone);
|
||||
clone->InsertEndChild(childClone);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
void XMLNode::DeleteChildren()
|
||||
{
|
||||
|
@ -2038,6 +2050,19 @@ void XMLDocument::Clear()
|
|||
}
|
||||
|
||||
|
||||
void XMLDocument::DeepCopy(XMLDocument* target)
|
||||
{
|
||||
TIXMLASSERT(target);
|
||||
if (target == this) {
|
||||
return; // technically success - a no-op.
|
||||
}
|
||||
|
||||
target->Clear();
|
||||
for (const XMLNode* node = this->FirstChild(); node; node = node->NextSibling()) {
|
||||
target->InsertEndChild(node->DeepClone(target));
|
||||
}
|
||||
}
|
||||
|
||||
XMLElement* XMLDocument::NewElement( const char* name )
|
||||
{
|
||||
XMLElement* ele = CreateUnlinkedNode<XMLElement>( _elementPool );
|
||||
|
|
28
tinyxml2.h
28
tinyxml2.h
|
@ -53,7 +53,7 @@ distribution.
|
|||
AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
|
||||
*/
|
||||
|
||||
#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
|
||||
#if defined( _DEBUG ) || defined (__DEBUG__)
|
||||
# ifndef DEBUG
|
||||
# define DEBUG
|
||||
# endif
|
||||
|
@ -865,6 +865,21 @@ public:
|
|||
*/
|
||||
virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
|
||||
|
||||
/**
|
||||
Make a copy of this node and all its children.
|
||||
|
||||
If the 'document' is null, then the nodes will
|
||||
be allocated in the current document. If document
|
||||
is specified, the memory will be allocated is the
|
||||
specified XMLDocument.
|
||||
|
||||
NOTE: This is probably not the correct tool to
|
||||
copy a document, since XMLDocuments can have multiple
|
||||
top level XMLNodes. You probably want to use
|
||||
XMLDocument::DeepCopy()
|
||||
*/
|
||||
XMLNode* DeepClone( XMLDocument* document ) const;
|
||||
|
||||
/**
|
||||
Test if 2 nodes are the same, but don't test children.
|
||||
The 2 nodes do not need to be in the same Document.
|
||||
|
@ -1806,7 +1821,16 @@ public:
|
|||
/// Clear the document, resetting it to the initial state.
|
||||
void Clear();
|
||||
|
||||
// internal
|
||||
/**
|
||||
Copies this document to a target document.
|
||||
The target will be completely cleared before the copy.
|
||||
If you want to copy a sub-tree, see XMLNode::DeepClone().
|
||||
|
||||
NOTE: that the 'target' must be non-null.
|
||||
*/
|
||||
void DeepCopy(XMLDocument* target);
|
||||
|
||||
// internal
|
||||
char* Identify( char* p, XMLNode** node );
|
||||
|
||||
// internal
|
||||
|
|
80
xmltest.cpp
80
xmltest.cpp
|
@ -1131,6 +1131,86 @@ int main( int argc, const char ** argv )
|
|||
}
|
||||
|
||||
{
|
||||
// Deep Cloning of root element.
|
||||
XMLDocument doc2;
|
||||
XMLPrinter printer1;
|
||||
{
|
||||
// Make sure doc1 is deleted before we test doc2
|
||||
const char* xml =
|
||||
"<root>"
|
||||
" <child1 foo='bar'/>"
|
||||
" <!-- comment thing -->"
|
||||
" <child2 val='1'>Text</child2>"
|
||||
"</root>";
|
||||
XMLDocument doc;
|
||||
doc.Parse(xml);
|
||||
|
||||
doc.Print(&printer1);
|
||||
XMLNode* root = doc.RootElement()->DeepClone(&doc2);
|
||||
doc2.InsertFirstChild(root);
|
||||
}
|
||||
XMLPrinter printer2;
|
||||
doc2.Print(&printer2);
|
||||
|
||||
XMLTest("Deep clone of element.", printer1.CStr(), printer2.CStr(), true);
|
||||
}
|
||||
|
||||
{
|
||||
// Deep Cloning of sub element.
|
||||
XMLDocument doc2;
|
||||
XMLPrinter printer1;
|
||||
{
|
||||
// Make sure doc1 is deleted before we test doc2
|
||||
const char* xml =
|
||||
"<?xml version ='1.0'?>"
|
||||
"<root>"
|
||||
" <child1 foo='bar'/>"
|
||||
" <!-- comment thing -->"
|
||||
" <child2 val='1'>Text</child2>"
|
||||
"</root>";
|
||||
XMLDocument doc;
|
||||
doc.Parse(xml);
|
||||
|
||||
const XMLElement* subElement = doc.FirstChildElement("root")->FirstChildElement("child2");
|
||||
subElement->Accept(&printer1);
|
||||
|
||||
XMLNode* clonedSubElement = subElement->DeepClone(&doc2);
|
||||
doc2.InsertFirstChild(clonedSubElement);
|
||||
}
|
||||
XMLPrinter printer2;
|
||||
doc2.Print(&printer2);
|
||||
|
||||
XMLTest("Deep clone of sub-element.", printer1.CStr(), printer2.CStr(), true);
|
||||
}
|
||||
|
||||
{
|
||||
// Deep cloning of document.
|
||||
XMLDocument doc2;
|
||||
XMLPrinter printer1;
|
||||
{
|
||||
// Make sure doc1 is deleted before we test doc2
|
||||
const char* xml =
|
||||
"<?xml version ='1.0'?>"
|
||||
"<!-- Top level comment. -->"
|
||||
"<root>"
|
||||
" <child1 foo='bar'/>"
|
||||
" <!-- comment thing -->"
|
||||
" <child2 val='1'>Text</child2>"
|
||||
"</root>";
|
||||
XMLDocument doc;
|
||||
doc.Parse(xml);
|
||||
doc.Print(&printer1);
|
||||
|
||||
doc.DeepCopy(&doc2);
|
||||
}
|
||||
XMLPrinter printer2;
|
||||
doc2.Print(&printer2);
|
||||
|
||||
XMLTest("DeepCopy of document.", printer1.CStr(), printer2.CStr(), true);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
// This shouldn't crash.
|
||||
XMLDocument doc;
|
||||
if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
|
||||
|
|
Loading…
Reference in New Issue