以文本方式查看主题

-  W3CHINA.ORG讨论区 - 语义网·描述逻辑·本体·RDF·OWL  (http://bbs.xml.org.cn/index.asp)
--  『 XML基础 』  (http://bbs.xml.org.cn/list.asp?boardid=1)
----  [原创]通过javascript+DOM方式遍历XML节点(四)  (http://bbs.xml.org.cn/dispbbs.asp?boardid=1&rootid=&id=50587)


--  作者:Qr
--  发布时间:7/27/2007 1:53:00 PM

--  [原创]通过javascript+DOM方式遍历XML节点(四)
通过javascript+DOM方式遍历XML节点(四)

*****************************************
*版权作者:Qr                            
*成文时间:2007/07/27 13:30:00           
*原创站点:http://Qr.blogger.org.cn      
*版权声明:转载请保留版权信息
*****************************************

代码说明:
本代码仍沿用Recursion的思路,以for(无限)循环重写代码,性能上比用javascript的递归更胜一筹,但相对前两篇来讲,性能上改进不大,只是代码更简洁,结构更清晰了。

JAVASCRIPT实现:

<script language="javascript">
/*
***************************************************
*代码:Qr http://Qr.blogger.org.cn
*时间:2007/07/15 22:50:00
*功能:遍历XML的所有节点、属性,仿IE浏览XML方式输出
*类型:支持TEXT、CDATA、COMMENT、ELEMENT节点
***************************************************
*/
var xml = null,format = "",fo = "";

function main(){
    createXmlDom("parser.xml");
    xmlparser(xml.documentElement);
}

function createXmlDom(xmlUrl){
    xml = new ActiveXObject("Msxml2.DOMDocument");
    xml.async=false;
    xml.load(xmlUrl);
}

function xmlparser(o) {
for(;;){
    if(o.nodeType==3 || o.nodeType==4 || o.nodeType==8){//o.hasChildNodes()==false
        switch(o.nodeType){
            case 3://[TEXT型节点]
            if(o.nextSibling || o.previousSibling)document.write("
"+format)
            document.write(o.nodeValue);
            if(!o.nextSibling && o.previousSibling){//针对混合节点的末节点为文本节点的情况
                document.write("
"+format.substr(0,format.length-24));
            }
            break;
            case 4://[CDATA型节点]
            document.write("
"+format+"&lt;![CDATA["+o.nodeValue+"]]&gt;");
            break;
            case 8://[COMMENT型节点]
            document.write("
"+format+"&lt;!--"+o.nodeValue+"--&gt;");
            break;
        }
        if(o.nextSibling){//#有同级兄弟元素节点#//
            o=o.nextSibling;
            continue;
        }else{//#返回上级相邻未解析节点#//
            o=N2PN(o.parentNode);
            if(o==xml.documentElement)break;//避免死循环
            continue;
        }
    }

    if(!o.hasChildNodes()){//[空无素(ELEMENT)或仅含属性(ATTRIBUTE)]
        if(o!=xml.documentElement)document.write("
");
        if(o.nodeType==1)document.write(format+"&lt;"+o.nodeName);
        if(o.attributes.length>0)attrparser(o);
        document.write("/&gt;");
        if(o.nextSibling){//#有同级兄弟元素节点#//
            o=o.nextSibling;
            continue;
        }else{//#返回上级相邻未解析节点#//
            if(o.previousSibling)//针对混合节点的末节点为空元素的情况
                document.write("
"+format.substr(0,format.length-24));
            o=N2PN(o.parentNode);
            if(o==xml.documentElement)break;//避免死循环
            continue;
        }
    }
    if(o.hasChildNodes()){//有子节点,包括:TEXT、CDATA、COMMENT、ELEMENT
        if(o!=xml.documentElement)document.write("
");
        if(o.nodeType==1)document.write(format+"&lt;"+o.nodeName);
        if(o.attributes.length>0)attrparser(o);
        document.write("&gt;");
        if(o.hasChildNodes()){
            format += fo;
            o=o.firstChild;//#有下级元素节点#//
            continue;
        }else{
            if(o.nextSibling){//#有同级兄弟元素节点#//
                o=o.nextSibling;
                continue;
            }
        }
    }
}
}
function N2PN(p){
    if(p.nextSibling){
        format = format.substr(0,format.length-24);
        //输出关闭节点名
        if(p.nodeType==1 && p.firstChild.nodeType==3)
            document.write("&lt;/"+p.nodeName+"&gt;");
        if(p.nodeType==1 && p.firstChild.nodeType!=3)
            document.write("
"+format+"&lt;/"+p.nodeName+"&gt;");
        p = p.nextSibling;
    }else{
        for(;;){
            format = format.substr(0,format.length-24);
            //输出关闭节点名
            if(p.parentNode && p.firstChild.nodeType==3)
                document.write("&lt;/"+p.nodeName+"&gt;");
            if(p.parentNode && p.firstChild.nodeType!=3)
                document.write("
"+format+"&lt;/"+p.nodeName+"&gt;");
            if(p==xml.documentElement)break;
            p=p.parentNode;//如果没有上面一行,将遍历到#document
            if(p.nextSibling){
                format = format.substr(0,format.length-24);
                document.write("
"+format+"&lt;/"+p.nodeName+"&gt;");
                p = p.nextSibling;
                break;
            }
            continue;
        }
    }
    return p;
}

function attrparser(o){
    if(o.attributes){
        var attr = o.attributes;
        for(i=0;i<attr.length;i++){
            document.write(" "+attr[i].nodeName+'="'+attr[i].firstChild.nodeValue+'"');
        }
    }
}

main();
</script>

写在最后:
文章写到这里,与其说是教程,不如说是学习笔记。工科出身,文笔很差,见笑了。

基本上就这样了,只是到目前,如此这般(js+DOM)遍历XML节点有什么作用和意义我还是不明白,但这次写学习笔记,我更清楚的了解了DOM的运行机制和处理XML的方法,足够了!

现在都提倡面向对象的程序设计,javascript也不例外,我按照xmlparser的思路,也对代码进行了重构,只是没有一款好用的调试软件,遇到了一个问题至今未能查决,也不知道性能如何,看情况再说吧,希望代码能顺利通过调试,这样第5篇笔记就有机会让大家拍砖头了:-)

javascript并非我的强项,只是写WEB系统要用到,这才临时抱佛脚,各位如有更好的遍历方法,请务必共享呵!另外,似乎javascript中的for...in语句也适合写这个程序,只是偶不太熟悉for...in语句来处理object,哪位熟悉的,写点简单代码给偶参考参考。

相关文章:
通过javascript+DOM方式遍历XML节点(三)

通过javascript+DOM方式遍历XML节点(二)

通过javascript+DOM方式遍历XML节点(一)


[此贴子已经被作者于2007-7-28 8:12:14编辑过]

--  作者:roverhuang
--  发布时间:7/28/2007

--  
看着有些糊涂
--  作者:happy-wind
--  发布时间:8/4/2007 5:26:00 PM

--  
真的好晕啊,不知道这个是做什么用的。
顺便提个问题:我知道xml文档的结构,然后知道节点名,怎么取到节点的内容呢?
用的是asp中的domDocument
--  作者:VictorWoo
--  发布时间:8/7/2007 9:49:00 PM

--  
Qr大的文章排版都很认真,赞。
--  作者:yanhongzhao
--  发布时间:9/22/2007 8:20:00 PM

--  
for...in 可以用来遍历object里的所有属性,不过据说for循环的效率比较底的。。。真的比递归高么? 个人觉得还是递归的代码可读性比较好。。
--  作者:sunny0311
--  发布时间:9/24/2007 11:07:00 AM

--  
文章写的相当不错啊!顶起来
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
78.125ms