note 112886 added to domdocument.savexml
| From: | fbernoldi at gmail dot com | 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