Reputation: 33
Unable to remove all children from the XML document
<?xml version="1.0" encoding="UTF-8"?>
<routes>
<route name="admin" />
<!---->
<route name="blog" bla bla/>
<route name="blog" bla bla/>
<route name="blog" bla bla/>
</routes>
$xml = simplexml_load_file('routes.xml');
$dom_sxe = dom_import_simplexml($xml); $dom = new \DOMDocument('1.0'); $dom_sxe = $dom->importNode($dom_sxe, true); $dom_sxe = $dom->appendChild($dom_sxe); foreach ($dom->getElementsByTagName('route') as $route) { if($route->getAttribute('name') === 'blog') { $route->parentNode->removeChild($route); echo $route->getAttribute('name'); } } echo $dom->saveXML();
removes only 2 elements with the attribute blog
Upvotes: 1
Views: 74
Reputation: 97718
The problem is that you are modifying the document while looping through it - a bit like modifying an array in the middle of a foreach
loop.
Note that $dom->getElementsByTagName
"returns a new instance of class DOMNodeList
" not just an array. So as the loop goes round it is retrieving the elements as it goes; removing one will mess up its assumptions about what exists.
One solution to this is to copy the entire list of matches into a plain array before you loop over it. There is a built-in function iterator_to_array()
which will do just that for you all in one go - basically, it runs a foreach
over the iterable object, and collects the values into an array.
So the simplest (though not necessarily most readable etc) solution is to change this line:
foreach ($dom->getElementsByTagName('route') as $route)
to this:
foreach (iterator_to_array($dom->getElementsByTagName('route')) as $route)
Here's a live demo of the fixed code.
Upvotes: 1