漂泊的云

javascript之XML DOM对象

javacript中对xml dom的支持,与其他任何特性一样面临着浏览器兼容问题。

一 IE中的XML DOM
1.微软通过ActiveX的MSXML库提供了支持,通过:
 var oXmlDom = new ActiveXObject("MSXML2.DOMDocument.5.0")
得到一个XML DOM对象,这是在IE6中的,如果你的IE是更老版本的,可以使用下面的函数得到,如果你没有安装MSXML,将不能得到:

 function createXMLDOM() {
        
            
var arrSignatures = ["MSXML2.DOMDocument.5.0""MSXML2.DOMDocument.4.0",
                                 
"MSXML2.DOMDocument.3.0""MSXML2.DOMDocument",
                                 
"Microsoft.XmlDom"];
                                 
            
for (var i=0; i < arrSignatures.length; i++) {
                
try {
                
                    
var oXmlDom = new ActiveXObject(arrSignatures[i]);
                    
                    
return oXmlDom;
                
                } 
catch (oError) {
                    
//ignore
                }
            }              
            
            
throw new Error("你的系统没有安装MSXML");           
        }     

当然,如果你使用prototype库,可以使用Try.these函数。

2.XML DOM对象可以通过load和loadXML方法载入xml文件或者字符串:
     oXmlDom.load("test.xml");
     oXmlDom.loadXML(
"<root></root>");
然后这个oXmlDom就可以使用所有的DOM对象方法,比如documentElement.tagName,参见:
 《javascript之DOM技术(一)》
 《javascript之dom技术(二)》

3.XML DOM默认是通过异步载入xml文件的,可以通过设置async值来选择是同步还是异步:
oXmlDom.async=true;


4.
IE的XML DOM拥有一个readyState值用来表示载入文件的状态:

0——准备载入
1——正在载入
2——载入完成
3——载入完成并可用,但有一部分数据也许不可用
4——完全载入,完全可用。

相应的有一个onreadystatechange事件,当状态改变时发生,我们可以通过监听此事件来判断XML DOM对象的可用性
oXmlDom.onreadystatechange = function () {
                
if (oXmlDom.readyState == 4) {
                    alert(
"load test.xml done!");
                    alert(
"Tag name of the root element is " + oXmlDom.documentElement.tagName);
                    alert(
"The root element has this many children: " + oXmlDom.documentElement.childNodes.length);

                }
            };

5.IE的XML DOM对象有一个xml属性,用来返回xml文件的字符串形式,比如
oXmlDom.async=false;
oXmlDom.load(
"test.xml");
alert(oXmlDom.xml);

alert出:<root><child/><child/></root>

6.IE,当载入的XML文件或者字符串解析错误时,将产生一个parseError对象,我们在下面的代码中演示此对象的属性:
            oXmlDom.async = false;
            oXmlDom.load(
"errors.xml");
            
            
//0表示没有错误
            if (oXmlDom.parseError != 0) {
                
var oError = oXmlDom.parseError;
            
                alert(
"An error occurred:\n错误代码: "
                      
+ oError.errorCode + "\n"
                      
+ "行数: " + oError.line + "\n"
                      
+ "列数: " + oError.linepos + "\n"
                      
+ "原因: " + oError.reason);
                      
            }


二.Mozilla的XML DOM对象
1.XML DOM对象的创建,符合DOM标准的,通过document.implementation.createDocument()方法。比如:
var oXmlDom=document.implementation.createDocument("","",null);

这三个参数分别是文档命名空间、文档元素的标签名以及一个文档类型对象(总为null),比如:
var oXmlDom=document.implementation.createDocument("http://www.rubyeye.net","root",null);

这段代码创建了一个<a0:root xmlns="http://www.rubyeye.net"/>的XML DOM对象


2.载入xml,Mozilla与IE不同的是只提供了一个load()方法用于载入xml文件,没有提供loadXML()方法用于载入XML字符串。同步载入XML文件的代码与IE相同:
oXmlDom.async=false;
oXmlDom.load(
"test.xml");

异步载入稍有不同,因为Mozilla并不支持readyState属性,并且没有onreadystatechange事件,它只有一个onload的事件,当载入完成时触发;或者说相当于IE的readyState属性等于4的状态。
oXmlDom.onload=function(){
alert(
"done");
}
oXmlDom.load(
"test.xml");

