posts - 297,  comments - 1618,  trackbacks - 0
说明:参见《JavaScript高级程序设计》第15章"JavaScript中的XML "。
一.             浏览器中的XML DOM支持

 目前只有两种浏览器支持客户端的XML处理,分别是IEMozilla

1. IE中的XML DOM支持

在为IE添加XML支持时,微软在JavaScript之外另寻了个方案:基于ActiveXMSXML库。

1) DOM创建

对每个新版本的MSXML,都会创建出不同的XML DOM对象,而它们各自的名称也不相同,MSXML最新的版本是5.0。它存在如下几种XML DOM实现:

 i)Microsoft XmlDom(最原始的);

ii)MSXML2.DOMDocument

iii)MSXML2.DOMDocument3.0

iv)MSXML2.DOMDocument4.0

v)MSXML2.DOMDocument5.0

为确保使用了正确的XML DOM版本,也为避免任何其他错误,我们可以创建一个函数来测试每个XML DOM对象字符串,出现错误即捕获:

function createXMLDOM() {
    var arrSignatures = {"MSXML2.DOMDocument5.0", "MSXML2.DOMDocument4.0", "MSXML2.DOMDocument3.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("SXML is not installed on your system.";
}

 

注意:这段在IE中创建XML DOM的代码在其他浏览器会出现错误。因此,必须在其之前先进行浏览器检测。

2) 载入XML

有了可用的XML DOM对象后,就可以载入XML了,微软的XML DOM提供两种方法,.即:loadXML()load()

loadXML()方法可直接向XML DOM输入XML字符串,eg.

var oXmlDom = createXMLDOM();

oXmlDom.loadXML(“<root><child/></root>”);

load()方法用于从服务器上载入XML文件,不过load()方法只可以载入与包含JavaScript的页面存储于同一个服务器上的文件,即:不可以通过其他人的服务器载入XML文件。

还有两种载入文件的模式:同步与异步。以同步模式载入时,JavaScript代码会等待文件完全载入后才继续执行代码;而以一步模式载入时,不会等待,可以使用事件处理函数来判断文件是否完全载入了。默认情况下,为异步载入。要进行同步载入,需设置async特性为false,如下:

oXmlDom. async = false;

然后使用load()方法,并给出要载入的文件名:

oXmlDom.load(“test.xml”);

异步载入文件时,要使用readyState特性和onreadystatechange事件处理函数:

readyState特性有五种可能的值:

     0——DOM尚未初始化任何信息;

     1——DOM尚未载入数据;

     2——DOM完成了数据载入;

     3——DOM已经可用,不过某些部分可能还不能用;

     4——DOM已经完全被载入,可以使用了。

一旦readyState的值发生变化,就会触发onreadystatechange事件。使用该函数,就可以在DOM完全载入时,发出通知:

oXmlDom.onreadystatechange = function() {

    if (oXmlDom.readyState == 4) {

       alert(“已完全载入!”);

}

}

必须在调用load()方法前分配好onreadystatechange事件处理函数,如下所示:

oXmlDom.onreadystatechange = function() {

    if (oXmlDom.readyState == 4) {

       alert(“已完全载入!”);

}

}

oXmlDom.load(“test.xml”);

注意:事件处理函数代码使用oXmlDom而不是this关键字,这是JavaScriptActiveX对象的特殊之处。

load()方法可以接受部分的、相对的或者完整的XML文件路径。eg.

oXmlDom.load(“test.xml”);

oXmlDom.load(“../test.xml”);

oXmlDom.load(“http://www.amigo.com/test.xml”)

3) 获取XML

XML载入到DOM中后,还需将XML取出来,微软为每个节点(包括文档节点)都添加了一个xml特性,使得这个操作十分方便,它会将XML表现形式作为字符串返回。所以获取载入后的XML十分简单:

oXmlDom.load(“test.xml”);

alert(oXmlDom.xml);

也可以获取某个特定节点的XML:

var oNode = oXmlDom.documentElements.childNodes[1];

alert(oNode.xml);

xml特性是只读的,如果尝试直接对其进行赋值会产生错误。

4) 解释错误

微软的XML DOMparseError的特性包含了关于解析XML代码时所遇到的问题的所有信息。

parseError特性实际上是包含以下特性的对象:

     errorCode——表示所发生的错误类型的数字代号(没有错误时为0);

     filePos——错误发生在文件中的位置;

     line——遇到错误的行号;

     linepos——在遇到错误的那一行上的字符的位置;

     reason——对错误的一个解释;

     srcText——造成错误的代码;

      url——造成错误的文件的URL(如果可用)。

可直接对parseError自身取值,它会返回errorCode的值。Eg.

if (oXmlDom. parseError != 0) {

    //…

}

可以使用parseError对象来创建自己的错误对话框:

if (oXmlDom. parseError != 0) {

    var oError = oXmlDom. parseError;

    alert(“错误发生!\nerrorCode: ” + oError. errorCode

+ “\nLine:” + oError.line + “\nLine Pos: ” + oError. linepos

+ “\nReason: ” + oError. reason);

}

 

