我有一个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>
如何element:data
element:input
1 中的attribute:id
我已经阅读了这个例子php-delete-xml-element,但这与我正在寻找的深度不同。
NB:我希望使用DOMDocument
答案 0 :(得分:2)
使用 DOMDocument 实现此目的的方法,类似于sevavietl发布的非常好的示例,是做同样的事情并使用XPath找到我们的节点。
DOMNode类有一个removeChild
方法,我们的元素扩展为DOMElement。为了删除节点,我们需要使用包含我们想要删除的节点的父元素。在所有DOMNode上,我们有一个名为parentNode
的属性,如果没有父级,则此属性将始终返回父级或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"]
我们要查找的节点必须具有id [contains(.,'1')]
该节点必须包含文本1
/..
从我们找到的节点向上移动一层上下文节点始终是传递给XPath的query
方法的第二个参数。因此,如果我们将它们放在一起,我们将得到XPath语句,找到名称属性等于id且包含文本1的所有输入节点。从那里将DOM树向上移动一级。
例如,如果您的DOM树包含其他元素,其中包含具有相同属性的input
元素,并且我们只想删除data
元素,我们可以将查询更改为
.//data/input[@name="id"][contains(., '1')]/..
现在,这意味着查找具有input
直接祖先的所有data
个节点。然后像以前一样应用我们的其他条件。
答案 1 :(得分:1)
我知道您希望使用 DOMDocument 执行此操作,但如果您只是需要删除节点,则可以使用SimpleXmlElement和XPath执行此操作:
$xml = new SimpleXMLElement($xmlString);
$id = 1;
$data = $xml->xpath('//input[@name="id"][.=' . $id . ']/..');
if (isset($data[0])) {
unset($data[0]->{0});
}
解释了unset()
的魔力here。