要将XML字符串解析为DOM对象,必须使用DOMParser对象:
var oParser=new DOMParser();
var oXmlDom=oParser.parseFromString(
"<root><child/></root>,"text/xml");

两个参数:要解析的XML字符串以及字符串的内容类型(只能为text/xml或者application/xml)。
不过我们可以实现自己的loadXML方法:
  Document.prototype.loadXML = function (sXml) {
    
            
var oParser = new DOMParser();
            
var oXmlDom = oParser.parseFromString(sXml, "text/xml");
         
            
//删除原文档内容
            while (this.firstChild) {
                
this.removeChild(this.firstChild);
            }
            
//导入新的文档内容
            for (var i=0; i < oXmlDom.childNodes.length; i++) {
                
var oNewNode = this.importNode(oXmlDom.childNodes[i], true);
                
this.appendChild(oNewNode);
            }
        
        };

3.Mozilla没有提供IE的xml属性来返回XML文档内容,只能通过使用XMLSerializer对象:
var oSerializer=new XMLSerializer();
var sXml=oSerializer.serializeToString(oXmlDom,"text/xml");
同样两个参数:XML DOM对象以及转化成的文档类型。

同样,我们也可以给Mozilla的XML DOM对象定义一个属性xml,通过defineGetter方法:
Node.prototype.__defineGetter__("xml",function(){
var oSerializer=new XMLSerializer();
var sXml=oSerializer.serializeToString(this,"text/xml");
});

以后就可以以IE的方式,oXmlDom.xml来获取XML文档内容。

4。错误处理,同样与IE不同,Mozilla当解析错误时会返回一段代码,以标签<prasereoor>包括其中的代码解释了错误发生的原因以及位置等信息,我们只有通过正则表达式解析此段代码,提取错误信息。
      var reError = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;
           
            
//返回代码的标签名为parsererror,表示错误发生
            if (oXmlDom.documentElement.tagName == "parsererror") {
                reError.test(oXmlDom.xml);
                alert(
"An error occurred:\n描述: "
                    
+ RegExp.$1 + "\n"
                    
+ "文件名: " + RegExp.$2 + "\n"
                    
+ "行数: " + RegExp.$3 + "\n"
                    
+ "列数: " + RegExp.$4 + "\n"
                    
+ "原因: " + RegExp.$5);
            }

三,提供一个跨浏览器的XML DOM对象解决方案,来自于《javascript高级程序设计》

function XmlDom() {
    
//通过对象/属性检测法,判断是IE来是Mozilla
    if (window.ActiveXObject) {
        
var arrSignatures = ["MSXML2.DOMDocument.5.0""MSXML2.DOMDocument.4.0",
                             
"MSXML2.DOMDocument.3.0""MSXML2.DOMDocument",
                             
"Microsoft.XmlDom"];
                         
        
for (var i=0; i < arrSignatures.length; i++) {
            
try {
        
                
var oXmlDom = new ActiveXObject(arrSignatures[i]);
            
                
return oXmlDom;
        
            } 
catch (oError) {
                
//ignore
            }
        }          

        
throw new Error("MSXML is not installed on your system."); 
           
    
//同上          
    } else if (document.implementation && document.implementation.createDocument) {
        
        
var oXmlDom = document.implementation.createDocument("","",null);

        
//创建Mozilla版本的parseError对象
        oXmlDom.parseError = {
            valueOf: 
function () { return this.errorCode; },
            toString: 
function () { return this.errorCode.toString() }
        };
        
        
//初始化parseError对象
        oXmlDom.__initError__();
                
        
        oXmlDom.addEventListener(
"load"function () {
            
this.__checkForErrors__();
            
this.__changeReadyState__(4);
        }, 
false);

        
return oXmlDom;        
        
    } 
else {
        
throw new Error("Your browser doesn't support an XML DOM object.");
    }
}

//此处用到了该书中一个浏览器系统检测js文件,如果是Mozilla
if (isMoz) {

    Document.prototype.readyState 
= 0;
    Document.prototype.onreadystatechange 
= null;

    
    Document.prototype.__changeReadyState__ 
= function (iReadyState) {
        
this.readyState = iReadyState;

        
if (typeof this.onreadystatechange == "function") {
            
this.onreadystatechange();
        }
    };
    
//初始化parseError对象
    Document.prototype.__initError__ = function () {
        
this.parseError.errorCode = 0;
        
this.parseError.filepos = -1;
        
this.parseError.line = -1;
        
this.parseError.linepos = -1;
        
this.parseError.reason = null;
        
this.parseError.srcText = null;
        
this.parseError.url = null;
    };
    
    Document.prototype.__checkForErrors__ 
= function () {

        
if (this.documentElement.tagName == "parsererror") {

            
var reError = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;

            reError.test(
this.xml);
            
            
this.parseError.errorCode = -999999;
            
this.parseError.reason = RegExp.$1;
            
this.parseError.url = RegExp.$2;
            
this.parseError.line = parseInt(RegExp.$3);
            
this.parseError.linepos = parseInt(RegExp.$4);
            
this.parseError.srcText = RegExp.$5;
        }
    };
    
     
//定义Mozilla的loadXML方法   
    Document.prototype.loadXML = function (sXml) {
    
        
this.__initError__();
    
        
this.__changeReadyState__(1);
    
        
var oParser = new DOMParser();
        
var oXmlDom = oParser.parseFromString(sXml, "text/xml");
 
        
while (this.firstChild) {
            
this.removeChild(this.firstChild);
        }

        
for (var i=0; i < oXmlDom.childNodes.length; i++) {
            
var oNewNode = this.importNode(oXmlDom.childNodes[i], true);
            
this.appendChild(oNewNode);
        }
        
        
//载入后检查错误
        this.__checkForErrors__();
        
        
//没有问题,设置readyState属性为4
        this.__changeReadyState__(4);

    };
    
    Document.prototype.__load__ 
= Document.prototype.load;

    Document.prototype.load 
= function (sURL) {
        
this.__initError__();
        
this.__changeReadyState__(1);
        
this.__load__(sURL);
    };
    
    Node.prototype.__defineGetter__(
"xml"function () {
        
var oSerializer = new XMLSerializer();
        
return oSerializer.serializeToString(this"text/xml");
    });

}

posted on 2009-04-30 15:46 王雪峰 阅读(48) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 

My Links

Blog Stats

常用链接

留言簿(2)

随笔分类

随笔档案

文章档案

搜索

最新评论