关于PHP SimpleXML:PHP SimpleXML-删除xpath节点

PHP SimpleXML - Remove xpath node

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

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

因此,它找到了项目ID,在那里没有问题-但是未设置的操作不会摆脱此节点。 我要做的就是删除此产品的...。 显然,xml文件中有许多节点,因此它不能执行unset($xml->data->items),因为这会删除所有内容。

任何想法表示赞赏:-)


1
2
3
4
<?php
$xml = new SimpleXMLElement('<b/>');
unset($xml->b);
echo $xml->asxml();

由于调用了__unset()方法(或模块代码中的等效方法),因此可以按预期工作(从文档中删除元素)。
但是,当您调用unset($parent);时,它仅删除$ parent中存储的对象引用,而不会影响对象本身或$ xml中存储的文档。
为此,我将恢复为DOMDocument。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?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();

版画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0"?>
<foo>
  <items>
    <info>
      <item_id>123</item_id>
    </info>
  </items>

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


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

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

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

有关更详细的说明,请参见相关问题"在PHP的SimpleXML中,删除具有特定属性的子级"中的相关答案。


一种方法是将SimpleXML节点导入DOMDocument,然后在DOMDocument中删除。并不是很简单,但是它可以工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$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;
    }
}

我肯定会将此问题视为过滤问题-而不是消除问题。

因此,为此需要将所需的节点复制到另一个字符串中或建立另一个XML文档。您知道在这种情况下使用什么工具。

我认为这不仅解决了您的问题,而且可能使您更容易阅读和理解。不过,不确定性能如何。告诉我们您经常使用多少个节点。