javascript之XML DOM对象

转自:http://www.duduwolf.com/wiki/2007/310.html

 

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 " );
    });

}

你可能感兴趣的:(JavaScript,xml,正则表达式,IE,prototype)