2. Mozilla中的XML DOM支持

 略。

 

3. 通用接口

   有了跨浏览器的解决方案时,使用XML DOM进行开发才真正有用。IEMozilla的实现之间有着很明显的区别,开发时会造成很严重的问题。需要找出一套能在两种浏览器中都可以使用XML DOM的通用方法。

1) 修改DOM创建

最简单方法是创建伪类,使其通过var oXmlDom = new XmlDom ();来创建XML DOM。在其构造函数中进行浏览器检测,eg.

function XmlDom() {

       if (window.ActiveObject) {

       //IE-specific code

} else if (document.implementation && document.implementation.createDocument) {

       //DOM-specific code

} else {

       throw new Error(“你的浏览器不支持XML DOM对象”);

}

}

2) IE分支

将上节的IE中创建DOM的代码转贴到上述代码中。

3) Mozilla分支

略。

4) 完整代码

完整代码如下所示:

 

function XmlDom() {
if (window.ActiveXObjext) {
var arrSignatures = {"MSXML2.DOMDocument5.0", "MSXML2.DOMDocument4.0", "MSXML2.DOMDocument3.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);
       oXmlDom.parseError 
= {
              
valueOf: function() {return this.errorCode;},
        toString: function() {return this.errorCode.toString()};
}
oXmlDom.addEventListener("load", function()) {
       this.__checkForErrors__();
       this.__changeReadyState__(4);
}, false);
return oXmlDom;
} else {
       throw new Error("你的浏览器不支持XML DOM对象");
}
}

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

Document.prototype.__initError__ 
= function() {
     this.parseError.errorCode 
= 0;
     
this.parseError..filepos = -1;
     
this.parseError..line = -1;
     
this.parseError..lineppos = -1;
     
this.parseError..reason = null;
     
this.parseError.srcText = null;
     
this.parseError..url = null;
};

Document.prototype.__checkForErrors__ 
= function() {
     if (this.documentElement.tagName 
== “parseError”) {
       var reError 
/>([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;
       reError.text(this.xml);
       this.parseError..errorCode = -999999;
       this.parseError..reason = RegExp.$1p;
       this.parseError..url = this.parseError..$2;
       this.parseError..line = pauseInt(RegExp.$3);
       this.parseError..linepos = parseInt(RegExp.$4);
       this.parseError..srcText = RegExp.$5;
}
};

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 = 0; I 
< oXmlDom.childNodes.length; i++) {
       var oNewNode 
= this.importNode(oXmlDom.childNodes[i], true);
       this.appendChild(oNewNode);
}

this.__checkForErrors__();
this.__changeReadyState__(4);
};

Document.prototype.__load__ 
= Document.prototype.load;
Document.prototype.load = function(sURL) {
     this.__initError__();
     this.__changeReadyState__(1);
     this.__load__(sURL)L
};

Node.prototype.__defineGetter__("xml", function()) {
     var oSerializer 
= new XMLSerializer();
     return oSerializer.serializeToString(this. "text/xml");
});
}

 

二.             浏览器对XPath的支持

 XPath是一种可以在XML代码中定位数据的方式。

1.       简介

每个XPath表达式有两部分:一个上下文节点和一个节点模式。前者提供了节点模式起始的位置。节点模式是由一个或多个节点选择器组成的字符串。

Eg.

<?xml version=”1.0”?>
    
<employees>
           
<employee title=”软件工程师”>
                  
<name>阿蜜果</name>
           
</employee>
           
<employee title=”测试工程师”>
                  
<name>amigo</name>
           
</employee>
       
</employees>

XPath表达式employee/name,匹配的是<name>阿蜜果</name><name>amigo</name>,若要选择<employee/>元素的第一个<name/>元素,可用employee[position() == 1]/name。在XPath中,方框记号用于为某个节点提供更加确切的信息,position()用于返回元素在父节点下的位置。

 除了未知和名称外,还可以使用不同的方法来匹配元素,若要选择所有title特性为“软件工程师”的<employee/>元素,对应的表达式为:

 employee[@title = “软件工程师”]

 其中@attribute的缩写。

2. IEXPath的支持

每个节点的都有两个可用于获取匹配XPath模式的节点的方法:

selectNodes():用于匹配某个模式的节点的集合;

selectSingleNode():用于返回匹配给定模式的第一个节点。

 eg. varlstNodes = oXmlDom.documentElement.selectNodes(“employee/name”);

 返回包含所有匹配给定模式的节点的NodeList,可以通过如下方式迭代所有的元素:

 for (var i = 0; i < varlstNodes.length; i++) {

    alert(varlstNodes[i]);

}

如果没有匹配的节点,返回的NodeListlength0

3. MozillaXPath的支持

略。

三.             浏览器的XSLT支持

 XSLT:可扩展样式表语言转换,可由一些模板组成。模板属于XML的某个特性的一部分(使用XPath指定),它可以决定为这一部分输出什么文本。通过为不同的元素和条件定义模板,XSLT样式表变成了一种XML的解析器。

