JavaScript高级程序设计读书笔记18

第18章 JavaScript与XML

浏览器对XML DOM的支持

DOM2级核心

  • document.implementation.createDocument():创建一个空白的XML文档

DOMParser类型

  • 将XML解析为DOM文档,首先必须创建一个DOMParser的实例,然后再调用parseFromString()方法,返回值是一个document实例
  • DOMParser只能解析XML,不能讲HTML解析为HTML文档
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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

XMLSerializer类型

  • 将DOM文档序列化为XML文档,使用XMLSerializer类型
  • XMLSerializer类型可以序列化XML和HTML

IE8及之前版本中的XML

  • 通过ActivrX对象实现对XML的支持
  • 创建XML文档:使用ActiveXObject构造函数并为其传入一个表示XML文档版本的字符串
  • 解析XML:loadXML()方法
  • 序列化:每个DOM节点都有一个xml属性,xmldom.xml
  • 加载XML文件:确定加载XML方式,调用load()启动下载过程

跨浏览器处理XML

  • 解析XML

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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;
    }
  • 序列化XML

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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.");
    }
    }

浏览器对XPath的支持

  • XPath是设计用来在DOM文档中查找节点的一种手段,因而对XML处理也很重要

DOM3级XPath

  • XPathEvaluator:用于在特定的上下文中对XPath表达式求值
  • 处理命名空间有两种方法:

    1.createNSResolver()创建XPathNSResolver对象
    2.定义一个函数,让它接收一个命名空间前缀

IE中的XPath

  • 在IE8及之前的浏览器,XPath是采用内置基于ActiveX的XML DOM文档对象实现的。在每一个节点上提供了两个方法:selectSingleNode()和selectNodes()。
  • 处理命名空间的方法:setProperty()

跨浏览器使用XPath

  • 要在其它使用DOM3级XPath对象的浏览器中,重新创建selectSingleNode()和selectNodes()方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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的支持

  • XSLT:它利用XPath将文档从一种表现形式转换成另一种表现形式

IE中的XSLT

  • 简单的XSLT转换:使用XSLT样式表

    1
    2
    3
    xmldom.load("employees.xml");
    xstldom.load("employees.xstl");
    var result = xmldom.transformNodes(xstldom);
  • 复杂的XSLT转换:使用XSL模板和XSL处理器

  • 第一步: 先要把XSTL样式表加载到一个线程安全的XML文档中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function createThreadSafeDocument() {
    if (typeof arguments.callee.activeXString != "string") {
    var versions = ["MSXML2.FreeThreadedDOMDocument.6.0", "MSXML2.FreeThreadedDOMDocument.3.0", "MSXML2.FreeThreadedDOMDocument"],
    i, len;
    for (i = 0, len = versions.length; i < len; i++) {
    try {
    new ActiveXObject(versions[i]);
    arguments.callee.activeXString = versions[i];
    break;
    } catch (ex) {
    //skip
    }
    }
    }
    return new ActiveXObject(arguments.callee.activeXString);
    }
  • 第二步:将创建并加载了自由线程的DOM文档指定给一个XSL模板,这也是一个ActiveX对象,模板用来创建XSL处理器对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function createXSTLTemplate() {
    if (typeof arguments.callee.activeXString != "string") {
    var versions = ["MSXML2.FreeThreadedDOMDocument.6.0", "MSXML2.FreeThreadedDOMDocument.3.0", "MSXML2.FreeThreadedDOMDocument"],
    i, len;
    for (i = 0, len = versions.length; i < len; i++) {
    try {
    new ActiveXObject(versions[i]);
    arguments.callee.activeXString = versions[i];
    break;
    } catch (ex) {
    //skip
    }
    }
    }
    return new ActiveXObject(arguments.callee.activeXString);
    }
  • 使用示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var xsltdom = createThreadSafeDocument();
    xstldom.async = false;
    xsltdom.load("employees.xslt");

    var template = createXSTLTemplate();
    template.stylesheet = xstldom;

    var processor = tempalte.createProcessor();
    processor.input = xmldom;
    processor.transform();
    var result = processor.output;

XSLTProcessor类型

  • XSLTProcessor:是通过JS进行XSLT转换的事实标准
    1
    2
    var processor = new XSLTProcessor();
    processor.importStylesheet(xsltdom);

跨浏览器使用XSLT

  • 接收两个参数: 要执行转换的上下文节点和XSLT文档对象。 返回序列化之后的字符串。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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 caontext.transformNode(xslt);
    } else {
    throw new Error("No XSLT processor available.");
    }
    }