JavaScript中XPath操作的基本方法与浏览器兼容性

作者:小圆点时间:2026-10-30 08:11:50浏览:285

本文介绍JavaScript中XPath的基本操作方法。在现代浏览器中,通过document.evaluate()执行查询,支持多种返回类型如节点迭代器与快照。针对含命名空间的XML文档,需配置命名空间解析器。此外,文章详述了IE8等旧版浏览器通过selectSingleNode/selectNodes及XML数据岛实现XPath支持的兼容方案。

XPath在JavaScript中的基本应用

Xpath现在很少被我们使用,因为JSON现在很盛行。可是在XML做为数据交换格式的年代,Xpath在我们随机访问大的xml文档结构的时候扮演着非常重要的位置。也许大家现在很多没有注意到,DOM Level 3 XPath指定的接口已经被Firefox,Safari, Chrome, and Opera实现了。他们所实现的核心接口就是XPathEvaluator,它包含一些能够使用xpath表达式进行工作的方法,最主要的方法就是evaluate(),它能够接受五个参数1.xpath查询字符串2.指明xpath查询字符串应该从哪个节点开始3.命名空间解析器(稍后介绍)4.返回的结果类型5.返回的结果应该添加到那个对象上(很少被使用,因为结果主要通过evaluate()返回)。

XPathResult对象定义了10种不同的返回类型常量,每种类型对应特定的查询结果格式。

  • XPathResult.ANY_TYPE:适用于任何数据类型,由XPath表达式决定。
  • XPathResult.ANY_UNORDERED_NODE_TYPE:返回匹配节点的集合,节点顺序可能与文档中的顺序不一致。
  • XPathResult.BOOLEAN_TYPE:返回布尔类型结果。
  • XPathResult.FIRST_ORDERED_NODE_TYPE:返回文档中匹配的第一个节点。
  • XPathResult.NUMBER_TYPE:返回数值类型结果。
  • XPathResult.ORDERED_NODE_ITERATOR_TYPE:返回匹配节点的集合,节点顺序与文档中的顺序保持一致。
  • XPathResult.ORDERED_NODE_SNAPSHOT_TYPE:返回节点集合的快照,将节点捕获在文档外部,确保后续对文档的修改不影响该集合。集合中节点的顺序与文档顺序一致。
  • XPathResult.STRING_TYPE:返回字符串类型结果。
  • XPathResult.UNORDERED_NODE_ITERATOR_TYPE:返回匹配节点的集合,节点顺序可能与文档中的顺序不一致。
  • XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE:返回节点集合的快照,将节点捕获在文档外部,确保后续对文档的修改不影响该集合。集合中节点的顺序无需与文档顺序一致。

XPathResult返回类型详解

了解了上述API后,实际使用时,evaluate()函数的返回信息完全取决于请求的结果类型。执行XPath查询需要借助XPathEvaluator对象,可以实例化一个新对象并初始化,或直接使用浏览器内置的对象。


var evaluator = new XPathEvaluator(); 
//得到第一个div 
var result = evaluator.evaluate("//div", document.documentElement, null, 
         XPathResult.FIRST_ORDERED_NODE_TYPE, null); 
alert("First div ID is " + result.singleNodeValue.id); 

现代浏览器中的evaluate()使用

在Firefox、Safari、Chrome和Opera中,所有文档实例均实现了XPathEvaluator接口。因此,在HTML页面中执行查询时,可直接使用document.evaluate()。若通过XMLHttpRequest或其他机制获取XML文档,同样可以使用evaluate()方法,例如:


//get first div 
var result = document.evaluate("//div", document.documentElement, null, 
         XPathResult.FIRST_ORDERED_NODE_TYPE, null); 
alert("First div ID is " + result.singleNodeValue.id); 

接下来介绍两种返回多节点的方式,先通过实例进行说明:


//get all divs - iterator style 
var result = document.evaluate("//div", document.documentElement, null, 
         XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); 
