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

2007/7/26 22:14:37


阅读全文(7918) | 回复(1) | 编辑 | 精华

通过javascript+DOM方式遍历XML节点(一) ******************************************版权作者:Qr                            **成文时间:2007/07/18 22:25:00           **原创站点:http://Qr.blogger.org.cn      **版权声明:转载请保留版权信息             ****************************************** 写在前面:曾经有位论坛上的网友问我,为什么不写些理论教程让大家学习和参考?我笑说工作太忙,抽不出时间。的确工作还是比较忙的,但只是其中一个理由。还有一个就是,网络上各种教程满天飞,自己也找不到一个好的切入点。前些日子,一个网友发贴子问遍历XML节点的问题(相关文章:一个遍历XML所有节点的递归代码[javascript+DOM方式]),我随手写了一段递归代码给对方。代码没什么过人之处,纯粹就事论事,针对那个特定的XML文档来写的,可是站长Collin还是给我加精了,惭愧。闲着没事,把相关代码继续完善一下,写成通用程序,也不辜负站长Collin给我前面那段代码加精。整理整理,形成了好几个版本的代码,看情况吧,也许会形成一个系列,也不是什么教程,贴上来看大家有没有不同的实现方法,与大家共勉吧! 简单说明:至今没想过js+DOM方式遍历XML节点有什么意义,为了体现遍历的效果,干脆就把遍历的结果以IE浏览XML的方式输出,当然只是纯粹进行格式化而已,因为涉及到MSXML版本的问题,序言和处理指令这一块没有考虑。 编程思路:自上而下、由外到内进行递归(正向),遇到子节点即继续遍历其下级节点,直到子节点为文本节点,然后后退,再次运用递归(反向),返回到其任意祖先级节点的相邻且含有子节点的兄弟节点,再递归(正向)遍历其下级节点,直到完成所有节点的遍历。 JAVASCRIPT实现: <script language="javascript"> /* ****************************************************** *代码:Qr http://Qr.blogger.org.cn                                      * *时间:2007/07/15 21:36:00                                                  * *功能:遍历XML的所有节点,仿IE浏览XML方式输出     * *类型:支持TEXT、CDATA、COMMENT、ELEMENT节点* ****************************************************** */ var xml = null , format = "" , fo = "&nbsp;&nbsp;&nbsp;&nbsp;" ;   function main(){     createXmlDom("parser.xml");     Recursion(xml.documentElement); }   function createXmlDom(xmlUrl){//这里大家可以自己处理一下,以适应不同浏览器     xml = new ActiveXObject("Msxml2.DOMDocument");     xml.async=false;     xml.load(xmlUrl); }   function Recursion(o) {     if(typeof(o)=="number")return;     if(o.nodeType==3 || o.nodeType==4 || o.nodeType==8){         switch(o.nodeType){             case 3://[TEXT型节点]             if(o.nextSibling || o.previousSibling)document.write("<br>"+format);             document.write(o.nodeValue);             //针对混合节点的末节点为文本节点的情况             if(!o.nextSibling && o.previousSibling){                 document.write("<br>"+format.substr(0,format.length-24));             }             break;               case 4://[CDATA型节点]             document.write("<br>"+format+"&lt;![CDATA["+o.nodeValue+"]]&gt;");//.replace("<","&lt;")             break;               case 8://[COMMENT型节点]             document.write("<br>"+format+"&lt;!--"+o.nodeValue+"--&gt;");//.replace("<","&lt;")             break;         }         if(o.nextSibling){             //#有同级兄弟元素节点#//             return arguments.callee(o.nextSibling);         }else{             //#返回上级相邻未解析节点#//             return arguments.callee(N2NP(o.parentNode));               //开始因为N2NP这个函数有问题,所以用try{}catch(e){}             //try{return arguments.callee(N2NP(o.parentNode));}catch(e){document.write ("<b><i>err:"+e+"</i></b>")};         }     }     if(!o.hasChildNodes()){//[空无素(ELEMENT)或仅含属性(ATTRIBUTE)]         if(o!=xml.documentElement)document.write("<br>");         if(o.nodeType==1)document.write(format+"&lt;"+o.nodeName);         if(o.attributes.length>0)attrparser(o);         document.write("/&gt;");         if(o.nextSibling){             //#有同级兄弟元素节点#//             return arguments.callee(o.nextSibling);         }else{             //针对混合节点的末节点为空元素的情况             if(o.previousSibling)document.write("<br>"+format.substr(0,format.length-24));               //#返回上级相邻未解析节点#//             return arguments.callee(N2NP(o.parentNode));               //开始因为N2NP这个函数有问题,所以用try{}catch(e){}             //try{return arguments.callee(N2NP(o.parentNode));}catch(e){document.write("<b>err:"+e+"</b>")};         }     }     if(o.hasChildNodes()){//有子节点,包括:TEXT、CDATA、COMMENT、ELEMENT         if(o.nodeName!=xml.documentElement.nodeName)document.write("<br>");         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;             return arguments.callee(o.firstChild);         }else{             if(o.nextSibling){//#有同级兄弟元素节点#//                 return arguments.callee(o.nextSibling);             }         }     } }   function N2NP(p){//alert(p.nodeName+":"+p.nodeValue)       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("<br>"+format+"&lt;/"+p.nodeName+"&gt;");         return p.nextSibling;//返回相邻节点     }else{           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("<br>"+format+"&lt;/"+p.nodeName+"&gt;");         if(p==xml.documentElement){return 0;}else{//如果不进行判断,函数将返回#document,导致错情             return arguments.callee(p.parentNode);//#返回上级相邻未解析元素节点#//         }     } }   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>   测试用XML文档:实际上这个文档是写后面两个版本的代码时,根据调试的情况,假设不同的情形,临时添加节点形成的,非常零乱,但是谁能保证某些客户不会提出这样的刁钻要求呢?!懒得重新设计所谓典型的XML文档,干脆就把这个文档贴出来当典型吧:-)后续文章还是继续延用这个测试文档。parser.xml:<?xml version="1.0" encoding="gb2312" ?> <root>    <!--COMMENT和CDATASection作为首个子节点在此出现没问题-->    <elements attribute="来个无文本节点试试,哈哈,没问题"/>    <elements>        <element attribute1="随便啦" attribute2="再多一个又如何">只有一行文本的节点</element>        <CDATASection>            <![CDATA[CDATASection和COMMENT相邻出错?※搞掂※]]>            <!--COMMENT和CDATASection相邻出错?※搞掂※-->        </CDATASection>        <COMMENT>            <!--针对以上相邻出错的问题将两个类型节点换个次序-->            <![CDATA[已经没有问题啦]]>        </COMMENT>        <CDATASection>            <![CDATA[CDATASection嵌套在一个空节点内]]>        </CDATASection>        <elem1>            <elem2>                既然已经解决,再加一个文本节点再这里试试!                <elem3>                    <![CDATA[CDATASection嵌套在多级空节点内出错?※搞掂※]]>                </elem3>                再再加一个文本节点再这里试试,没问题!            </elem2>        </elem1>        <![CDATA[CDATASection嵌套在两级以上节点均已调试通过]]>        <COMMENT>            <!--COMMENT嵌套在一级空节点中-->        </COMMENT>        <COMMENT>            <!--再加一个在此处-->            <comment>                <!--COMMENT嵌套在多级空节点中-->            </comment>        </COMMENT>        <!--COMMENT嵌套在两级以上节点均已调试通过-->        <!--COMMENT-->        <![CDATA[CDATASection]]>        <ELEMENT ATTRIBUTE="属性值">元素文本</ELEMENT>        <![CDATA[CDATASection混杂在节点中]]>        <中文节点>已经定义了encoding,没问题的</中文节点>        <!--COMMENT混杂在节点中-->        <ELEM>ELEM1</ELEM>        <ELEM>ELEM2</ELEM>        <ELEM>ELEM3</ELEM>        <EMPTY>            <empty>                <noValue/>            </empty>        </EMPTY>        <!--两级及以上空节点嵌套已通过-->        <ELEMENT>            <element 属性="attribute" 还是属性="ATTRIBUTE">两级节点嵌套,含文本</element>        </ELEMENT>        <ELEMENT>            <element>                <elem>多级节点嵌套,含文本</elem>                <!--COMMENT或CDATASection在末尾有问题!※搞掂※-->            </element>        </ELEMENT>        <interfusion>            <!---->            混合节点调试通过            <element>                element value                <empty/>            </element>            空元素调试通过            <!--COMMENT-->            <![CDATA[CDATASection]]>            Text            <ELEMENT>ELEMENT VALUE</ELEMENT>            TEXT            <![CDATA[COMMENT或CDATASection在末尾有问题!※搞掂※]]>        </interfusion>    </elements>    <!--COMMENT或CDATASection作为根节点的末子节点有问题!※搞掂※-->    <![CDATA[你会不会设计如此结构的XML文档,反正偶不会,看着就头痛□]]></root>   自我点评: 代码好坏不必说,我自己清楚。相信大家对DOM的性能应该是比较清楚的,它不能处理体积过于庞大的XML文档,这是一个现实。当然另一个实现是电脑的性能了,CPU性能越高、内存越大,处理能力就越强。 但以上自定义函数Recursion()所使用的javascript递归却更加严重影响了遍历和性能,所以,当如果XML文档体积过大的时候(当然这个体积远比不使用递归的小很多),就不能完整将XML节点遍历出来了。   下一篇将摒弃javascript的递归来实现XML节点的遍历。   相关文章:一个遍历XML所有节点的递归代码[javascript+DOM方式]   待续......

Qr

Posted by Qr on 2007/7/26 22:14:37

回复:通过javascript+DOM方式遍历XML节点(一)[原创]

2007/7/19 0:21:52


个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除

红色有点刺眼。。

徐涵(Han Xu)

Posted by 徐涵(Han Xu) on 2007/7/19 0:21:52

» 1 »

发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)
站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.078 second(s), page refreshed 144754413 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号