按子元素的值删除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});
}
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
直接祖先的节点。然后像以前一样应用我们的其他条件。
我有一个 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});
}
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
直接祖先的节点。然后像以前一样应用我们的其他条件。