前几天了解了下javascript对于xml解析的一些知识,在这里稍作记录下。这里主要对针对IE、Mozilla进行相关代码编写及测试,不涉及chrome浏览器,因此可能在chrome浏览器相关代码无法正常工作。期间参考了《JavaScript高级程序设计》第15章中的相关知识。
针对chrome浏览器的读取xml文档,需通过XMLHttpRequest对象进行设置,因为在chrome浏览器通过document.implementation.createDocument方法创建的Document对象中并未定义load方法,因此必须通过下述方式获取。
var xmlhttp = new window.XMLHttpRequest();
xmlhttp.open("GET", file, false);
xmlhttp.send(null);
xmlDoc = xmlhttp.responseXML.documentElement;
IE通过ActiveXObject实现针对xml文档的操作,而Mozilla则通过document.implementation.createDocument对象实现对xml文档的操作。同时IE提供了load及loadXML两个方法访问xml,而Mozilla只提供了load方法进行。我们可以通过改造Mozilla的相关对象实现与IE相同的loadXML方法。
这里要说明的是在创建好xml文档操作的对象后,默认读取xml的模式为异步即async = true;
当async = true即异步模式时,javascript代码不会等待xml文档完全载入后才继续执行代码,那么就可能会出现在使用xml文档对象时,文档还尚未被完全载入的情况。同时IE与Mozilla处理异步模式的方式也不同:
1、针对IE,异步载入文件时,会使用readyState属性和触发onreadystatechange事件处理函数;readyState属性的说明如下:
0——DOM尚未初始化任何信息;
1——DOM正在载入数据;
2——DOM完成了数据载入;
3——DOM已经可用,不过某些部分可能还不能用;
4——DOM已经完全被加载,可以使用;
2、针对Mozilla,异步载入时,同样会使用readyState属性,但触发的是onload事件处理函数;但readyState属性的定义不同
‘loading’——DOM尚在载入数据;
‘complete’——DOM完成加载,可以使用;
那么当使用异步模式时,针对xml文档的处理就应该放在相应的事件处理函数中及readyState标识为完成加载时,而不应该紧接着load方法之后。
当async = false即异步模式时,可以不用考虑上述问题,因为这时候只有文档已经被完全载入后,javascript才会继续执行后面的代码;
针对以上两个问题,显而易见,为了使用javascript对xml文档的操作是要考虑浏览器的。为此可以创建以下代码:
function XmlDom() {
if (window.ActiveXObject) {
try {
var oXmlDom = new ActiveXObject("Microsoft.XMLDOM");
oXmlDom.async = false;
return oXmlDom;
} catch (oError) {
oError.reason;
}
throw new Error("MSXML is not installed on you system.");
} else if (document.implementation
&& document.implementation.createDocument) {
var oXmlDom = document.implementation.createDocument("", "", null);
oXmlDom.addEventListener("load", function() {
this.__changeReadyState__();
}, false);
/*
* 设置为同步模式,使其在调用 load 方法完成对xml文档的读入后在继续进行其他操作<br/>
* 如果设置为异步模式,则在使用 oXmlDom 对象前首先判断xml文档是否已经加载完成。<br/>
* xml文档加载完成的标志是:<br/>
* 1、在 IE 中 oXmlDom 对象的 readyState 属性等于4时;
* 2、在 Mozilla 中 oXmlDom 对象的 readyState 属性等于 'complete' 时;
*/
oXmlDom.async = true;
return oXmlDom;
} else {
throw new Error("Your browser doesn't support an XML DOM object.");
}
}
if (Document) {//这里偷懒了,需要判断是否是Mozilla
Document.prototype.onreadystatechange = null;
Document.prototype.__changeReadyState__ = function() {
if (typeof this.onreadystatechange == 'function') {
this.onreadystatechange();
}
};
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);
}
};
Document.prototype.__load__ = Document.prototype.load;
Document.prototype.load = function(sURL) {
this.__load__(sURL);
};
// 为节点定义xml获取函数,使其节点可以直接使用方法.xml
// __defineGetter__方法只在Mozilla中定义
Node.prototype.__defineGetter__("xml", function() {
var oSerializer = new XMLSerializer();
return oSerializer.serializeToString(this, "text/xml");
});
}
测试代码如下:
测试1、当使用同步模式时
function test() {
var oXmlDom = XmlDom();
oXmlDom.async = false;
oXmlDom.load("exam1.xml");
alert(oXmlDom.xml);
}
测试2、当使用异步模式时
function test() {
var oXmlDom = XmlDom();
oXmlDom.async = true;
oXmlDom.onreadystatechange = function() {
//IE|FF
if (oXmlDom.readyState == 4 || oXmlDom.readyState == "complete") {
alert(oXmlDom.xml);
}
}
oXmlDom.load("exam1.xml");
}
如果异步模式时仍使用测试1的代码,将不会得不到任何返回值;