Reputation: 147
I've got a fairly complex XML document, where I need to remove specific nodes with PHP / SimpleXML. I don't know for sure the depth where I will find them in the document.
It works as follows: The user inserts a few IDs of elements which I need to delete. (these IDs refer to an attribute.) Here's a simplified exemplary XML File:
<?xml version="1.0"?>
<root>
<firstlayer>
<secondlayer>
<thirdlayer>
<element id="1"/>
<element id="2"/>
<element id="3"/>
</thirdlayer>
<thirdlayer>
<element id="4"/>
<element id="5"/>
</thirdlayer>
</secondlayer>
</firstlayer>
</root>
I don't know where the elements are going to be when I have to delete them, so I wrote a recursive function which traverses the XML document:
function traverseNodes($node) {
foreach($node->children() as $child) {
if($child->getName()=="element") {
// Code for finding out if node has to be deleted
if(deleteMe) {
$dom = dom_import_simplexml($child);
$dom->parentNode->removeChild($dom);
} else {
traverseNodes($child); // visit the children
}
}
else {
// do some other stuff with the rest of the nodes
// and recursively call the function
}
}
}
This function starts at the root node and visits all the children. When it encounters a node which has to be deleted, it removes it by using the DOM-structure...but here is the problem: It only removes the first sibling of a parent node. So when I want to delete the elements 1, 3 and 5 from the previous XML document, it will only remove 1 and 5 (for they are the first ones to be deleted in the respective parent element.
I'm not sure what the problem is. I already thought about destroying the $child object, so the foreach-loop can't continue, but it's the very same before and after the two lines
$dom = dom_import_simplexml($child);
$dom->parentNode->removeChild($dom);
I'd be really grateful about any ideas...
Upvotes: 0
Views: 1817
Reputation: 4456
Assuming your XML is in $xmlString, you can use something like:
$xml = new SimpleXMLElement( $xmlString );
$ids_to_delete = array( 1, 4 );
foreach ($ids_to_delete as $id) {
$result = $xml->xpath( "//element[@id='$id']" );
foreach ( $result as $node ) {
$dom = dom_import_simplexml($node);
$dom->parentNode->removeChild($dom);
}
}
Upvotes: 3