1. IEXSLT的支持

MSXML3.0开始,IE就完全支持XSLT1.0了。对于在IE6.0以前的版本,还需要安装新版的MSXML

最简单的XSLT转换的方法是:分别将XML源代码和XSLT文件载入各自的DOM,并使用特有的transformNode方法:

 oXmlDom.load(“employees.xml”);

 oXslDom.load(“employees.xslt”);

 var sResult = oXmlDom. transformNode(oXslDom);

 其实,也可以不从文档层次转换,而从节点层次转换,如果从某个节点调用transformNode(),则从这个点开始转换,但是XSLT能访问包含这个节点的整个XML文档。

 IE中使用XSLT的另外一个比较复杂的方法是,使用XSL模板和处理器。这种方法必须使用MSXML的其他几个ActiveX控件。首先XSLT文件必须载入到一个自由线程DOM文档中,代码如下:

 var oXslDom = new ActiveXObject(“MSXML2.FreeThreadedDOMDocumnet”);

 oXslDom.asyn = false;

 oXslDom.load(“employees.xml”);

 自由线程DOM文档建立并加载好后,必须将其分配到XSL模板中,这是另一个ActiveX对象:

 var oTemplate = new ActiveXObject(“:MSXML2.XSLTemplate”);

 oTemplate.stylesheet = oXslDom;

 然后,可以用XSL模板来创建一个XSL处理器:

 var oProcessor = oTemplate.createProcessor();

 创建处理器后,将input特性设置为要进行转换的XML DOM节点,然后调用transform()方法:

 oProcessor.input = oXmlDom;

 oProcessor.transform();

 然后将从output特性中访问结果字符串:

 var sResult = oProcessor.output;

 这个复杂的方法模仿了transformNode()的功能,但该方法允许更多地控制XSLT

 注意:MSXML只支持XSLT1.0MSXML的开发自从转到.NET Framework后就停止了。可能在未来的某天,JavaScript会允许访问XMLXSL.NET对象。

2. MozillaXSLT的支持

略。

posted on 2007-08-13 13:19 阿蜜果 阅读(2804) 评论(6)  编辑  收藏 所属分类: Javascript


FeedBack:
# re: JavaScript学习笔记——JavaScript中的XML
2007-08-13 15:08 | 杨爱友
抢到了。
好快的速度,上午还问了下‘其他章节呢’,中午就下好了,而且写这么多。仔细研读...  回复  更多评论
  
# re: JavaScript学习笔记——JavaScript中的XML[未登录]
2007-08-13 15:12 | 阿蜜果
@ 杨爱友
嘻嘻,是昨晚写好的
今天中午上传了一下
:)
  回复  更多评论
  
# re: JavaScript学习笔记——JavaScript中的XML
2007-08-27 10:43 | Candlelighting
有没有兼容fireFox的,对xml的操作的例子
在下面代码中第一个if语句中的alert(xmldoc.xml);在用fireFox浏览的时候会跳出undefined...试过好几个例子了,不知道问题出在哪里.
var url = "employees.xml";
if(document.implementation&&document.implementation.createDocument) {
var xmldoc = document.implementation.createDocument("", "", null);
xmldoc.load(url);
alert(xmldoc.xml);
}
else if(window.ActiveXObject) {
var xmldoc = new ActiveXObject("Microsoft.XMLDOM");
xmldoc.onreadystatechange = function() {
if(xmldoc.readyState == 4) handler(xmldoc, url);
}
xmldoc.load(url);
alert(xmldoc.xml);
  回复  更多评论
  
# re: JavaScript学习笔记——JavaScript中的XML
2007-08-27 10:52 | Candlelighting
JavaScript高级程序设计
这本书很好,可惜我才刚刚开始看。  回复  更多评论
  
# re: JavaScript学习笔记——JavaScript中的XML
2007-08-28 08:53 | Candlelighting
就应该是Undefined,因为firefox里的xmldom就没有xml的属性...  回复  更多评论
  
# re: JavaScript学习笔记——JavaScript中的XML
2007-09-06 13:48 | 喝小酒泡尼姑
FireFox对XPath的支持要难于使用得多,你需要使用到XPathEvaluator和XPathResult对象,并使用 XPathEvaluator的evaluate()方法计算XPath表达式,evaluate()接收五个参数:XPath表达式,上下文节点,命名空间解释程序
参见:
http://www.cnblogs.com/thinhunan/archive/2006/12/19/596985.html  回复  更多评论
  

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


网站导航:
 
<2007年8月>
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678

      生活将我们磨圆,是为了让我们滚得更远——“圆”来如此。
      我的作品:
      玩转Axure RP  (2015年12月出版)
      

      Power Designer系统分析与建模实战  (2015年7月出版)
      
     Struts2+Hibernate3+Spring2   (2010年5月出版)
     

留言簿(262)

随笔分类

随笔档案

文章分类

相册

关注blog

积分与排名

  • 积分 - 2286196
  • 排名 - 3

最新评论

阅读排行榜

评论排行榜