在这里我要介绍一个我早些时间编写的一个封装XML DOM操作的库 CXML。写这个库的原因都是基于对XML DOM操作的繁杂性和重复性,况且不用说它的效率底下了,这是我们都感同身受的。CXML可以操作导入的xml文件以及xml字符串,CXML里提供了四个接口方法:load,toXMLString,getXMLObject,selectNodes。需要指出的一点是,load和selectNodes方法是最强大的部分。当然了,CXML同时还可以跟使用Ajax通过responseXML返回的XML DOM对象结合使用。
- load:提供了一个参数,该参数可以一个xml文件的URL,也可以是一段符合xml语法的xml字符串。比如:cxml.load(“
“),或者cxml.load(“http://www.ilovejs.net/xml/test.xml”);supersha 24 - toXMLString:该方法带有一个可选择的node节点,返回该节点内的xml字符串,默认是XML DOM实力对象。
- getXMLObject:返回XML DOM实力对象。
- selectNodes:该方法的参数是一个css形式的selectors,从XML DOM对象中查询节点集合。支持的selectors在下面会有说明。
同时需要说明的是:selectNodes方法内是通过XPath来查询XML DOM实例对象的,不过它扩展了一些css形式的selectors,其他的XPath形式的查询字符串都是支持的,因为它给予XPath的查询。CXML在编写的过程中遇到的唯一的问题就是Google Chrome 和 Safari载入xml文件的时候无法生成XML DOM对象的兼容性问题,这个问题琢磨了有些时间。最后不得不使用这种的方式,对Google Chrome和Safari使用XMLHttpRequest的方式来加载,通过responseXML的形式来返回XML DOM对象。不过Google Chrome和Safari对加载xml字符串的形式是可以的。
CXML目前支持的css形式的selectors有(顺便也附带上例子吧
),不过这些selectors最终都会转化为XPath的方式来查询:
[javascript]
//下面是载入XML字符串的形式
var cxml=new CXML();
cxml.load("<item id=’it’><name>supersha</name><age>24</age></item>");
cxml.selectNodes("item"); //得到全部item元素的引用
cxml.selectNodes("item:attr[@id]");
cxml.selectNodes("item:first-child"); //or cxml.selectNodes("item:first");
cxml.selectNodes("item > name");
cxml.selectNodes("item:last-child"); // or cxml.selectNodes("item:last");
cxml.selectNodes("item:only-child");
cxml.selectNodes("item:nth-child(1)");
cxml.selectNodes("item:text");
cxml.selectNodes("item,name");
//下面是载入XML文件的方式
var cxml=new CXML();
cxml.load("http://www.ilovejs.net/xml/test.xml",true,function(oXml){
oXml.selectNodes("item");
……
}
//下面是跟Ajax结合的方式
var cxml=new CXML(request.responseXML);
cxml.selectNodes("item:only-child");
cxml.selectNodes("item:nth-child(1)");
cxml.selectNodes("item:text");
cxml.selectNodes("item,name");
[/javascript]
可怜的是IE对XPath支持的太少,Fuck IE!!!下面是展示CXML的源码:
[javascript]
(function(){
//使得Mozilla浏览器能兼容IE的使用方法而定义xml属性和loadXML方法
if (document.__defineGetter__) {
Node.prototype.__defineGetter__("xml", function(){
//Mozilla浏览器要获取xml代码,需要使用XMLSerializer对象
//XMLSerializer对象对象的唯一方法是serializeToString(),
//它接受一个oXmlDom节点和一个内容类型作为参数
var os = new XMLSerializer();
return os.serializeToString(this, "text/xml");
});
Document.prototype.loadXML = function(sXML){
//Mozilla下要想载入XML类型的字符串,必须使用DOMParser对象
//parseFromString()是DOMParser对象的唯一方法,
//以药解析的xml字符串以及内容类型为参数,并返回一个XML DOM实例对象
var oParser = new DOMParser();
var oXml = oParser.parseFromString(sXML, "text/xml");
//清除掉原本的XML DOM对象的内容
while (this.firstChild) {
this.removeChild(this.firstChild);
}
//使用XML DOM对象的importNode方法获取节点并添加到XML DOM对象中
for (var i = 0, l = oXml.childNodes.length; i < l; i++) {
this.appendChild(this.importNode(oXml.childNodes[i], true));
}
}
//这个是位Mozilla浏览器扩展的selectNodes方法,目的是
//让它跟IE的selectNodes方法有相同的使用方式
//并且以一个XPath字符串作为参数
Element.prototype.selectNodes = function(sXPath){
//Mozilla浏览器中处理XPath相关的对象主要是:XPathEvaluator和XPathResult对象
//XPathEvaluator利用它的evaluate方法计算XPath,并返回结果集
//但是需要注意的是:返回的节点集合没有length属性,所以不得不利用
//iterateNext方法循环取得结果节点集合的值并添加到数组中
var oEvaluator = new XPathEvaluator();
var oResult = oEvaluator.evaluate(sXPath, this, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
var aNodes = [];
if (oResult != null) {
var elem = oResult.iterateNext();
while (elem) {
aNodes.push(elem);
elem = oResult.iterateNext();
}
}
return aNodes;
}
}
//跨浏览器声明XML Document实例对象
var createXML = function(oXml){
if (oXml && typeof oXml === "object") {
return oXml;
}
var xml = false;
//Mozilla
if (document.implementation && document.implementation.createDocument) {
xml = document.implementation.createDocument("", "", null);
return xml;
} else if (window.ActiveXObject) { // IE
var args = ["MSXML2.DOMDocument.5.0", "MSXML2.DOMDocument.4.0", "MSXML2.DOMDocument.3.0", "MSXML2.DOMDocument", "Microsoft.XmlDom"];
for (var i = 0, l = args.length; i < l; i++) {
try {
xml = new ActiveXObject(args[i]);
return xml;
}
catch (e) {
}
}
} else {
return false;
}
}
//判断是否是Chrome和Safari浏览器
var isChromeOrSafari = function(){
var userAgent = window.navigator.userAgent;
if (userAgent.indexOf("Chrome") !== -1 || userAgent.indexOf("Safari") !== -1) {
return true;
}
return false;
}
var CXML = function(oXML){
this.xml = createXML(oXML);
}
//sXML:可以是xml文件路径(相对或者绝对),xml格式的字符串
//async:是异步加载(true),还是同步(false)
//callback:加载xml文件完毕之后调用的回调函数,该函数的参数为当前的XML DOM对象
CXML.prototype.load = function(sXML, async, callback){
var that = this;
that.xml.async = async || true;
//以文件的形式载入
if (/.+\.xml/.test(sXML)) {
//利用XMLHttpRequest对象来处理Chrome和Safari浏览器无法载入xml文件的兼容处理方法
//不过Chrome、Safari浏览器对载入XML字符串是支持的
if (isChromeOrSafari()) {
var xhr = new XMLHttpRequest();
xhr.open("GET", sXML, async);
xhr.onreadystatechange = function(){
if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 304)) {
that.xml = xhr.responseXML;
callback ? callback(that.xml) : null;
}
}
xhr.send(null);
} else {
try {
//Mozilla,在异步载入xml文件的时候,需要利用onload事件来判断文件是否载入完成
that.xml.onload = function(){
callback ? callback(that.xml) : null;
}
}
catch (e) {
// IE,在异步载入xml文件的时候,IE会有一个readyState的改变,
//因此,会触发onreadystatechange事件
that.xml.onreadystatechange = function(){
if (that.xml.readyState === 4) {
callback ? callback(that.xml) : null;
}
}
}
that.xml.load(sXML);
}
} else if (/<[^>]*/.test(sXML)) { //以XML字符串的形式载入
that.xml.loadXML(sXML);
}
}
//用于输出指定节点node开始的xml字符串
CXML.prototype.toXMLString = function(node){
node = node || this.xml;
return node.xml;
}
//返回XML DOM对象
CXML.prototype.getXMLObject = function(){
return this.xml;
}
//利用XPath在XML文档中进行查找符合XPath条件的节点集合
CXML.prototype.selectNodes = function(sXPath){
var regs = [/^(\w+)/, /\s?(,)\s?/g, /(:text)/g, /:attr\[@(\w+)\]/g, /(:first-child)|(:first)/g, /(:last-child)|(:last)/g, /(\s?>\s?)/g, /:nth-child\((\d+)\)/g, /:only-child/g, /(?=\s)(\w+\[@\w+\])/g];
var xpath = ["//$1", "|//", "/text()", "/attribute::$1", "/child::*[1]", ‘/child::*[last()]‘, "/", "/child::*[$1]", "/child::*", "//$1"];
for (var i = 0, l = regs.length; i < l; i++) {
sXPath = sXPath.replace(regs[i], xpath[i]);
}
var nodes = this.xml.documentElement.selectNodes(sXPath);
return nodes.length === 1 ? nodes[0] : nodes;
}
window.CXML = CXML;
})();
[/javascript]
唉,刚学js没多久,我调试chrome浏览器对xml Dom操作都崩溃了,好东西,收藏用着了。