一、解析XML
很少有开发人员能够有福气专门针对一款浏览器做开发。因此,编写能够跨浏览器处理 XML 的函数就成为了常见的需求。对解析 XML 而言,下面这个函数可以在所有四种主要浏览器中使用。
function parseXml(xml){
var xmldom = null;
if (typeof DOMParser != "undefined"){
xmldom = (new DOMParser()).parseFromString(xml, "text/xml");
var errors = xmldom.getElementsByTagName("parsererror");
if (errors.length){
throw new Error("XML parsing error:" + errors[0].textContent);
}
} else if (typeof ActiveXObject != "undefined"){
xmldom = createDocument();
xmldom.loadXML(xml);
if (xmldom.parseError != 0){
throw new Error("XML parsing error: " + xmldom.parseError.reason);
}
} else {
throw new Error("No XML parser available.");
}
return xmldom;
}
这个parseXml()
函数只接收一个参数,即可解析的 XML 字符串。在函数内部,我们通过能力检测来确定要使用的 XML 解析方式。DOMParser
类型是受支持最多的解决方案,因此首先检测该类型是否有效。如果是,则创建一个新的DOMParser
对象,并将解析 XML 字符串的结果保存在变量xmldom
中。由于DOMParser
对象在发生解析错误时不抛出错误(除 IE9+ 之外),因此还要检测返回的文档以确定解析过程是否顺利。如果发现了解析错误,则根据错误消息抛出一个错误。
函数的最后一部分代码检测了对 ActiveX 的支持,并使用前面定义的createDocument()
函数来创建适当版本的 XML 文档。与使用DOMParser
时一样,这里也需要检测结果,以防有错误发生。如果确实有错误发生,同样也需要抛出一个包含错误原因的错误。
如果上述 XML 解析器都不可用,函数就会抛出一个错误,表示无法解析了。
在使用这个函数解析 XML 字符串时,应该将它放在try-catch
语句当中,以防发生错误。来看下面的例子。
var xmldom = null;
try {
xmldom = parseXml("<root><child/></root>");
} catch (ex){
alert(ex.message);
}
//进一步处理
二、序列化XML
对序列化 XML 而言,也可以按照同样的方式编写一个能够在四大浏览器中运行的函数。例如:
function serializeXml(xmldom){
if (typeof XMLSerializer != "undefined"){
return (new XMLSerializer()).serializeToString(xmldom);
} else if (typeof xmldom.xml != "undefined"){
return xmldom.xml;
} else {
throw new Error("Could not serialize XML DOM.");
}
}
这个serializeXml()
函数接收一个参数,即要序列化的 XML DOM 文档。与parseXml()
函数一样,这个函数首先也是检测受到最广泛支持的特性,即XMLSerializer
。如果这个类型有效,则使用它来生成并返回文档的 XML 字符串。由于 ActiveX 方案比较简单,只使用了一个xml
属性,因此这个函数直接检测了该属性。如果上述两方面尝试都失败了,函数就会抛出一个错误,说明序列化不能进行。一般来说,只要针对浏览器使用了适当的 XML DOM 对象,就不会出现无法序列化的情况,因而也就没有必要在try-catch
语句中调用serializeXml()
。结果,就只需如下一行代码即可:
var xml = serializeXml(xmldom);
注意:只不过由于序列化过程的差异,相同的 DOM 对象在不同的浏览器下,有可能会得到不同的 XML 字符串。