Categories
PHP Tips & Tutorials XML Tips and FAQ

How to delete / remove nodes in SimpleXML

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!

By Yang Yang

Hello, I'm Yang. I build online businesses that please people. Want to join in and post some useful articles on Kavoir.com? Shoot me a message.

14 replies on “How to delete / remove nodes in SimpleXML”

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.

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?

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.

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);

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??

@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 are closed.