I have several identical elements with different attributes that I\'m accessing with SimpleXML:
If you want to cut list of similar (not unique) child elements, for example items of RSS feed, you could use this code:
for ( $i = 9999; $i > 10; $i--) {
unset($xml->xpath('/rss/channel/item['. $i .']')[0]->{0});
}
It will cut tail of RSS to 10 elements. I tried to remove with
for ( $i = 10; $i < 9999; $i ++ ) {
unset($xml->xpath('/rss/channel/item[' . $i . ']')[0]->{0});
}
But it works somehow randomly and cuts only some of the elements.
For future reference, deleting nodes with SimpleXML can be a pain sometimes, especially if you don't know the exact structure of the document. That's why I have written SimpleDOM, a class that extends SimpleXMLElement to add a few convenience methods.
For instance, deleteNodes() will delete all nodes matching a XPath expression. And if you want to delete all nodes with the attribute "id" equal to "A5", all you have to do is:
// don't forget to include SimpleDOM.php
include 'SimpleDOM.php';
// use simpledom_load_string() instead of simplexml_load_string()
$data = simpledom_load_string(
'<data>
<seg id="A1"/>
<seg id="A5"/>
<seg id="A12"/>
<seg id="A29"/>
<seg id="A30"/>
</data>'
);
// and there the magic happens
$data->deleteNodes('//seg[@id="A5"]');
This work for me:
$data = '<data>
<seg id="A1"/>
<seg id="A5"/>
<seg id="A12"/>
<seg id="A29"/>
<seg id="A30"/></data>';
$doc = new SimpleXMLElement($data);
$segarr = $doc->seg;
$count = count($segarr);
$j = 0;
for ($i = 0; $i < $count; $i++) {
if ($segarr[$j]['id'] == 'A12') {
unset($segarr[$j]);
$j = $j - 1;
}
$j = $j + 1;
}
echo $doc->asXml();
There is a way to remove a child element via SimpleXml. The code looks for a element, and does nothing. Otherwise it adds the element to a string. It then writes out the string to a file. Also note that the code saves a backup before overwriting the original file.
$username = $_GET['delete_account'];
echo "DELETING: ".$username;
$xml = simplexml_load_file("users.xml");
$str = "<?xml version=\"1.0\"?>
<users>";
foreach($xml->children() as $child){
if($child->getName() == "user") {
if($username == $child['name']) {
continue;
} else {
$str = $str.$child->asXML();
}
}
}
$str = $str."
</users>";
echo $str;
$xml->asXML("users_backup.xml");
$myFile = "users.xml";
$fh = fopen($myFile, 'w') or die("can't open file");
fwrite($fh, $str);
fclose($fh);
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
This code was taken from How to delete / remove nodes in SimpleXML.
With FluidXML you can use XPath to select the elements to remove.
$doc = fluidify($doc);
$doc->remove('//*[@id="A12"]');
https://github.com/servo-php/fluidxml
The XPath //*[@id="A12"]
means:
//
)*
)id
equal to A12
([@id="A12"]
).