Firefox 专门为把 XML 解析为 DOM 文档新增了 DOMParser 类型,后来所有其他浏览器也实现了该 类型。要使用 DOMParser,需要先创建它的一个实例,然后再调用 parseFromString()方法。这个方 法接收两个参数:要解析的 XML 字符串和内容类型(始终应该是"text/html")。返回值是 Document 的实例。来看下面的例子:
let parser = new DOMParser();
let xmldom = parser.parseFromString("<root><child/></root>", "text/xml");
console.log(xmldom.documentElement.tagName); // "root" console.log(xmldom.documentElement.firstChild.tagName); // "child"
let anotherChild = xmldom.createElement("child");
xmldom.documentElement.appendChild(anotherChild);
let children = xmldom.getElementsByTagName("child");
console.log(children.length); // 2
浏览器对 XML DOM 的支持
这个例子把简单的 XML 字符串解析为 DOM 文档。得到的 DOM 结构中是 document 元素, 22 它有个子元素。然后就可以使用 DOM 方法与返回的文档进行交互。
DOMParser 只能解析格式良好的 XML,因此不能把 HTML 解析为 HTML 文档。在发生解析错误时, 不同浏览器的行为也不一样。Firefox、Opera、Safari 和 Chrome 在发生解析错误时,parseFromString() 23 方法仍会返回一个 Document 对象,只不过其 document 元素是,该元素的内容为解 析错误的描述。下面是一个解析错误的示例:
<parsererror xmlns="http://www.mozilla.org/newlayout/xml/parsererror.xml">XML Parsing Error: no element found Location: file:// /I:/My%20Writing/My%20Books/ Professional%20JavaScript/Second%20Edition/Examples/Ch15/DOMParserExample2.js Line Number 1, Column 7:<sourcetext><root> ------^</sourcetext></parsererror>
Firefox 和 Opera 都会返回这种格式的文档。Safari 和 Chrome 返回的文档会把元素 嵌入在发生解析错误的位置。早期 IE 版本会在调用 parseFromString()的地方抛出解析错误。由于 这些差异,最好使用 try/catch 来判断是否发生了解析错误,如果没有错误,则通过 getElements- ByTagName()方法查找文档中是否包含元素,如下所示:
let parser = new DOMParser(),
xmldom,
if (errors.length > 0) {
errors; try {
xmldom = parser.parseFromString("<root>", "text/xml");
errors = xmldom.getElementsByTagName("parsererror");
throw new Error("Parsing error!");
}
} catch (ex) {
console.log("Parsing error!");
}
这个例子中解析的 XML 字符串少一个标签,因此会导致解析错误。IE 此时会抛出错误。 Firefox 和 Opera 此时会返回 document 元素为的文档,而在 Chrome 和 Safari 返回的文 档中,是的第一个子元素。调用 getElementsByTagName(“parsererror”) 可适用于后两种情况。如果该方法返回了任何元素,就说明有错误,会弹警告框给出提示。当然,此时 可以进一步解析出错误信息并显示出来。
XMLSerializer类型
与 DOMParser 相对,Firefox 也增加了 XMLSerializer 类型用于提供相反的功能:把 DOM 文档 序列化为 XML 字符串。此后,XMLSerializer 也得到了所有主流浏览器的支持。
要序列化 DOM 文档,必须创建 XMLSerializer 的新实例,然后把文档传给 serializeToString() 方法,如下所示:
let serializer = new XMLSerializer();
let xml = serializer.serializeToString(xmldom);
console.log(xml);
serializeToString()方法返回的值是打印效果不好的字符串,因此肉眼看起来有点困难。
XMLSerializer 能够序列化任何有效的 DOM 对象,包括个别节点和 HTML 文档。在把 HTML 文 档传给 serializeToString()时,这个文档会被当成 XML 文档,因此得到的结果是格式良好的。
注意 如果给serializeToString()传入非DOM对象,就会导致抛出错误。
浏览器对XPath的支持
XPath 是为了在 DOM 文档中定位特定节点而创建的,因此它对 XML 处理很重要。在 DOM Level 3 之前,XPath 相关的 API 没有被标准化。DOM Level 3 开始着手标准化 XPath。很多浏览器实现了 DOM Level 3 XPath 标准,但 IE 决定按照自己的方式实现。
DOM Level 3 XPath
DOM Level 3 XPath 规范定义了接口,用于在 DOM 中求值 XPath 表达式。要确定浏览器是否支持 DOM Level 3 XPath,可以使用以下代码:
let supportsXPath = document.implementation.hasFeature("XPath", "3.0");
```
虽然这个规范定义了不少类型,但其中最重要的两个是 XPathEvaluator 和 XPathResult。 XPathEvaluator 用于在特定上下文中求值 XPath 表达式,包含三个方法。
createExpression(expression, nsresolver),用于根据 XPath 表达式及相应的命名空间 计算得到一个 XPathExpression,XPathExpression 是查询的编译版本。这适合于同样的查 询要运行多次的情况。
createNSResolver(node),基于 node 的命名空间创建新的 XPathNSResolver 对象。当对 使用名称空间的 XML 文档求值时,需要 XPathNSResolver 对象。
evaluate(expression, context, nsresolver, type, result),根据给定的上下文和 命名空间对 XPath 进行求值。其他参数表示如何返回结果。
Document 类型通常是通过 XPathEvaluator 接口实现的,因此可以创建 XPathEvaluator 的实 例,或使用 Document 实例上的方法(包括 XML 和 HTML 文档)。
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE:返回节点集合的快照,在文档外部捕获节点, 因此对文档的进一步修改不会影响这个节点集合。集合中节点的顺序与它们在文档中的顺序一致。 23
XPathResult.ANY_UNORDERED_NODE_TYPE:返回匹配节点的集合,但集合中节点的顺序可能 与它们在文档中的顺序不一致。
XPathResult.FIRST_ORDERED_NODE_TYPE:返回只有一个节点的节点集合,包含文档中第一 个匹配的节点。
指定的结果类型决定了如何获取结果的值。下面是一个典型的示例:
```js
let result = xmldom.evaluate("employee/name", xmldom.documentElement, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
if (result !== null) {
let element = result.iterateNext();
while(element) {
console.log(element.tagName);
node = result.iterateNext();
```
在上述三个方法中,使用最频繁的是 evaluate()。这个方法接收五个参数:XPath 表达式、上下 文节点、命名空间解析器、返回的结果类型和 XPathResult 对象(用于填充结果,通常是 null,因 为结果也可能是函数值)。第三个参数,命名空间解析器,只在 XML 代码使用 XML 命名空间的情况下 有必要。如果没有使用命名空间,这个参数也应该是 null。第四个参数要返回值的类型是如下 10 个常 18 量值之一。
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:返回节点集合的快照,在文档外部捕获节 点,因此对文档的进一步修改不会影响该节点集合。集合中节点的顺序可能与它们在文档中的 顺序不一致。
## 浏览器对 XPath 的支持
这个例子使用了 XPathResult.ORDERED_NODE_ITERATOR_TYPE 结果类型,也是最常用的类型。 如果没有节点匹配 XPath 表达式,evaluate()方法返回 null;否则,返回 XPathResult 对象。返回 的 XPathResult 对象上有相应的属性和方法用于获取特定类型的结果。如果结果是节点迭代器,无论有序还是无序,都必须使用 iterateNext()方法获取结果中每个匹配的节点。在没有更多匹配节点时, iterateNext()返回 null。