关于Ajax的一揽子工程(2)
关于Ajax的一揽子工程
--XML支持
随着XML的日益流行,对XML的支持成为每一门高级语言都需要面对的问题。虽然JSON能在Javascript中以更高的效率和更少的资源表达数据,但XML这种世界语作为Javascript与其它语言(包括运行在服务端的语言)优秀解决方案仍被大量使用。而且在AJAX应用中,XML通常是服务端对客户端异步请求的响应形式。
如何支持XML?
跟以前一样,IE和Firefox有不同的实现方式:
MSXML现在已经有五个不同的版本,所以工厂模式同样可用于XMLDOM的创建:
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可以以异步加载,所以我们又会见到类似这样的代码:
if (oXmlDom.readyState == 4) {
var oRoot = oXmlDom.documentElement;
var oFirstBook = oRoot.firstChild;
alert(oFirstBook.text);
}
};
和以前一样,4代表DOM完全载入。如果在载入数据时出现错语,则可以通过以下代码来处理:
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:
oXmlDom.load("books.xml");
oXmlDom.onload = function () {
//Do something when the document is fully loaded.
};
其中第一个参数为命名空间,第二个为标签名,第三个始终为null。在FireFox中,XMLDOM只能载入处部XML文件,而使用DOMParser对象来专门负责XML字符串的解析:
"<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类似的信息:
"<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 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程序员越来越重要的技能。
(未完待续……)