我有一个只运行一次的 foreach 循环,它把我难住了。
1:我加载一个状态值数组(“请求”、“删除”或“已购买”)
2:然后我加载一个XML文件,需要遍历“code”节点并更新它们的状态,* 但是 * 如果新代码是“delete”,我想在移动到下一个节点之前删除它
XML结构是...
<content>
.... lots of stuff
<codes>
<code date="xxx" status="request">xxxxx</code>
.. repeat ...
</codes>
</content>
PHP代码是...
$newstatus = $_POST['updates'];
$file = '../apps/templates/' . $folder . '/layout.xml';
$xml2 = simplexml_load_file($file);
foreach($xml2->codes->code as $code) {
if($code['status'] == "delete") {
$dom = dom_import_simplexml($code);
$dom->parentNode->removeChild($dom);
}
}
$xml2->asXml($file);
我已经暂时删除了更新,所以我可以调试删除检查。
这一切工作,* 但 * 它只删除第一个删除,并留下所有其他删除,即使它是一个 foreach 循环?
2条答案
按热度按时间oprakyz71#
在同一迭代中多次删除是不稳定的。例如,如果删除第二个元素,第三个元素将变为第二个元素,依此类推。
可以通过先将要删除的元素存储到数组中来防止这种情况:
然后根据在迭代过程中保持稳定的数组删除元素:
您还可以将if条件放入XPath查询中,该查询直接返回数组(请参见the duplicate question中的示例)或使用
iterator_to_array()
。yeotifhr2#
SimpleXML节点列表是普通的引用数组,就像在向前迭代数组时删除项一样,数组位置指针可能会混淆,因为预期的下一项已经消失。
在SimpleXML中删除一堆子元素而不使用额外的数组的简单方法是反向迭代(=递减索引),以示例中的循环为例:
当然,如果您的其他处理需要向前迭代元素,那么使用数组是最好的。