note 112886 added to domdocument.savexml

From: Date: Thu, 01 Aug 2013 20:24:34 +0000
Subject: note 112886 added to domdocument.savexml
Groups: php.notes 
Request: Send a blank email to php-notes+get-195852@lists.php.net to get a copy of this message
Hello, I had an unexpected behavior in some parsing code, because of this saveXML method that is saving the tags without namespace specification. If you try to load into a DOMDocument a string saved from a DOMNode that has a referenced namespace but it the original document it was not defined in that element, you get a not well formed xml. In the example you can see the issue and a possible solution, the other solution may be add to the ChildElement node the namespace reference (<testNS:ChildElement testNS="http://example.org">), but in my scenario it was not needed. <?php //Test XML $test_xml = "<?xml version=\"1.0\"?> <testNS:RootNode xmlns:testNS=\"http://example.org\"> <testNS:ChildElement> <testNS:AnotherChildElement>I'm a Another Child node.</testNS:AnotherChildElement> </testNS:ChildElement> </testNS:RootNode>"; //We define our Test DOMDocument $domDoc = new DOMDocument("1.0"); $domDoc->loadXML($test_xml); //We use xpath to search ChildElement: $domXPath = new DOMXPath($domDoc); $domXPath->registerNamespace("testNS", "http://example.org"); $DOMNodeList_ChildElement = $domXPath->query("//testNS:RootNode/testNS:ChildElement"); $ChildElement = $DOMNodeList_ChildElement->item(0); echo "Not usefull xml to load in another document:\n\n"; echo $domDoc->saveXML($ChildElement); /* Output here: * * Not usefull xml to load in another document: * * <testNS:ChildElement> * <testNS:AnotherChildElement>I'm a Another Child node.</testNS:AnotherChildElement> * </testNS:ChildElement> * */ /** * Function to help us clone the element to another document. * @param DOMElement $node The node to clone. * @param DOMDocument $doc The document where we are going to reference the elements. * @return DOMElement The new cloned element without namespace. */ function cloneNode($node, $doc) { //Create new element with the original localName (w/o namespace) $nd = $doc->createElement($node->localName); //Clone attributes foreach($node->attributes as $value) $nd->setAttribute($value->localName, $value->value); //No more childs then we finish. if (!$node->childNodes) return $nd; //We have childs, add them foreach($node->childNodes as $child) { if ($child->nodeName=="#text") //Only needed to clone text nodes, i.e. text comments, spaces, tabs. etc. $nd->appendChild($doc->createTextNode($child->nodeValue)); else $nd->appendChild(cloneNode($child, $doc)); //recursion to clone all children. } return $nd; } //New Document to reference the new node without namespaces $domDoc2 = new DOMDocument("1.0"); //We clone this node taking out the namespace $new_node = cloneNode($ChildElement, $domDoc2); echo "\n\nWe can load this into a DOMDocument without problems:\n\n"; echo $domDoc2->saveXML($new_node); /* * We can load this into a DOMDocument without problems: * * <ChildElement> * <AnotherChildElement>I'm a Another Child node.</AnotherChildElement> * </ChildElement> */ ?> ---- Server IP: 201.216.232.240 Probable Submitter: 190.2.0.5 (proxied: 190.2.0.5) ---- Manual Page -- http://php.net/manual/en/domdocument.savexml.php Edit -- https://master.php.net/note/edit/112886 Del: integrated -- https://master.php.net/note/delete/112886/integrated Del: useless -- https://master.php.net/note/delete/112886/useless Del: bad code -- https://master.php.net/note/delete/112886/bad+code Del: spam -- https://master.php.net/note/delete/112886/spam Del: non-english -- https://master.php.net/note/delete/112886/non-english Del: in docs -- https://master.php.net/note/delete/112886/in+docs Del: other reasons-- https://master.php.net/note/delete/112886 Reject -- https://master.php.net/note/reject/112886 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#195852) next »