使用XPath在DOM中搜索相同字符串的倍数



我正在编写一个Chrome扩展,将搜索DOM并突出显示页面上的所有电子邮件地址。我发现这是为了寻找页面上的符号,但它只有在有一个电子邮件地址时才能正确返回,当有多个地址时它会中断。

found = document.evaluate('//*[contains(text(),"@")]', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0);

如果找到多个返回倍数,正确的方法是什么?

如果你想处理多个结果,不要在document.evaluate()上调用.snapshotItem(0),而是使用for循环和snapshotLength():

示例:使用snapshotLength()snapshotItem() 遍历结果
var nodesSnapshot = document.evaluate('//*[contains(text(),"@")]',
    document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
for ( var i=0 ; i < nodesSnapshot.snapshotLength; i++ )
{
  console.dir( nodesSnapshot.snapshotItem(i) );
}

或者指定XPathResult.UNORDERED_NODE_ITERATOR_TYPE参数(而不是XPathResult.ORDERED_NODE_SNAPSHOT_TYPE),并使用while循环与iterateNext():

示例:使用iterateNext() 遍历结果
var iterator = document.evaluate('//*[contains(text(),"@")]',
    document, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null );
try {
  var thisNode = iterator.iterateNext(); 
  while (thisNode) {
    console.dir( thisNode );
    thisNode = iterator.iterateNext();
  } 
}
catch (e) {
  console.log( 'Error: Document tree modified during iteration ' + e );
}

在与这个问题中的情况相反的情况下-当您真的只想获得第一个匹配节点时-您可以指定XPathResult.FIRST_ORDERED_NODE_TYPE值,只返回单个节点,然后使用属性(而不是方法)singleNodeValue:

示例:使用XPathResult.FIRST_ORDERED_NODE_TYPEsingleNodeValue
var firstMatchingNode = document.evaluate('// [contains(text(),"@")]',
    document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null );
console.dir( firstMatchingNode.singleNodeValue );

获取文本或计数,或测试true/false条件

请注意,您可以将其他值(常量)指定为document.evaluate()的倒数第二个参数以获得其他结果类型,您可以使其直接返回:

  • 单个字符串(XPathResult.STRING_TYPE)从文档的某些部分发出呼噜声
  • 表示某种计数的数字( XPathResult.NUMBER_TYPE);例如,计数的数量在文档
  • 中找到的电子邮件地址
  • 一个布尔值(XPathResult.BOOLEAN_TYPE),表示文档的某些真/假方面;例如,指示文件是否包含电子邮件地址

当然,要获得其他结果类型,作为document.evaluate()的第一个参数提供的XPath表达式需要是一个实际返回字符串、数字或布尔值(而不是返回一组属性节点或元素节点)的表达式。


更多链接MDN

上面的例子都是基于MDN介绍在JavaScript中使用XPath教程,强烈推荐给任何试图使用XPath和document.evaluate()的人。

通过下面的代码,您可以将XPath选择器的结果作为一个数组。

const xpath = `//*[contains(text(),"@")]`;//your special XPath
const elements = Array.from((function*(){ let iterator = document.evaluate(xpath, document, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null); let current = iterator.iterateNext(); while(current){ yield current; current = iterator.iterateNext(); }  })());
//Use the simple array

也可以把它作为一个函数,用于更多的调用…

function getElementsByXPath(xpath) {
    return Array.from((function*(){ let iterator = document.evaluate(xpath, document, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null); let current = iterator.iterateNext(); while(current){ yield current; current = iterator.iterateNext(); }  })());
}

享受…

最新更新