【问题标题】:Searching the DOM for multiples of the same string, using XPath使用 XPath 在 DOM 中搜索多个相同字符串
【发布时间】:2015-12-04 17:38:03
【问题描述】:

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

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

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

【问题讨论】:

  • 您可以使用innerHTML 搜索带有RegExp 的字符串并用元素包装它们
  • 查看 this answer 以使用 XPath 选择包含特定文本的节点。
  • @PitaJ 该页面上的问题和答案很好,但这是关于属性节点的,OP 似乎想要获取包含 @ 字符的 element 节点.在这种情况下,问题中的 XPath 表达式就可以了。
  • @sideshowbarker 是的,我认为它至少是相关的。他的 XPath 让我可以选择带有该文本的每个节点。他只需要 while 循环遍历列表(在最后增加零)
  • @RyanGrush 在使用 document.evaluate() 和 XPath 时要小心——因为它有点像一把性能枪,因为它允许您构建非常复杂的查询,但有可能就 CPU 周期而言,这些查询的评估成本可能非常高(与 CSS 选择器相比,CSS 选择器在设计上限制为不允许您执行这些复杂的查询,因为性能受到影响)。所以在这些情况下,你会想要异步使用它;例如,来自工作人员——这样在评估查询时它不会让你的整个 UI 崩溃。

标签: javascript dom xpath document.evaluate


【解决方案1】:

如果你想处理多个结果,不要在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 );

取而代之的是获取文本或倒数,或测试真/假条件

注意among the other values (constants) you can specify as the second-to-last argument to document.evaluate()获取其他结果类型,可以直接返回:

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

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


MDN 上的更多内容

以上示例均基于 MDN Introduction to using XPath in JavaScript 教程,强烈推荐给任何尝试使用 XPath 和 document.evaluate() 的人。

【讨论】:

  • 我猜由于是在过去的时代被人们用 Java 或其他方式编写 DOM 东西所构建的,document.evaluate 和 DOM3 XPath API 的其余部分是一个设计奇特的 bizarro-superman API,它是与 Web 平台的其他 API 不一致。但是,一旦您克服了它的古怪之处并熟悉了它,它就可以完成工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多