该死的DOMDocument!
PHP处理XML类文档主要有两个模块,一般简单点用SimpleXML,不过他只能作遍历、取值、取属性等操作,而不能进行删除修改节点的操作。使用libxml的DOMDocument功能比较强大,不过也比较麻烦。今天就遇见一问题,折腾很久~
有XML格式如下:
<foo xmlns="test"> <bar attr='a'></bar> <bar attr='b'></bar> <bar attr='c'></bar> </foo>
开始尝试解析
<?php $dom = new DOMDocument; $dom->loadXML($xmls);//xmls变量为以上XML的字符串内容 $messages = $dom->getElementsByTagName('bar'); foreach($messages as $k=>$message){ if(!is_object($message) || ($message->getAttribute('attr') == 'a')){ continue;//属性attr 为a的保留 } $message->parentNode->removeChild($message); } echo $dom->saveXML();
//原以为删除了attr属性不为a的bar节点,可是却混淆了!后来尝试了replaceChild等,也不是太理想,而且还麻烦
//最后在PHP官方发现也有人提了此问题,并且人家找到办法绕过了此BUG
You can’t remove DOMNodes from a DOMNodeList as you’re iterating over them in a foreach loop. For example… 意思是说在遍历节点的时候进行删除操作会得到意想不到的结果,因此将要删除的结点暂存起来,最后再来删除
修正以上代码:
<?php $dom = new DOMDocument; $dom->loadXML($xmls);//xmls变量为以上XML的字符串内容 $messages = $dom->getElementsByTagName('bar'); $deletemessages = array(); foreach($messages as $k=>$message){ if(!is_object($message) || ($message->getAttribute('attr') == 'a')){ continue;//属性attr 为a的保留 } $deletemessages[] = $message; } //删除 foreach($deletemessages as $k=>$v){ $v->parentNode->removeChild($v); } echo $dom->saveXML();
好了!这样就正常了……
参考PHP文档:http://us3.php.net/manual/en/domnode.removechild.php
哦,原来如此