说明:参见《JavaScript高级程序设计》第15章"JavaScript中的XML "。
一. 浏览器中的XML DOM支持
目前只有两种浏览器支持客户端的XML处理,分别是IE和Mozilla。
1. IE中的XML DOM支持
在为IE添加XML支持时,微软在JavaScript之外另寻了个方案:基于ActiveX的MSXML库。
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关键字,这是JavaScript中ActiveX对象的特殊之处。
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 DOM的parseError的特性包含了关于解析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进行开发才真正有用。IE和Mozilla的实现之间有着很明显的区别,开发时会造成很严重的问题。需要找出一套能在两种浏览器中都可以使用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. IE中XPath的支持
每个节点的都有两个可用于获取匹配XPath模式的节点的方法:
selectNodes():用于匹配某个模式的节点的集合;
selectSingleNode():用于返回匹配给定模式的第一个节点。
eg. varlstNodes = oXmlDom.documentElement.selectNodes(“employee/name”);
返回包含所有匹配给定模式的节点的NodeList,可以通过如下方式迭代所有的元素:
for (var i = 0; i < varlstNodes.length; i++) {
alert(varlstNodes[i]);
}
如果没有匹配的节点,返回的NodeList的length为0。
3. Mozilla中XPath的支持
略。
三. 浏览器的XSLT支持
XSLT:可扩展样式表语言转换,可由一些模板组成。模板属于XML的某个特性的一部分(使用XPath指定),它可以决定为这一部分输出什么文本。通过为不同的元素和条件定义模板,XSLT样式表变成了一种XML的解析器。
1. IE对XSLT的支持
从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.0。MSXML的开发自从转到.NET Framework后就停止了。可能在未来的某天,JavaScript会允许访问XML和XSL的.NET对象。
2. Mozilla中XSLT的支持
略。
posted on 2007-08-13 13:19
阿蜜果 阅读(2800)
评论(6) 编辑 收藏 所属分类:
Javascript