PHP SimpleXML - 删除xpath节点

时间:2010-03-14 13:37:30

标签: php simplexml

我有点困惑的是如何删除我可以通过xpath搜索找到的东西的父节点:

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

所以,它找到了项目ID,没有问题 - 但是未设置的东西没有摆脱这个<items>节点。我想要做的就是删除此产品的<items>...</items>。显然,xml文件中有大量<items>个节点,因此它不能删除所有节点unset($xml->data->items)

任何想法都非常感激: - )

4 个答案:

答案 0 :(得分:14)

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

这可以按预期工作(从文档中删除&lt; b /&gt;元素),因为调用了__unset() method(或模块代码中的等价物)。
但是当你调用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>

答案 1 :(得分:13)

它对我来说就像这样。不是unset($parent);而是unset($parent[0]);

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

这可以通过在$parent(或$res[0])中创建对simplexml-element 的自引用来实现。

有关更详细的说明,请参阅相关问题a related answer中的Remove a child with a specific attribute, in SimpleXML for PHP

答案 2 :(得分:2)

一种方法是将SimpleXML节点导入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;
    }
}

答案 3 :(得分:1)

我肯定会将此问题作为过滤问题处理 - 而不是删除问题。

因此,将所需节点复制到另一个字符串中或为此构建另一个XML文档。您知道这些场景使用的工具。

我认为这不仅可以解决您的问题,还可以让您更轻松地阅读和理解。但是不确定性能命中率。告诉我们您经常使用多少个节点。