Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove a child with a specific attribute, in SimpleXML for PHP

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);     } } 
like image 492
TimTowdi Avatar asked Nov 04 '08 16:11

TimTowdi


1 Answers

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> 
like image 98
hakre Avatar answered Sep 17 '22 13:09

hakre