简体   繁体   中英

Remove multiple sibling nodes from XML document with PHP SimpleXML

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...

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);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM