I have several identical elements with different attributes that I'm accessing with SimpleXML:
<data>
<seg id="A1"/>
<seg id="A5"/>
<seg id="A12"/>
<seg id="A29"/>
<seg id="A30"/>
</data>
I need to remove a specific seg element, with an id of "A12", how can I do this? I've tried looping through the seg elements and unsetting the specific one, but this doesn't work, the elements remain.
foreach($doc->seg as $seg)
{
if($seg['id'] == 'A12')
{
unset($seg);
}
}
Contrary to popular belief in the existing answers, each Simplexml element node can be removed from the document just by itself and unset()
. The point in case is just that you need to understand how SimpleXML actually works.
First locate the element you want to remove:
list($element) = $doc->xpath('/*/seg[@id="A12"]');
Then remove the element represented in $element
you unset its self-reference:
unset($element[0]);
This works because the first element of any element is the element itself in Simplexml (self-reference). This has to do with its magic nature, numeric indices are representing the elements in any list (e.g. parent->children), and even the single child is such a list.
Non-numeric string indices represent attributes (in array-access) or child-element(s) (in property-access).
Therefore numeric indecies in property-access like:
unset($element->{0});
work as well.
Naturally with that xpath example, it is rather straight forward (in PHP 5.4):
unset($doc->xpath('/*/seg[@id="A12"]')[0][0]);
The full example code (Demo):
<?php
/**
* Remove a child with a specific attribute, in SimpleXML for PHP
* @link http://stackoverflow.com/a/16062633/367456
*/
$data=<<<DATA
<data>
<seg id="A1"/>
<seg id="A5"/>
<seg id="A12"/>
<seg id="A29"/>
<seg id="A30"/>
</data>
DATA;
$doc = new SimpleXMLElement($data);
unset($doc->xpath('seg[@id="A12"]')[0]->{0});
$doc->asXml('php://output');
Output:
<?xml version="1.0"?>
<data>
<seg id="A1"/>
<seg id="A5"/>
<seg id="A29"/>
<seg id="A30"/>
</data>