If you just started to work with PHP SimpleXML you migth find some deadends that are quite hard to get out of. Here are a couple of tips and tricks for you to use with SimpleXML and always have a 100% perfect XML manipulation.
Removing nodes from the XML:
If you search PHP site for all functions from SimpleXML there is one that you wont find, deleteChild (or any name like it), but there is a work around that. SimpleXML works very similar to Arrays, so if you need to delete a child node just use unset.
Consider the XML bellow:
<?xml version="1.0" encoding="UTF-8" ?>
<rss>
<channel>
<item>
<title><![CDATA[Tom & Jerry]]></title>
</item>
</channel>
</rss>
If you want to remove the channel node, just do the following:
unset($xml->channel);
$newXMLText = $xml->asXML();
$h = fopen($xmlFilePath,’w+’);
// fwrite($newXMLText,$h);
fwrite($h,$newXMLText);
fclose($h);
This will successfully remove any child node from the XML file. The only bad thing about this is that when you open the file you will see pretty much everything out of indent and line breaks. The file will not have format at all. To fix this you will need to use a second work around:
Before witting the file, do the following:
$dom = new DomDocument();
$dom->loadXML($newXMLText);
$dom->formatOutput = true;
$formatedXML = $dom->saveXML();$h = fopen($xmlFilePath,’w+’);
// fwrite($formatedXML ,$h);
fwrite($h, $newXMLText);
fclose($h);
These are some hacks to not get too much involved with DOM, but if you are considering serious XML manipulation, then DOM XML is what you should be looking for.
Amazon MP3 Store




