Удалить элемент XML по значению дочернего элемента

У меня есть 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

0

Решение

Я знаю, что ты хотел сделать это с 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() объясняется Вот.

1

Другие решения

Способ достичь этого с 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, Тогда примените наши другие условия как прежде.

2

По вопросам рекламы [email protected]