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!
You should also read:
- PHP: How to process a string one byte (character) at a time
- PHP: Check if A String Contain Only Uppercase / Capital Letters
- PHP: Change Tabs to Spaces and Vice Versa in String | Change Tab Sizes / Lengths in Strings
- JavaScript: Split and Divide Text String by A Delimiter
- PHP: What is Hash? | Hashing a String | Generate Hash of Strings


Facebook
Twitter
Google Plus
{ 10 comments… read them below or add one }
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
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.
@david, that’s some outstanding work! :D
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);
@Peter
thanks it worked very good here!
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??
+1 for Peter
Works great!
Thank you very much.
:):D
[code]Hi.[/code]
[b]Hi.[/b]
{ 1 trackback }