高程3总结#第18章JavaScript与XML
JavaScript与XML
浏览器对XML DOM的支持
DOM2级核心
在通过JavaScript处理XML时,通常只使用参数root,因为这个参数指定的是XML DOM文档元素的标签名
var xmldom = document.implementation.createDocument("", "root", null); alert(xmldom.documentElement.tagName); //"root" var child = xmldom.createElement("child"); xmldom.documentElement.appendChild(child);
DOMParser类型
在解析XML之前,首先必须创建一个DOMParser的实例,然后再调用parseFromString()方法,这个方法接收两个参数,要解析的XML字符串和内容类型,返回的值是一个Document的实例
var parser = new DOMParser(); var xmldom = parser.parseFromString("<root><child/></root>", "text/xml"); alert(xmldom.documentElement.tagName); //"root" alert(xmldom.documentElement.firstChild.tagName); //"child" var anotherChild = xmldom.createElement("child"); xmldom.documentElement.appendChild(anotherChild); var children = xmldom.getElementsByTagName("child"); alert(children.length); //2
XMLSerialize类型
- XMLSerialize类型提供了相反的功能,将DOM文档序列化为XML字符串
要序列化DOM文档,首先必须创建XMLSerializer的实例,然后将文档传入其serializeToString()方法
var serializer = new XMLSerializer(); var xml = serializer.serializeToString(xmldom); alert(xml);
IE8及之前版本中的XML
6种不同的XML文档版本可以供选择
- Microsoft.XmlDom,最初随同IE发布,不建议使用
- MSXML2.DOMDocument,为方便脚本处理而更新的版本,建议仅在特殊情况下作为后备版本使用
- MSXML2.DOMDocument3.0,为了在JavaScript中使用,这是最低的建议版本
- MSXML2.DOMDocument4.0,在通过脚本处理时并不可靠,使用这个版本可能导致安全警告
- MSXML2.DOMDocument5.0,在通过脚本处理时并不可靠,使用这个版本可能导致安全警告
- MSXML2.DOMDocument6.0,通过脚本能够可靠处理的最新版本
如果解析过程中出错,可以在parseError属性中找到错误信息,这个属性本身是一个包含多个属性的对象,每个属性都保存着有关解析错误的某一方面信息
- errorCode,错误类型的数值编码,在没有发生错误时值为0
- filePos,文件中导致错误发生的位置
- line,发生错误的行
- linepos,发生错误的行中的字符
- reason,对错误的文本解释
- srcText,导致错误的代码
- url,导致错误的文件的URL
跨浏览器处理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; }
浏览器对XPath的支持
DOM3级XPath
- 在DOM3级XPath规范定义的类型中,最重要的两个类型是XPathEvaluator和XPathResult
XPathEvaluator用于在特定的上下文中对XPath表达式求值
- createExpression(expression, nsresolver) :将 XPath 表达式及相应的命名空间信息转换成一个 XPathExpression ,这是查询的编译版。在多次使用同一个查询时很有用。
- createNSResolver(node) :根据 node 的命名空间信息创建一个新的 XPathNSResolver 对象。在基于使用命名空间的 XML 文档求值时,需要使用 XPathNSResolver 对象。
evaluate(expression, context, nsresolver, type, result) :在给定的上下文中,基于特定的命名空间信息来对 XPath 表达式求值。剩下的参数指定如何返回结果。
- evaluate()是最常用的,这个方法接收5个参数:XPath表达式、上下文节点、命名空间求解器、返回结果的类型和保存结果的XPathResult对象。
其中第三个参数只在XML代码中使用了XML命名空间时有必要指定,如果XML代码中没有使用命名空间,这个参数应该指定为null。第四个参数的取值类型是下列常量之一
- XPathResult.ANY_TYPE,返回与 XPath 表达式匹配的数据类型。
- XPathResult.NUMBER_TYPE,返回数值。
- XPathResult.STRING_TYPE,返回字符串值。
- XPathResult.BOOLEAN_TYPE,返回布尔值。
- XPathResult.UNORDERED_NODE_ITERATOR_TYPE,返回匹配的节点集合,但集合中节点的次序不一定与它们在文档中的次序一致。
- XPathResult.ORDERED_NODE_ITERATOR_TYPE,返回匹配的节点集合,集合中节点的次序与它们在文档中的次序一致。这是最常用的结果类型。
- XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,返回节点集合的快照,由于是在文档外部捕获节点,因此对文档的后续操作不会影响到这个节点集合。集合中节点的次序不一定与它们在文档中的次序一致。
- XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,返回节点集合的快照,由于是在文档外部捕获节点,因此对文档的后续操作不会影响到这个节点集合。集合中节点的次序与它们在文档中的次序一致。
- XPathResult.ANY_UNORDERED_NODE_TYPE,返回匹配的节点集合,但集合中节点的次序不一定与它们在文档中的次序一致。
- XPathResult.FIRST_ORDERED_NODE_TYPE,返回只包含一个节点的节点集合,包含的这个节点就是文档中第一个匹配的节点
IE中的XPath
- IE对XPath的支持是内置在基于ActiveX的XML DOM文档对象中的,没有使用DOMParser返回的DOM对象,因此,为了在IE9以及之前的版本中使用XPath,必须使用基于ActiveX的实现,这个接口在每个节点上额外定义了两个方法:selectSingleNode()和selectNodes()
跨浏览器使用XPath
- 在其他使用DOM3级XPath对象的浏览器中,重新创建selectSingleNode()和selectNodes()方法。第一个函数接收三个参数:上下文节点、XPath表达式和可选的命名空间对象
命名空间对象应该是下面这种字面量形式
{ prefix1:"uri1", prefix2:"uri2", prefix3:"uri3" }
selectSingleNode()函数的完整代码
function selectSingleNode(context, expression, namespaces){ var doc = (context.nodeType != 9 ? context.ownerDocument : context); if (typeof doc.evaluate != "undefined"){ var nsresolver = null; if (namespaces instanceof Object){ nsresolver = function(prefix){ return namespaces[prefix]; }; } var result = doc.evaluate(expression, context, nsresolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null); return (result !== null ? result.singleNodeValue : null); } else if (typeof context.selectSingleNode != "undefined"){ //创建命名空间字符串 if (namespaces instanceof Object){ var ns = ""; for (var prefix in namespaces){ if (namespaces.hasOwnProperty(prefix)){ ns += "xmlns:" + prefix + "='" + namespaces[prefix] + "' "; } } doc.setProperty("SelectionNamespaces", ns); } return context.selectSingleNode(expression); } else { throw new Error("No XPath engine found."); } }
浏览器对XSLT的支持
IE中的XSLT
- 与IE对其他XML功能的支持一样,它对XSLT的支持也是通过ActiveX对象实现的,IE9中通过DOMParser创建的ODM文档不能使用XSLT
使用XSLT样式表转换XML文档的最简方式,就是将它们分别加到一个DOM文档中,然后再使用transformNode()方法,这个方法存在于文档的所有节点中,它接收一个参数,即包含XSLT样式表的文档,调用transformNode()方法会返回一个包含转换信息的字符串。
//加载 XML 和 XSLT(仅限于 IE) xmldom.load("employees.xml"); xsltdom.load("employees.xslt"); //转换 var result = xmldom.transformNode(xsltdom);
XSLTProcessor类型
- XSLTProcessor也支持使用setParameter()来设置XSLT的参数,这个方法接收三个参数:命名空间URI、参数内部名称和要设置的值
命名空间URI都是null,而内部名称就是参数的名称,另外,必须在调用transformToDocument()或transformToFragment()之前调用这个方法
var processor = new XSLTProcessor() processor.importStylesheet(xsltdom); processor.setParameter(null, "message", "Hello World! "); var result = processor.transformToDocument(xmldom);
还有两个与参数相关的方法,getParameter()和removeParameter(),分别用于取得和移除当前参数的值,这两个方法都要接受命名空间参数和参数的内部名称
var processor = new XSLTProcessor() processor.importStylesheet(xsltdom); processor.setParameter(null, "message", "Hello World! "); alert(processor.getParameter(null, "message")); //输出"Hello World!" processor.removeParameter(null, "message"); var result = processor.transformToDocument(xmldom);
重置处理器时要调用reset()方法,这个方法会从处理器中移除所有参数和样式,然后就可以再次调用importStyleSheet(),以加载不同的XSLT样式表
var processor = new XSLTProcessor() processor.importStylesheet(xsltdom); //执行转换 processor.reset(); processor.importStylesheet(xsltdom2); //再执行转换
跨浏览器使用XSLT
function transform(context, xslt){ if (typeof XSLTProcessor != "undefined"){ var processor = new XSLTProcessor(); processor.importStylesheet(xslt); var result = processor.transformToDocument(context); return (new XMLSerializer()).serializeToString(result); } else if (typeof context.transformNode != "undefined") { return context.transformNode(xslt); } else { throw new Error("No XSLT processor available."); } }