高程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.");
}
}

相关推荐