Question:
How to create a super-root node that contain the previous documentElement?
Example scenario:
Given the following snippet in PHP, the encapsulateRootNode
function has to create a new root node which contain the old full dom structure:
Example:
<anyContent>...</anyContent>
Become
<newRoot><anyContent>...</anyContent></newRoot>
The following code cannot be changed, and it has to be as fast as possible, so I discard any serialization, concatenation and parsing. I also would like to avoid to clone the full DOM structure.
$doc = new \DOMDocument();
if(!@$doc->loadXML($xmlContent))
{
$myLibrary->encapsulateRootNode($doc, 'newRoot');
}
My question is about how could I create the following function:
public function encapsulateRootNode( $doc, $tagName )
{
...
}
Information search:
Usually, replaceChild
is used for this kind of operation, but as there is no parent on which to call this function, I found myself lost in how to perform this operation.
I randomly tried some possibilities without success:
$newXml = $doc->createElement( $tagName);
$newXml->appendChild($doc->documentElement);
// strange behaviours / warning using the resulting DOM
or
$newXml = $doc->createElement( $tagName);
$old = $doc->documentElement;
$doc->documentElement = $newXml;
$newXml->appendChild($old);
// documentElement is read only
or even:
$fragment = $doc->createDocumentFragment();
$newXml = $doc->createElement( $tagName);
$fragment->appendChild($newXml);
$newXml->appendChild($doc->documentElement);
// How to convert this fragment back to the normal domDocument?
After some searching, I found this solution:
replaceChild work even on root, as DOMDocument extends DomNode.
The old root node has to bee append to the new root node AFTER to replace it, because if done before, documentElement become null and it is not possible to replace it any more.
$newXml = $doc->createElement( $tagName);
$old = $doc->documentElement;
doc->replaceChild($newXml, $old);
$newXml->appendChild($old);