diff --git a/tinyxml2.cpp b/tinyxml2.cpp
index b890cb1..7ecbf86 100755
--- a/tinyxml2.cpp
+++ b/tinyxml2.cpp
@@ -625,7 +625,6 @@ void XMLNode::DeleteChildren()
void XMLNode::Unlink( XMLNode* child )
{
- TIXMLASSERT( child->_parent == this );
if ( child == _firstChild ) {
_firstChild = _firstChild->_next;
}
@@ -639,7 +638,6 @@ void XMLNode::Unlink( XMLNode* child )
if ( child->_next ) {
child->_next->_prev = child->_prev;
}
- child->_parent = 0;
}
@@ -652,6 +650,12 @@ void XMLNode::DeleteChild( XMLNode* node )
XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
{
+ if (addThis->_document != _document)
+ return 0;
+ if (addThis->_parent)
+ addThis->_parent->Unlink( addThis );
+ else
+ addThis->_memPool->SetTracked();
if ( _lastChild ) {
TIXMLASSERT( _firstChild );
TIXMLASSERT( _lastChild->_next == 0 );
@@ -669,13 +673,18 @@ XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
addThis->_next = 0;
}
addThis->_parent = this;
- addThis->_memPool->SetTracked();
return addThis;
}
XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )
{
+ if (addThis->_document != _document)
+ return 0;
+ if (addThis->_parent)
+ addThis->_parent->Unlink( addThis );
+ else
+ addThis->_memPool->SetTracked();
if ( _firstChild ) {
TIXMLASSERT( _lastChild );
TIXMLASSERT( _firstChild->_prev == 0 );
@@ -694,13 +703,14 @@ XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )
addThis->_next = 0;
}
addThis->_parent = this;
- addThis->_memPool->SetTracked();
- return addThis;
+ return addThis;
}
XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )
{
+ if (addThis->_document != _document)
+ return 0;
TIXMLASSERT( afterThis->_parent == this );
if ( afterThis->_parent != this ) {
return 0;
@@ -710,12 +720,15 @@ XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )
// The last node or the only node.
return InsertEndChild( addThis );
}
+ if (addThis->_parent)
+ addThis->_parent->Unlink( addThis );
+ else
+ addThis->_memPool->SetTracked();
addThis->_prev = afterThis;
addThis->_next = afterThis->_next;
afterThis->_next->_prev = addThis;
afterThis->_next = addThis;
addThis->_parent = this;
- addThis->_memPool->SetTracked();
return addThis;
}
diff --git a/tinyxml2.h b/tinyxml2.h
index 52f9180..d4c0919 100755
--- a/tinyxml2.h
+++ b/tinyxml2.h
@@ -734,6 +734,10 @@ public:
/**
Add a child node as the last (right) child.
+ If the child node is already part of the document,
+ it is moved from its old location to the new location.
+ Returns the addThis argument or 0 if the node does not
+ belong to the same document.
*/
XMLNode* InsertEndChild( XMLNode* addThis );
@@ -742,10 +746,19 @@ public:
}
/**
Add a child node as the first (left) child.
+ If the child node is already part of the document,
+ it is moved from its old location to the new location.
+ Returns the addThis argument or 0 if the node does not
+ belong to the same document.
*/
XMLNode* InsertFirstChild( XMLNode* addThis );
/**
Add a node after the specified child node.
+ If the child node is already part of the document,
+ it is moved from its old location to the new location.
+ Returns the addThis argument or 0 if the afterThis node
+ is not a child of this node, or if the node does not
+ belong to the same document.
*/
XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
diff --git a/xmltest.cpp b/xmltest.cpp
index 86b4ba2..80e42ea 100644
--- a/xmltest.cpp
+++ b/xmltest.cpp
@@ -1202,6 +1202,77 @@ int main( int argc, const char ** argv )
}
}
+ {
+ // Insertion with Removal
+ const char* xml = ""
+ ""
+ ""
+ ""
+ "element 1text"
+ ""
+ ""
+ ""
+ "";
+ const char* xmlInsideTwo = ""
+ ""
+ ""
+ ""
+ ""
+ "element 1text"
+ ""
+ ""
+ "";
+ const char* xmlAfterOne = ""
+ ""
+ ""
+ ""
+ "element 1text"
+ ""
+ ""
+ "";
+ const char* xmlAfterTwo = ""
+ ""
+ ""
+ ""
+ ""
+ "element 1text"
+ ""
+ "";
+
+ XMLDocument doc;
+ doc.Parse( xml );
+ XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
+ XMLElement* two = doc.RootElement()->FirstChildElement("two");
+ two->InsertFirstChild(subtree);
+ XMLPrinter printer1( 0, true );
+ doc.Accept( &printer1 );
+ XMLTest( "Move node from within to ", xmlInsideTwo, printer1.CStr());
+
+ doc.Parse( xml );
+ subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
+ two = doc.RootElement()->FirstChildElement("two");
+ doc.RootElement()->InsertAfterChild(two, subtree);
+ XMLPrinter printer2( 0, true );
+ doc.Accept( &printer2 );
+ XMLTest( "Move node from within after ", xmlAfterTwo, printer2.CStr());
+
+ doc.Parse( xml );
+ XMLNode* one = doc.RootElement()->FirstChildElement("one");
+ subtree = one->FirstChildElement("subtree");
+ doc.RootElement()->InsertAfterChild(one, subtree);
+ XMLPrinter printer3( 0, true );
+ doc.Accept( &printer3 );
+ XMLTest( "Move node from within after ", xmlAfterOne, printer3.CStr());
+
+ doc.Parse( xml );
+ subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
+ two = doc.RootElement()->FirstChildElement("two");
+ doc.RootElement()->InsertEndChild(subtree);
+ XMLPrinter printer4( 0, true );
+ doc.Accept( &printer4 );
+ XMLTest( "Move node from within after ", xmlAfterTwo, printer4.CStr());
+ }
+
// ----------- Performance tracking --------------
{
#if defined( _MSC_VER )