PHP XML remove element and all children by name

I have an XML file structured as:

<root>
  <featured>
    <title></title>
    <tweet></tweet>
    <img></img>
  </featured>
</root> 

The element is added dynamically , the user needs the option to remove the element on certain occasions,

I have tried a few variations of code including:

        $featureddel = $xpath->query('//featured');

while ( $featureddel->hasChildNodes()){
$featureddel->removeChild($featureddel->childNodes->item(0));
}

which gives me a error:

PHP Fatal error: Call to undefined method DOMNodeList::hasChildNodes() 

Ive also tried:

$featureddel= $dom->getElementsByTagName('featured');
$featureddel->parentNode->removeChild($featureddel);

which returns:

PHP Fatal error: Call to a member function removeChild() on a non-object

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

Both DOMElement::getElementsByTagName and DOMXPath::query return a DOMNodeList. Your code seems to be expecting a single DOMNode instead. Try this:

$featureddel = $xpath->query('//featured');
// OR:
// $featuredde1 = $dom->getElementsByTagName('featured');

foreach ($featuredde1 as $node) {
    $node->parentNode->removeChild($node);
}

Edit: This exact code works as expected for me (PHP 5.3, Debian Squeeze):

<?php 
$xml = '<root>
  <featured>
    <title></title>
    <tweet></tweet>
    <img></img>
  </featured>
</root>';    
$dom = new DOMDocument();
$dom->loadXML($xml);
$featuredde1 = $dom->getElementsByTagName('featured');

foreach ($featuredde1 as $node) {
    $node->parentNode->removeChild($node);
}
echo $dom->saveXML();

The output is:

<?xml version="1.0"?>
<root>

</root>

Solution 2

This should do it:

foreach ($featureddel as $node) {
    $node->parentNode->removeChild($node);
}

You’re probably just forgetting that with both xPath and getElementsByTagName you get a list (DOMNodeList) of items. That object itself only has a property $length, which you can use to determine how many objects are on the list, and function item($index), which returns specified DOMNode from the list. DOMNodeList is also iteratable through foreach.
So besides foreach like I wrote above you can also do:

for ($i = 0; $i < $featureddel->length; $i++) {
    $temp = $featureddel->item($i); //avoid calling a function twice
    $temp->parentNode->removeChild($temp);
}

But foreach is usually more preferred.

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply