关于Ajax的一揽子工程(2)

关于Ajax的一揽子工程
--XML支持

  随着XML的日益流行,对XML的支持成为每一门高级语言都需要面对的问题。虽然JSON能在Javascript中以更高的效率和更少的资源表达数据,但XML这种世界语作为Javascript与其它语言(包括运行在服务端的语言)优秀解决方案仍被大量使用。而且在AJAX应用中,XML通常是服务端对客户端异步请求的响应形式。


如何支持XML?


跟以前一样,IE和Firefox有不同的实现方式:

var xmlDom = new ActiveXObject(“Microsoft.XmlDom”);

MSXML现在已经有五个不同的版本,所以工厂模式同样可用于XMLDOM的创建:
 

       function createDocument() {
            
var aVersions = 
"MSXML2.DOMDocument.5.0",
                 
"MSXML2.DOMDocument.4.0",
"MSXML2.DOMDocument.3.0",
                 
"MSXML2.DOMDocument","Microsoft.XmlDom"];
 
            
for (var i = 0; i < aVersions.length; i++) {
                
try {
                    
var oXmlDom = new ActiveXObject(aVersions[i]);
                    
return oXmlDom;
                } 
catch (oError) {
                    
//Do nothing
                } 
            }
            
throw new Error("MSXML is not installed.");
        }
        
var oXmlDom = createDocument();

创建XMLDOM之后,就可以使用它了:
oXmlDom.load("books.xml");或 oXmlDom.loadXML(“<root></root>”);
XMLDOM默认使用异步的方式载入,如要进行同步加载,则使用oXmlDom.async = false;来设置。
 既然XMLDOM可以以异步加载,所以我们又会见到类似这样的代码:

         oXmlDom.onreadystatechange = function () {
            
if (oXmlDom.readyState == 4) {
            
                
var oRoot = oXmlDom.documentElement;
                
var oFirstBook = oRoot.firstChild;
                
                alert(oFirstBook.text);
            }
        };

 和以前一样,4代表DOM完全载入。如果在载入数据时出现错语,则可以通过以下代码来处理:

         oXmlDom.onreadystatechange = function () {
            
if (oXmlDom.readyState == 4) {
                
if (oXmlDom.parseError.errorCode == 0) {
                    
var cElements = oXmlDom.getElementsByTagName("*");
                    
                    alert(cElements.length 
+ " elements in the document.");
                    
                } 
else {
                    alert(
"An Error Occurred: " + oXmlDom.parseError.reason);
                }
            }
        };

 parseError对象有以下几个属性:
1. errorCode  -- 错误代码
2. line  -- 错误所在行
3. linepos -- 错误所在位置
4. reason  -- 对错误的一些说明
XMLDOM和HTMLDOM行为基本相似,除了HTML中的document换成documentElement。所以也可以使用firstChild,lastChild,childNodes等API。
 firefox则使用document.implementation来创建XMLDOM:

     var oXmlDom = document.implementation.createDocument(""""null);
              
        oXmlDom.load(
"books.xml");
        oXmlDom.onload 
= function () {
            
//Do something when the document is fully loaded.
        };


 其中第一个参数为命名空间,第二个为标签名,第三个始终为null。在FireFox中,XMLDOM只能载入处部XML文件,而使用DOMParser对象来专门负责XML字符串的解析:

        var sXml = 
"<root><person><name>Jeremy McPeak</name></person></root>";
        
var oParser = new DOMParser();


        var oXmlDom = oParser.parseFromString(sXml,"text/xml");
 对载入XML内容后,和IE不同的是,FireFox中的DOM会触发load事件(参见上面代码)。
 如果加载发生错误,FireFox会返回一个XML格式的代码,我们需要对它进行分析,才能得到和IE类似的信息:
 

       var sXml = 
"<root><person><name>Jeremy McPeak</name></root>";
        
var oParser = new DOMParser();
        
var oXmlDom = oParser.parseFromString(sXml, "text/xml");
        
        
if (oXmlDom.firstChild.tagName != "parsererror") {
            
//No error occurred. Do something here.
        } else {
            
var oXmlSerializer = new XMLSerializer();
            
var sXmlError =
 oXmlSerializer.serializeToString(oXmlDom);
            
var reError = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;
            reError.test(sXmlError);            
            
var str = "An error occurred!!\n" +
                
"Description: " + RegExp.$1 + "\n" +
                
"File: " + RegExp.$2 + "\n" +
                
"Line: " + RegExp.$3 + "\n" +
                
"Line Position: " + RegExp.$4 + "\n" +
                
"Source Code: " + RegExp.$5;
            alert(str);
        }

 如果需要反过来把XMLDOM转成字符串,IE提供一个很方便的属性来达到目的:
 var sXml = oXmlDom.xml;
 而在FireFox下要达到这一目的,要麻烦得多:
        function serializeXml(oNode) {
            var oSerializer = new XMLSerializer();
            return oSerializer.serializeToString(oNode);
        }
对XPath的支持
 IE对XPath的支持也是比较简便的,IE中的XML DOM对象的每个节点都可以直接使用selectNodes()和selectSingleNode()方法,这两个方法都接收一个XPath表达式作为参数。
 而FireFox对XPath的支持要难于使用得多,你需要使用到XPathEvaluator和XPathResult对象,并使用XPathEvaluator的evaluate()方法计算XPath表达式,evaluate()接收五个参数:XPath表达式,上下文节点,命名空间解释程序,返回类型:

    var sXPath = "na:book/pub:name";
    
var oEvaluator = new XPathEvaluator();
    
var oResult =
   oEvaluator.evaluate(sXPath,oXmlDom.documentElement,
nsResolver, XPathResult.ORDERED_NODE_ITERATOR_TYPE, 
null);

    
var aNodes = new Array;

    
if (oResult != null) {
        
var oElement;
        
while (oElement = oResult.iterateNext()) {
            aNodes.push(oElement);
        }
    }

    
    
function nsResolver(sPrefix) {
        
switch (sPrefix) {
            
case "na":
                
return "http://site1.com";
                
break;
            
case "pub":
                
return "http://site2.com";
                
break;
            
default:
                
return null;
                
break;
        }
    } 


 很多情况下,XML并没有命名空间,所以对于nsResolver参数可以传入null。
对XSLT的支持
 在IE中同样可以清晰简单的使用XSLT:
oXmlDom.load("books.xml");
oXslDom.load("books.xsl");
ar sResults =
  oXmlDom.documentElement.firstChild.transformNode(oXslDom);
 任何一个XMLDOM节点都可以调用transformNode(oXslDom)获得转换后的结果。
 在FireFox中使用XSLT的方法如下:
  oXmlDom.load("books.xml");
  oXslDom.load("books.xsl");
       
  var oXsltProcessor = new XSLTProcessor();
  oXsltProcessor.importStylesheet(oXslDom);
       
  var oNewDom = oXsltProcessor.transformToDocument(oXmlDom);
小结
 本文简单讨论了在Javascript中如何操作XML。随着越来越火的RSS等XML应用,基于Javascript开发支持XML的程序将成为WEB程序员越来越重要的技能。
(未完待续……)

posted @ 2006-12-19 16:46  Think  阅读(3250)  评论(2编辑  收藏  举报