用PHP SimpleXML从XML文档中移除多个兄弟节点

2022-04-13 00:00:00 xml php simplexml

我得到了一个相当复杂的XML文档,其中需要使用PHP/SimpleXML删除特定节点。我不确定我会在文件中找到它们的深度。

其工作原理如下: 用户插入了几个我需要删除的元素的ID。(这些ID指的是属性。)以下是一个简化的示例XML文件:

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

我不知道当我必须删除这些元素时它们会在哪里,所以我编写了一个遍历XML文档的递归函数:

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

该函数从根节点开始,访问所有子节点。当它遇到必须删除的节点时,它会使用DOM结构将其删除...但问题是:它只删除父节点的第一个兄弟节点。因此,当我想要从前面的XML文档中删除元素1、3和5时,它只会删除1和5(因为它们是各自父元素中第一个被删除的元素。

我不确定问题出在哪里。我已经考虑过销毁$Child对象,所以Foreach循环不能继续,但在这两行之前和之后都是一样的

$dom = dom_import_simplexml($child);
$dom->parentNode->removeChild($dom);

如有任何想法,我将不胜感激…


解决方案

假设您的xml是$xmlString,您可以使用如下内容:

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

相关文章