Searching the DOM for multiples of the same string, using XPath

会有一股神秘感。 提交于 2020-01-23 01:01:28

问题


I'm writing a Chrome extension that will search the DOM and highlight all email addresses on the page. I found this to look for at symbols on the page but it only returns correctly when there is one email address, it breaks when there are multiple addresses found.

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

What is the correct way to have this return multiples if more than one is found?


回答1:


If you want to handle multiple results, don’t call .snapshotItem(0) on document.evaluate() but instead loop through the results using a for loop and snapshotLength():

Example: Loop through results using snapshotLength() with 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) );
}

Either that, or specify the XPathResult.UNORDERED_NODE_ITERATOR_TYPE argument (instead of XPathResult.ORDERED_NODE_SNAPSHOT_TYPE), and use a while loop with iterateNext():

Example: Iterate over results using 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 );
}

In cases that are sorta the reverse of the one in this question—cases when you really do just want to get the first matching node—you can specify the XPathResult.FIRST_ORDERED_NODE_TYPE value, to return just a single node, and then use the property (not method) singleNodeValue:

Example: Use XPathResult.FIRST_ORDERED_NODE_TYPE and singleNodeValue
var firstMatchingNode = document.evaluate('// [contains(text(),"@")]',
    document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null );

console.dir( firstMatchingNode.singleNodeValue );

Getting text or counts back instead, or testing true/false conditions

Note that among the other values (constants) you can specify as the second-to-last argument to document.evaluate() to get other results types, you can make it directly return:

  • a single string (XPathResult.STRING_TYPE) of text slurped from some part of the document
  • a number representing a count of some kind (XPathResult.NUMBER_TYPE); for example, a count of the number of e-mail addresses found in the document
  • a boolean value (XPathResult.BOOLEAN_TYPE) representing some true/false aspect of the document; e.g., an indicator whether or not the document contains any e-mail addresses

Of course to get those other result types back, the XPath expression you give as the first argument to document.evaluate() needs to be an expression that will actually return a string, or a number, or a boolean value (instead of returning a set of attribute nodes or element nodes).


More at MDN

The examples above are all based on the MDN Introduction to using XPath in JavaScript tutorial, which is highly recommended to anybody trying to work with XPath and document.evaluate().



来源:https://stackoverflow.com/questions/32467897/searching-the-dom-for-multiples-of-the-same-string-using-xpath

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!