按子元素的值删除XML个元素

Delete XML element by value of child element

我有一个 xml 文件,例如:

<file>
    <data>
        <input name="id">1</input>
        <input name="name">Mike</input>
    </data>
    <data>
        <input name="id">2</input>
        <input name="name">Andree</input>
    </data>
</file>

如何通过 attribute:id

删除值 element:input 1 中的 element:data

我读过这个例子 php-delete-xml-element 但是它没有我正在寻找的深度。

注意: 我希望使用 DOMDocument

我知道你想用 DOMDocument 来做到这一点,但如果你只需要删除节点,你可以用 SimpleXmlElement and XPath:

$xml = new SimpleXMLElement($xmlString);

$id = 1;

$data = $xml->xpath('//input[@name="id"][.=' . $id . ']/..');

if (isset($data[0])) {
    unset($data[0]->{0});
}

Here is working demo.

unset()的魔法解释here

使用 DOMDocument 实现此目的的方法类似于 sevavietl 发布的非常好的示例,是做同样的事情并使用 [= 找到我们的节点25=]。

DOMNode class, which our elements extend as a DOMElement 上有一个 removeChild 方法。为了删除节点,我们需要使用包含我们希望删除的节点的父元素。在所有 DOM 节点上,我们有一个名为 parentNode 的 属性 并且此 属性 将始终 return 父节点或 null 如果没有父节点(例如,当您到达 documentElement 节点或您创建了一个节点但未插入它时)。

// Load the dom document
$document = new DOMDocument();
$document->load('./path/to/xml.xml'); 
// use $document->loadXML($xml) if you're passing a XML string

// Create XPath for the document
$xpath = new DOMXpath($document);

// Use XPath to locate our node(s)
$nodelist = $xpath->query('.//input[@name="id"][contains(., '1')]/..', $document->documentElement);

// Iterate over our node list and remove the data
foreach ($nodelist as $dataNode) {
    if ($dataNode->parentNode === null) {
        continue; // Uh oh, no parent node?
    }
    // Get the data node parent (file) so we can call remove child
    $dataNode->parentNode->removeChild($dataNode);
}

所有真正的魔法都在我们的 XPath 中:

  • .//input从上下文节点中,找到任意深度的输入元素
  • [@name="id"]我们要找的节点必须有一个name属性为id
  • [contains(.,'1')] 节点必须包含文本 1
  • /..从找到的节点开始,向上移动一级

上下文节点始终是传递给 XPath 的 query 方法的第二个参数。因此,如果我们将它们放在一起,我们将得到我们的 XPath 语句,找到名称属性等于 id 并包含文本 1 的所有输入节点。从那里向上移动 DOM 树一级。

例如,如果您的 DOM 树包含其他元素,这些元素还包括具有相同属性的 input 元素,而我们只想删除 data 元素,我们可以将查询更改为

.//data/input[@name="id"][contains(., '1')]/..

现在这意味着找到所有 input 个具有 data 直接祖先的节点。然后像以前一样应用我们的其他条件。