Подтвердить что ты не робот

PHP SimpleXML - Удалить xpath node

Я немного запутался относительно того, как я могу удалить родительский node что-то, что я могу найти через поиск по xpath:

$xml = simplexml_load_file($filename);
$data = $xml->xpath('//items/info[item_id="' . $item_id . '"]');
$parent = $data[0]->xpath("parent::*");
unset($parent);

Итак, он находит идентификатор элемента, никаких проблем нет, но unset не избавляется от этого <items> node. Все, что я хочу сделать, это удалить <items>...</items> для этого продукта. Очевидно, что в xml файле имеется множество узлов <items>, поэтому он не может сделать unset($xml->data->items), поскольку это приведет к удалению всего.

Любые идеи, которые очень ценят: -)

4b9b3361

Ответ 1

<?php
$xml = new SimpleXMLElement('<a><b/></a>');
unset($xml->b);
echo $xml->asxml();

это работает по назначению (удаление элемента < b/ > из документа), поскольку метод __ unset() (или эквивалент в коде модулей). Но когда вы вызываете unset($parent);, он удаляет только ссылку на объект, хранящуюся в $parent, но не влияет на сам объект или документ, хранящийся в $xml. Я вернусь к DOMDocument для этого.

<?php
$doc = new DOMDOcument;
$doc->loadxml('<foo>
  <items>
    <info>
      <item_id>123</item_id>
    </info>
  </items>
  <items>
    <info>
      <item_id>456</item_id>
    </info>
  </items>
  <items>
    <info>
      <item_id>789</item_id>
    </info>
  </items>
</foo>');
$item_id = 456;

$xpath = new DOMXpath($doc);
foreach($xpath->query('//items[info/item_id="' . $item_id . '"]') as $node) {
  $node->parentNode->removeChild($node);
}
echo $doc->savexml();

печатает

<?xml version="1.0"?>
<foo>
  <items>
    <info>
      <item_id>123</item_id>
    </info>
  </items>

  <items>
    <info>
      <item_id>789</item_id>
    </info>
  </items>
</foo>

Ответ 2

Это работает для меня. Не unset($parent);, но unset($parent[0]);:

$res    = $xml->xpath('//key/k[. = "string"]/parent::*');
$parent = $res[0];
unset($parent[0]);

Это работает путем создания саморекламы к элементу simplexml в $parent (или $res[0]).

Более подробное объяснение см. в связанном ответе в соответствующем вопросе Удалить ребенка с определенным атрибутом, в SimpleXML для PHP.

Ответ 3

Один из способов - импортировать SimpleXML node в DOMDocument, а затем удалить в DOMDocument. Не очень прямо, но он работает:

$xml = simplexml_load_file($filename);

$result = $xml->xpath("/cardsets/cardgroup");

foreach ($result as $el)
{
    if ($el['id'] == $id)
    {
        $domRef = dom_import_simplexml($el);
        $domRef->parentNode->removeChild($domRef);
        $dom = new DOMDocument('1.0');
        $dom->preserveWhiteSpace = false;
        $dom->formatOutput = true;
        $dom->loadXML($xml->asXML());
        $dom->save($filename);
        break;
    }
}

Ответ 4

Я бы наверняка подошел к этой проблеме как к фильтрующей, а не к удаленной.

Таким образом, копирование необходимых узлов в другую строку или создание другого документа XML, если на то пошло. Вы знаете, какие инструменты вы используете для таких сценариев.

Я думаю, что это не только решает вашу проблему, но, вероятно, вам легче читать и понимать. Тем не менее, вы не уверены в производительности. Расскажите, сколько узлов вы регулярно работаете.