该死的DOMDocument!

九 24th, 2009

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

标签:
  1. veidy.lei
    九 25th, 200917:46

    哦,原来如此 :D

;) :| :x :twisted: :roll: :oops: :o :mrgreen: :lol: :idea: :evil: :cry: :arrow: :P :D :?: :? :) :( :!: 8O 8)

Spam Protection by WP-SpamFree