Index: XML-LibXML-1.66/LibXML.xs
===================================================================
--- XML-LibXML-1.66.orig/LibXML.xs
+++ XML-LibXML-1.66/LibXML.xs
@@ -830,6 +830,40 @@ LibXML_test_node_name( xmlChar * name )
     return(1);
 }
 
+/* Assumes that the node has a proxy. */
+static void
+LibXML_reparent_removed_node(xmlNodePtr node) {
+    /*
+     * Attribute nodes can't be added to document fragments. Adding
+    * DTD nodes would cause a memory leak. So document and owner are
+     * set to NULL.
+     */
+    if (node->type != XML_ATTRIBUTE_NODE
+        && node->type != XML_DTD_NODE) {
+        ProxyNodePtr docfrag = PmmNewFragment(node->doc);
+        xmlAddChild(PmmNODE(docfrag), node);
+        PmmFixOwner(PmmPROXYNODE(node), docfrag);
+    }
+}
+
+static void
+LibXML_set_int_subset(xmlDocPtr doc, xmlNodePtr dtd) {
+    xmlNodePtr old_dtd = (xmlNodePtr)doc->intSubset;
+    if (old_dtd == dtd) {
+        return;
+    }
+
+    if (old_dtd != NULL) {
+        xmlUnlinkNode(old_dtd);
+
+        if (PmmPROXYNODE(old_dtd) == NULL) {
+            xmlFreeDtd((xmlDtdPtr)old_dtd);
+        }
+    }
+
+    doc->intSubset = (xmlDtdPtr)dtd;
+}
+
 /* ****************************************************************
  * XPathContext helper functions
  * **************************************************************** */
@@ -4415,35 +4449,48 @@ replaceChild( self, nNode, oNode )
         xmlNodePtr oNode
     PREINIT:
         xmlNodePtr ret = NULL;
-        ProxyNodePtr docfrag = NULL;
     CODE:
-       if ( self->type == XML_DOCUMENT_NODE ) {
-                switch ( nNode->type ) {
-                case XML_ELEMENT_NODE:
-                case XML_DOCUMENT_FRAG_NODE:
-                case XML_TEXT_NODE:
-                case XML_CDATA_SECTION_NODE:
-                    XSRETURN_UNDEF;
-                    break;
-                default:
-                    break;
-                }
-        }
-        ret = domReplaceChild( self, nNode, oNode );
-        if (ret == NULL) {
-            XSRETURN_UNDEF;
-        }
-        else {
-                docfrag = PmmNewFragment( self->doc );
-                /* create document fragment */
-                xmlAddChild( PmmNODE(docfrag), ret );
-                RETVAL = PmmNodeToSv(ret, docfrag);
+        // if newNode == oldNode or self == newNode then do nothing, just return nNode.
+        if(nNode == oNode || self == nNode ){
+              ret = nNode;
+	      RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret)));
+	}
+	else{
+	    if ( self->type == XML_DOCUMENT_NODE ) {
+		    switch ( nNode->type ) {
+		    case XML_ELEMENT_NODE:
+			    warn("replaceChild with an element on a document node not supported yet!");
+			    XSRETURN_UNDEF;
+			    break;
+		    case XML_DOCUMENT_FRAG_NODE:
+			    warn("replaceChild with a document fragment node on a document node not supported yet!");
+			    XSRETURN_UNDEF;
+			    break;
+		    case XML_TEXT_NODE:
+		    case XML_CDATA_SECTION_NODE:
+			    warn("replaceChild with a text node not supported on a document node!");
+			    XSRETURN_UNDEF;
+			    break;
+		    default:
+			    break;
+		    }
+	    }
+	    ret = domReplaceChild( self, nNode, oNode );
+	    if (ret == NULL) {
+		    XSRETURN_UNDEF;
+	    }
+	    else {
+	        LibXML_reparent_removed_node(ret);
+		RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret)));
+		if (nNode->type == XML_DTD_NODE) {
+			LibXML_set_int_subset(nNode->doc, nNode);
 
+		}
                 if ( nNode->_private != NULL ) {
                     PmmFixOwner( PmmPROXYNODE(nNode),
                                  PmmOWNERPO(PmmPROXYNODE(self)) );
                 }
-                PmmFixOwner( SvPROXYNODE(RETVAL), docfrag );
+	    }
         }
     OUTPUT:
         RETVAL
Index: XML-LibXML-1.66/dom.c
===================================================================
--- XML-LibXML-1.66.orig/dom.c
+++ XML-LibXML-1.66/dom.c
@@ -741,7 +741,7 @@ domReplaceChild( xmlNodePtr self, xmlNod
         return NULL;
 
     if ( new == old ) 
-        return new;
+        return NULL;
  
     if ( new == NULL ) {
         /* level2 sais nothing about this case :( */
