How to delete / remove nodes in SimpleXML

by Yang Yang on December 2, 2008

The other day I was testing and playing with SimpleXML to process some XML documents when I came to a problem – I realized that I needed to delete a node before dumping the XML object to text. However if you are familiar with SimpleXML, it doesn’t come with a down right way to remove nodes like DOMDocument does.

A few searches on Google neither helped – people were just saying how simple SimpleXML was and it simply could not fulfill a task like this.

You know what I did? Yes, just ‘unset‘ the node.

$str = <<<STR
<a>
  <b>
    <c>
    </c>
  </b>
</a>
STR;

$xml = simplexml_load_string($str);
unset($xml –> a –> b –> c); // this would remove node c
echo $xml –> asXML(); // xml document string without node c

There you go!

Niels Kristensen December 13, 2008 at 1:11 am

Oh so this is how to do it and it seems to be easy  Now I don’t need to bother our IT whenever I want to remove SimpleXML . Thanks for covering this topic dude 

david stokes January 14, 2009 at 5:10 am

The problem with this approach (and all the approaches I have seen) is that you need to know the the xml tree. What happens if you have multiple nodes of the same type?

You can use:
unset($xmlNode->file[$ix]);

but you still need to know the name of the node you want to delete (above it is “file”).

Still this approach does allow you to iterate through nodes deleting the ones you want to:

$ix = count($xmlNode->file);
for ($ix– ; $ix >= 0 ; $ix–)
{
$xmlSubNode = $xmlNode->file[$ix];
if (doYouWantToDeleteThisNode($xmlSubNode))
{
unset($xmlNode->file[$ix]);
}
}

The reason I count backwards is because deleting the nodes causes the later indices to change. You can count up – you just need to make sure that you do not increment your counter variable (ix above) when you delete the node.

Yang Yang January 14, 2009 at 10:58 am

@david, that’s some outstanding work! 😀

CeremCem January 29, 2009 at 7:36 pm

I have faced with the problem that David described, and found a simpler solution at php.net.

Steps are as follows:
* Get the node object in any ways (eg. via xpath())
* import the node as DOM object
* perform the removal.

As an example:

list($theNodeToBeDeleted) = $myXml->xpath($someXPathQuery);
$oNode = dom_import_simplexml($theNodeToBeDeleted);
$oNode->parentNode->removeChild($oNode);

Simple enaugh, huh?

Peter April 13, 2009 at 5:07 pm

I made a class extension based on the code in the last post. In my case I needed to remove nodes by specific attributes and values. So here’s my effort:

class SimpleXMLExtend extends SimpleXMLElement
{
public function addCData($nodename,$cdata_text)
{
$node = $this->addChild($nodename); //Added a nodename to create inside the function
$node = dom_import_simplexml($node);
$no = $node->ownerDocument;
$node->appendChild($no->createCDATASection($cdata_text));
}

public function removeNodeByAttrib($nodename,$attribute,$value){
foreach ($this->xpath($nodename) as $key => $node) {
foreach($node->attributes() as $attrib => $val){
if ($attrib == $attribute && $val == $value) {
$oNode = dom_import_simplexml($node);
}
}
}
$oNode->parentNode->removeChild($oNode);
}

}

Hope this may be helpful for anyone.

geoffrey September 2, 2009 at 7:46 pm

I’m using this class.
I always receive this error:

Fatal error: Call to a member function removeChild() on a non-object on line 20.

And this is line 20 : $oNode->parentNode->removeChild($oNode);

Yang Yang July 5, 2012 at 6:43 pm

Thanks for the contribution, Peter!

tresloukadu November 7, 2009 at 6:09 am

@Peter

thanks it worked very good here!

Niels October 4, 2010 at 5:07 am

Hi,
I came across this solution to delete nodes from an xml document. This example explains how to delete a childnode from a childnode from… etc.

Now i have a xml document in the following structure:

foo
bar
baz

Now i want to delete the bar nodes, but unfortunately Unset doesn’t work here…
Anybody any suggestions??

Jonathan Asquier May 7, 2011 at 4:46 pm

+1 for Peter

Works great!

bds` December 26, 2011 at 7:44 pm

Thank you very much.

:)
😀

[code]Hi.[/code]
[b]Hi.[/b]

Vishwas August 25, 2012 at 4:15 am

hey! thnx
But what if there are 5 node, and i want to delete, say the 3rd one ?

V.

Luxian March 5, 2013 at 8:23 pm

@david stokes: You’re comment saved my day! Thanks you and Yang Yang for the info.

@Yang Yang: Maybe you should update the post with David’s comment

@Vishwas: unset($element->childtagname[2]); // indices start from 0, and 2 is the third element

Comments on this entry are closed.

{ 1 trackback }

Previous post:

Next post: