У меня есть 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-удаления-XML-элемент но это не тот уровень глубины, который я ищу.
NB: Я надеюсь использовать DOMDocument
Я знаю, что ты хотел сделать это с 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()
объясняется Вот.
Способ достичь этого с DOMDocument, похожий на очень хороший пример, опубликованный sevavietl, состоит в том, чтобы сделать то же самое и найти наш узел, используя XPath.
Eсть removeChild
метод на DOMNode класс, который наши элементы расширяют как 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"]
узлы, которые мы ищем, должны иметь атрибут name[contains(.,'1')]
Узел должен содержать текст 1
/..
От узла, который мы нашли, поднимитесь на один уровень вверхУзел контекста всегда является вторым аргументом, передаваемым query
метод XPath. Поэтому, если мы соберем все это вместе, мы получим наш оператор XPath, найдем все входные узлы с атрибутом имени, равным id и содержащим текст 1. Оттуда вернемся вверх по дереву DOM на один уровень.
Если, например, ваше дерево DOM содержит другие элементы, которые также включают input
элементы с такими же атрибутами, и мы только хотим удалить data
элементы, мы можем изменить запрос
.//data/input[@name="id"][contains(., '1')]/..
Теперь это значит найти все input
узлы, которые имеют прямой предок data
, Тогда примените наши другие условия как прежде.