BobFlemming
BobFlemming

Reputation: 2040

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

Upvotes: 2

Views: 13887

Answers (2)

Sander Marechal
Sander Marechal

Reputation: 23216

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>

Upvotes: 5

Slava
Slava

Reputation: 2050

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.

Upvotes: 2

Related Questions