在遍历SimpleXMLElement中的所有元素之前,foreach结束

时间:2016-05-27 12:24:57

标签: php foreach simplexml

我遍历一个大的xml文档,我需要删除一些节点。不幸的是,我的foreach在第一次移除后断了那怎么样?

$ids = [1, 2];

$data=<<<DNS_TXT
<feed xmlns:g="http://base.google.com/ns/1.0">
<entry><g:id>1</g:id><description>Desc 1</description></entry>
<entry><g:id>2</g:id><description>Desc 2</description></entry>
<entry><g:id>3</g:id><description>Desc 3</description></entry>
<entry><g:id>4</g:id><description>Desc 4</description></entry>
<entry><g:id>5</g:id><description>Desc 5</description></entry>
</feed>
DNS_TXT;

$doc = new SimpleXMLElement($data);

$i = 0;

foreach($doc->entry as $entry)
{
    $i++;

    $dom = $entry->children('http://base.google.com/ns/1.0');

    if(!in_array($dom->id, $ids)) {
        $dom = dom_import_simplexml($entry);
        $dom->parentNode->removeChild($dom);
    }
}

echo $i;

结果是3而不是5 ......

当然,我可以这样做:

/.../

$toRemove = array();
foreach($doc->entry as $entry)
{
    $dom = $entry->children('http://base.google.com/ns/1.0');

    if(!in_array($dom->id, $ids)) {
        $dom = dom_import_simplexml($entry);
        $toRemove[] = $dom;
    }
}

foreach ($toRemove as $dom) {
    $dom->parentNode->removeChild($dom);
}

/.../

但是为什么在第一种情况下foreach会结束?

1 个答案:

答案 0 :(得分:0)

以这种方式从最大索引循环到最低索引更好。所以它有效:

$entries = $doc->entry;
for($i = count($entries)-1; $i >= 0; $i--)
{
    $entry = $entries[$i];
    $dom = $entry->children('http://base.google.com/ns/1.0');
    if(!in_array($dom->id, $ids)) {
        unset($doc->entry[$i]);
     }