if (result){ 
  var node = result.iterateNext(); 
  while(node) { 
    alert(node.id); 
    node = node.iterateNext(); 
  } 
} 
//get all divs - SNAPSHOT style 
var result = document.evaluate("//div", document.documentElement, null, 
         XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 
if (result){ 
  for (var i=0, len=result.snapshotLength; i < len; i++) { 
    alert(result.snapshotItem(i).id); 
  } 
} 

命名空间解析器的配置

关于命名空间的处理:如果仅在HTML文档中进行简单的XPath查询,evaluate()中的命名空间解析器参数通常设为null。若需在包含命名空间的XML文档中查询,则需学习如何创建和使用命名空间解析器。除默认命名空间外,每个命名空间URI都映射到特定的前缀,命名空间解析器负责在XPath引擎中建立前缀与URI的映射。第一种生成方法是创建一个接受命名空间前缀为参数并返回对应URL的方法,例如:


function resolver(prefix){ 
  switch(prefix){ 
    case "wrox": return "http://www.wrox.com/"; 
    case "ncz": return "http://www.nczonline.net/"; 
    default: return "http://www.yahoo.com/"; 
  } 
} 

第二种方法是利用包含命名空间信息的节点来生成解析器。


<books xmlns:wrox="http://www.wrox.com/" xmlns="http://www.amazon.com/"> 
  <wrox:book>Professional JavaScript</book> 
</books> 

<books>元素包含了所有命名空间信息,可将该节点的引用传递给XPathEvaluator对象的createNSResolver()方法,从而自动获得命名空间解析器。例如:


var evaluator = new XPathEvaluator(); 
var resolver = evaluator.createNSResolver(xmldoc.documentElement); 

使用上述任一方法,即可轻松在包含命名空间的XML文档中进行查询。


var evaluator = new XPathEvaluator(); 
var resolver = evaluator.createNSResolver(xmldoc.documentElement); 
var result = evaluator.evaluate("wrox:book", xmldoc.documentElement, 
         resolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null); 
if (result){ 
  alert(result.singleNodeValue.firstChild.nodeValue); 
} 

注意:如果在包含命名空间的XML文档中执行查询而未提供命名空间解析器,将会导致错误。

IE浏览器的兼容处理方案

关于IE浏览器对XPath的支持:IE8尚未实现DOM Level 3 XPath定义的接口,但提供了有限的XPath支持,主要适用于XML文档,对HTML文档对象不可用。在IE中生成XML文档的方法包括:


function createDocument(){ 
  if (typeof arguments.callee.activeXString != "string"){ 
    var versions = ["MSXML2.DOMDocument.6.0", 
            "MSXML2.DOMDocument.3.0", 
            "MSXML2.DOMDocument"]; 
    for (var i=0,len=versions.length; i < len; i++){ 
      try { 
        var xmldom = new ActiveXObject(versions[i]); 
        arguments.callee.activeXString = versions[i]; 
        return xmldom; 
      } catch (ex){ 
        //skip 
      } 
    } 
  } 
  return new ActiveXObject(arguments.callee.activeXString); 
} 

生成文档对象后,可使用loadXML()方法加载内容:


var xmldoc = createDocument(); 
xmldoc.loadXML(""); 

第二种方法是通过XMLHttpRequest对象请求生成XML对象。


var xhr = new XMLHttpRequest(), 
  xmldoc; 
xhr.open("get", "data.xml", true); 
xhr.onreadystatechange = function(){ 
  if (xhr.readyState == 4){ 
    if (xhr.status >= 200 && xhr.status < 300){ 
      xmldoc = xhr.responseXML; 
    } 
}; 
xhr.send(null); 

第三种方法是使用<xml>标签,Microsoft称之为“XML数据岛”,示例如下:


<xml id="myXML" src="data.xml"></xml>

随后:


var xmldoc = document.getElementById("myXML").XMLDocument;

XPath支持方面:IE中的XML文档对象提供了两个内置方法以支持XPath:selectSingleNode()和selectNodes()。这两个方法均接受XPath表达式作为参数,分别返回第一个匹配节点和所有匹配节点。关于命名空间支持:


<books xmlns:wrox="http://www.wrox.com/" xmlns="http://www.amazon.com/">
  <wrox:book>Professional JavaScript</book>

对于</books>这段XML文档,应采用以下方法进行查询,即首先使用setProperty()设置XML文档的命名空间。


xmldoc.setProperty("SelectionNamespaces",
  "xmlns:wrox='http://www.wrox.com/' xmlns='http://www.amazon.com/'");
var book = xmldoc.documentElement.selectSingleNode("wrox:book");

作者最新文章