【问题标题】:php DOMDocument xml filtering elementsphp DOMDocument xml过滤元素
【发布时间】:2026-02-02 05:20:09
【问题描述】:

我现在已经失去了半天的时间。虽然不是专家。为什么用 php 遍历和操作 xml 比在纸上处理数据更难(看起来)?为什么不能有一个像 jQuery 这样的简单系统呢?
我一直在尝试根据一个简单的条件从一个长列表(580 个元素)中删除一些元素:if (element['attr'] == value) {remove element},但我就是没有到达那里。
这是我的代码:

$xml = simplexml_load_file('xml/suchia.xml');
$dom = new DOMDocument('1.0');
$dom->loadXML($xml->asXML());
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
foreach ($dom->getElementsByTagName('image') as $node) {
   echo 'Checking '.$node->getAttribute('id').'<br />';
   if ($node->getAttribute('value') == 'useless') {
      echo $node->getAttribute('id').' deleted.<br />';
      $node->parentNode->removeChild($node);
   }
}
$dom->save('xml/suchia.xml');

我从第一个回显中看到的主要问题是 foreach 并没有遍历它看起来的每个元素。对于更长的列表(我的 xml 文件大约有 180,000 个字符),即使是简单的循环也似乎是不可能的。

XML(缩短,也许无法用一个小的 xml 文件重建我的问题):

<?xml version="1.0"?>
<suchia>
  <image id="1" value="useless">
    <sources>
      <src>a</src>
    </sources>
  </image>
  <image id="2" value="useless">
    <sources>
      <src>b</src>
    </sources>
  </image>
  <image id="3" value="useless">
    <sources>
      <src>c</src>
    </sources>
  </image>
  <image id="4" value="useless">
    <sources>
      <src>d</src>
    </sources>
  </image>
  <image id="5" value="useless">
    <sources>
      <src>e</src>
    </sources>
  </image>
  <image id="6" value="useless">
    <sources>
      <src>f</src>
    </sources>
  </image>
  <image id="7" value="useless">
    <sources>
      <src>g</src>
    </sources>
  </image>
  <image id="8" value="useful">
    <sources>
      <src>h</src>
    </sources>
  </image>
</suchia>

【问题讨论】:

    标签: php xml domdocument


    【解决方案1】:

    因为您在遍历活动的 DOMNodeList 时从父节点中删除节点,所以迭代器只能看到其他所有节点。正如 Ghost 建议的那样,使用 XPath 允许在删除节点的同时进行迭代。

    如果您在适当的位置设置preserveWhiteSpace(它需要在解析XML 之前设置,而formatOutput 仅适用于输出),那么额外的空格将不会出现在输出中。

    <?php
    
    $doc = new DOMDocument();
    $doc->preserveWhiteSpace = false;
    $doc->load('input.xml');
    
    $xpath = new DOMXPath($doc);
    $nodes = $xpath->query('image[@value="useless"]');
    
    printf("Removing %d useless images\n", $nodes->length);
    
    foreach ($nodes as $node) {
      $node->parentNode->removeChild($node);
    }
    
    $doc->formatOutput = true;
    $doc->save('output.xml');
    

    【讨论】: