Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DOM replaceChild not replacing all specified elements

Consider the following code:

$xml = <<<XML
<root>
<region id='thisRegion'></region>
<region id='thatRegion'></region>
</root>
XML;

$partials['thisRegion'] = "<p>Here's this region</p>";
$partials['thatRegion'] = "<p>Here's that region</p>";
$DOM = new DOMDocument;
$DOM->loadXML($xml);

$regions = $DOM->getElementsByTagname('region');

foreach( $regions as $region )
{
    $id = $region->getAttribute('id');
    $partial = $DOM->createDocumentFragment();
    $partial->appendXML( $partials[$id] );
    $region->parentNode->replaceChild($partial, $region);

}

echo $DOM->saveXML();

The output is:

<root>
<p>Here's this region</p>
<region id="thatRegion"/>
</root>

I cannot for the life of me figure out why all of the region tags aren't being replaced. This is a problem in my project, and at first I thought that it wasn't replacing elements I appended after the loadXML, but with some experimenting I haven't been able to narrow down the pattern here.

I would appreciate a code correction to allow me to replace all tags in a DOMDocument with a given Element Node. I also wouldn't mind any input into a more efficient/practical way to execute this if I haven't found it.

Thanks in advance!

[edit] PHP 5.3.13

like image 223
tryexceptcontinue Avatar asked Jun 16 '12 22:06

tryexceptcontinue


People also ask

How do you correctly replace an existing element in HTML using the replaceChild () method?

First, select the DOM element that you want to replace. Then, create a new element. Finally, select the parent element of the target element and replace the target element by the new element using the replaceChild() method.

How can we replace a node with an existing node in the DOM structure?

Inserting Nodes into the DOM The methods appendChild() and insertBefore() are used to add items to the beginning, middle, or end of a parent element, and replaceChild() is used to replace an old node with a new node.

Which of the following methods replaces the specified child element of the current element with a new element?

The replaceChild() method of the Node element replaces a child node within the given (parent) node.

Which method is used to replace nodes?

The replaceChild() method is used to replace a node.


1 Answers

NodeLists are live. So when you remove an item inside the document, the NodeList also will be modified. Avoid using a reference to the NodeList and start replacing at the last item:

$DOM = new DOMDocument;
$DOM->loadXML($xml);
$regions = $DOM->getElementsByTagname('region');

$regionsCount = $DOM->getElementsByTagName('region')->length;
for($i= $regionsCount;$i>0;--$i)
{   
    $region=$DOM->getElementsByTagName('region')->item($i-1);
    $id = $region->getAttribute('id');
    $partial = $DOM->createDocumentFragment();
    $partial->appendXML( $partials[$id] );
    $region->parentNode->replaceChild($partial, $region);
}

echo $DOM->saveXML();
?>

http://codepad.org/gTjYC4hr

like image 79
Dr.Molle Avatar answered Nov 03 '22 00:11

Dr.Molle