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()
|
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* XMLDocument::NewElement( const char* name )
|
||||||
{
|
{
|
||||||
XMLElement* ele = CreateUnlinkedNode<XMLElement>( _elementPool );
|
XMLElement* ele = CreateUnlinkedNode<XMLElement>( _elementPool );
|
||||||
|
|
26
tinyxml2.h
26
tinyxml2.h
|
@ -53,7 +53,7 @@ distribution.
|
||||||
AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
|
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
|
# ifndef DEBUG
|
||||||
# define DEBUG
|
# define DEBUG
|
||||||
# endif
|
# endif
|
||||||
|
@ -865,6 +865,21 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
|
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.
|
Test if 2 nodes are the same, but don't test children.
|
||||||
The 2 nodes do not need to be in the same Document.
|
The 2 nodes do not need to be in the same Document.
|
||||||
|
@ -1806,6 +1821,15 @@ public:
|
||||||
/// Clear the document, resetting it to the initial state.
|
/// Clear the document, resetting it to the initial state.
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
// internal
|
||||||
char* Identify( char* p, XMLNode** node );
|
char* Identify( char* p, XMLNode** node );
|
||||||
|
|
||||||
|
|
80
xmltest.cpp
80
xmltest.cpp
|
@ -1130,6 +1130,86 @@ int main( int argc, const char ** argv )
|
||||||
XMLTest( "Clone and Equal", 4, count );
|
XMLTest( "Clone and Equal", 4, count );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// 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.
|
// This shouldn't crash.
|
||||||
XMLDocument doc;
|
XMLDocument doc;
|
||||||
|
|
Loading…
Reference in New Issue