July 9th, 2009 at 10:38 AM
So I am new to simpleXML and I am working with your example but I can’t seem to get it to work. I think I have copied everything exactly but apparently I am missing something because I can’t get it to work:
channel);
$newXMLText = $xml->asXML();
$h = fopen('file.xml',’w+’);
fwrite($newXMLText,$h);
fclose($h);
}
?>
Any suggestions?
July 9th, 2009 at 10:40 AM
oops:
channel);
$newXMLText = $xml->asXML();
$h = fopen('file.xml',’w+’);
fwrite($newXMLText,$h);
fclose($h);
}
?>
July 9th, 2009 at 10:42 AM
Wow, I really wish wordpress would let you delete comments. Sigh.
Here is my code:
if( ! $xml = simplexml_load_file('file.xml') )
{
echo 'unable to load XML file';
}
else
{
unset($xml->channel);
$newXMLText = $xml->asXML();
$h = fopen('file.xml',’w+’);
fwrite($newXMLText,$h);
fclose($h);
}
July 9th, 2009 at 11:54 AM
Hi Thomas,
I believe that you are having difficulties because that is an example with only tips, so the full code is not there. Here is how it should look like;
BTW – I have just noticed that the fwrite on the code of the article is with the order of the elements inversed. I have fixed it on this comment, but just to keep track.
Just a note, this is a great way to format the xml, but if you are working with a big xml file, consider using only the DOM object to handle this. It’s a bit more complex, but has a ton of features that can make your coding a bit simpler and faster.
July 9th, 2009 at 11:58 PM
Hey thanks for your help, its hard to find good resources on simpleXML. I failed to add single quotes around the w+ in the fopen line and thats why it was failing. Thanks!
July 10th, 2009 at 9:35 AM
No worries… I’m working on a series of articles that will go from the basic of PHP to the advanced. I’m still working on the basics, but soon enough I will start on the medium level and I will surely focus a full article on the xml features of PHP, including simpleXML.
See you around.
July 10th, 2009 at 12:49 PM
Man, I hate to bother you with this but I have been looking at documentation all day and I can’t seem to figure it out-
I am using the last example you post for removing nodes but now I would like to identify the nodes I want to remove by searching for a specific attribute.
For example I want to remove the codeItem node with the id attribute set to ‘kill’:
RST12345668
RST12345668
I used your previous example to set my code up like this:
code->codeItem->id['kill']);
$newXmlText = $xml->asXML();
$fp = fopen(‘file.xml’,'w+’);
fwrite($fp, $newXmlText);
fclose($fp);
?>
Again, I am still not real clear on how to access attributes, so targeting a node with a specific attribute is really giving me a lot of trouble. Any suggestions?
July 10th, 2009 at 1:00 PM
Sorry, I screwed up the code tags again, the xml line I am trying to target looks like this:
RST12345668
July 10th, 2009 at 1:42 PM
Thomas,
The xml code tags did not appear no your comment, but anyway, to access, via simpleXml any node or value you will use something that looks like a mix of objects to array.
Let’s say that you have the following node, inside your xml:
<code>
<codeItem id=”kill”>RS1234567987<codeItem>
<code>
The codeItem is the first (and only) item from your code node, so to access it you would use:
$xml->code[0];
If you needed it be sure that the one that you are accessing is really the node with the “kill” id, then you would use:
$attr = $xml->code[0]->attributes();
echo $attr['id']; // it would result kill
So to unset (read delete) the node that have the id = kill you would use:
if ($attr['id'] == ‘kill’)
{
unset($xml->code[0]);
}
Working with simpleXML is quite fun because you can loop on it like you are on an array, you can directly access it as you would access an object and you can use xpath to directly access an value from the xml (like a query string).
Since it’s seems to be that you are starting, check out this article, from the Zend Developer Zone. It will help you to get an basic idea how to work with the simpleXML from PHP 5 – http://devzone.zend.com/article/688
Keep in mind that the xml must always be well formed to be accessed by the simpleXML library.
If you still in doubt, come back, ask and I will help you out as much as I can.
July 10th, 2009 at 1:50 PM
I have just realized that you might be trying to remove a node that have the value RST12345668. For that there are 3 ways:
1. Go directly to it, let’s say that it is the second node from the code node, so accessing it would be $xml->code[1];
2. Loop into all code subnodes and match the value
$keyToUnset = ”;
foreach($xml->code as $key => $codeItem)
{
$value = (string) $codeItem;
if ($value == ‘RST12345668′)
{
$keyToUnset = $key;
}
}
unset ($xml->code[$keyToUnset]);
3. Use XPath
unset ($xml->xpath(/code/coditem['RST12345668']));
For performance like, using xpath is the way to go.
Have fun.
July 10th, 2009 at 2:00 PM
I have multiple nodes named ‘codeItem’, so I am interested in picking out the node that has the attribute ‘id’ set to ‘kill’. Since I am so clumbsy with the wordpress comment declarations, checkout: http://cstang.hk/eater/demo.html for the php code and http://cstang.hk/eater/file.xml for the xml file I am working with.
July 10th, 2009 at 2:27 PM
Beautiful. Way better to read.
What you are missing on that function is simply the part that you get to the attribute.
$xml = simplexml_load_file(‘file.xml’);
$keyToKill = null;
foreach ( $xml->code as $key => $item)
{
$attr = $item->attributes();
if ($attr['id'] == ‘kill’)
$keyToKill = $key;
}
unset($xml->code->codeItem[$keyToKill]);
$newXmlText = $xml->asXML();
$fp = fopen(‘file.xml’,'w+’);
fwrite($fp, $newXmlText);
fclose($fp);
You only don’t unset the key inside the foreach loop to avoid errors during the loop.
Try this and let me know.
July 10th, 2009 at 3:31 PM
Thomas,
I have gone through the code, made some simple modifications, but you will be able to see it working fully.
Go to: http://www.dollartoolbox.com/simplexml/index.php
July 10th, 2009 at 2:50 PM
Hmm, still not working – I added a bracket to the ‘if’ statement but nothing changed. I have updated http://cstang.hk/eater/demo.html with the code I am currently using again. I also tried setting $key as a $xml->code->codeItem (instead of $xml->code) because I was worried that might be the problem but still nothing changed. I don’t think there is a permission problem on the server and I know the unset thing works with your earlier example so there must be some sort of small detail being overlooked here…
July 10th, 2009 at 4:04 PM
Wow, I think you may have just saved my sanity. Thank you – you didn’t have to help me, so I really appreciate it. Good luck with your blog!
July 10th, 2009 at 4:18 PM
Not a problem man … I know some times a second coder looking at the code helps …
come back any time .. this is the place that I keep every single line of code that one day I have used as a library or in some way helped me with PHP
December 8th, 2009 at 10:17 PM
Hi mcloide,
This article is really useful. I was wondering if there’s a function in simpleXML to set a value; update a value.
Marc
December 9th, 2009 at 9:57 AM
Hi Marc,
Simple XML is a great tool from PHP therefore, just like deleting, you don’t have a direct way to update a node but you do have a way around for it.
I have a more detailed article where you can find a good look around the SimpleXML element from PHP: http://mcloide.wordpress.com/2009/11/02/php-basic-series-playing-with-xml/
Check it out and if you still need something more direct or with more functions, use DOM for manipulating XML.
Have fun.