Javascript 如何使用 document.evaluate() 和 XPath 来获取元素列表?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36303869/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 18:54:05  来源:igfitidea点击:

How to use document.evaluate() and XPath to get a list of elements?

javascriptxpath

提问by Abhishek Tripathi

I'm using the document.evaluate()JavaScript method to get an element pointed to by an XPath expression:

我正在使用document.evaluate()JavaScript 方法来获取 XPath 表达式指向的元素:

var element = document.evaluate(
  path,
  document,
  null,
  XPathResult.FIRST_ORDERED_NODE_TYPE,
  null
).singleNodeValue;

But how do I get a list of elements in case the XPath expression points to more than one element on the page?

但是,如果 XPath 表达式指向页面上的多个元素,我如何获取元素列表?

I tried the following code, but it is not working:

我尝试了以下代码,但它不起作用:

var element = document.evaluate(
  path,
  document,
  null,
  XPathResult.ORDERED_NODE_ITERATOR_TYPE,
  null
);

回答by Jenny O'Reilly

I found the following solution in the bookI am currently reading. It says that the code is from the Prototype library.

我在我目前正在阅读的书中找到了以下解决方案。它说代码来自Prototype 库

function getElementsByXPath(xpath, parent)
{
    let results = [];
    let query = document.evaluate(xpath, parent || document,
        null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    for (let i = 0, length = query.snapshotLength; i < length; ++i) {
        results.push(query.snapshotItem(i));
    }
    return results;
}

Use it like this:

像这样使用它:

let items = getElementsByXPath("//*"); // return all elements on the page

回答by kernowcode

From the documentation

从文档

var iterator = document.evaluate('//phoneNumber', documentNode, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null );

try {
  var thisNode = iterator.iterateNext();

  while (thisNode) {
    alert( thisNode.textContent );
    thisNode = iterator.iterateNext();
  } 
}
catch (e) {
  dump( 'Error: Document tree modified during iteration ' + e );
}

回答by ddlab

I was working hard with the same problem some weeks ago. I found out, that the result already represents a list of elements (if any) and one can iterate trough it. I needed to build a jQuery plugin for realize a search of partial or full text strings, which means the inner text of any DOM element like LI or H2. I got the initial understanding on his page : Document.evaluate() | MDN

几周前我正在努力解决同样的问题。我发现,结果已经代表了一个元素列表(如果有的话),并且可以遍历它。我需要构建一个 jQuery 插件来实现对部分或完整文本字符串的搜索,这意味着任何 DOM 元素的内部文本,如 LI 或 H2。我在他的页面上得到了初步的理解:Document.evaluate() | MDN

After some hours I got the plugin running: Search for the word "architecture" only in "p" elements, find partial matching strings ("true" for <p>todays architecture in Europe</p>) instead of matches of entire text (<h2>architecture</h2>).

几个小时后,我让插件运行起来:只在“p”元素中搜索“架构”这个词,找到部分匹配的字符串(“true” for <p>todays architecture in Europe</p>)而不是整个文本的匹配(<h2>architecture</h2>)。

var found = $('div#pagecontent').findtext('architecture','p',true);

Found results are regular jQuery objects, which can be used as usual.

找到的结果是常规的 jQuery 对象,可以照常使用。

found.css({ backgroundColor: 'tomato'});

The example of usage above may be altered like this for search trough entire document and all node types like this (partial results)

上面的使用示例可能会像这样更改以搜索整个文档和所有节点类型(部分结果)

var found = $('body').findtext('architecture','',true);

or only exact matches

或仅完全匹配

var found = $('div#pagecontent').findtext('architecture');

The plugin itself shows a variable "es" which is the plural of a single "e" for "element". And you can see, how the results are iterated, and collected into a bunch of objects with f = f.add($(e))(where "f" stands for "found"). The beginning of the function deals with different conditions, like full or partial search ("c" for condition) and the document range for the search ("d").

插件本身显示了一个变量“es”,它是“元素”的单个“e”的复数形式。你可以看到,结果是如何迭代的,并收集到一堆对象中f = f.add($(e))(其中“f”代表“找到”)。函数的开头处理不同的条件,例如完全或部分搜索(条件为“c”)和搜索的文档范围(“d”)。

It may be optimized whereever needed, may not represent the maximum of possibilities, but it represents my best knowledge at the moment, is running without errors and it may answer your question, hopefully. And here is it:

它可以在任何需要的地方进行优化,可能不代表最大的可能性,但它代表了我目前最好的知识,运行没有错误,它可能会回答你的问题,希望如此。这是它:

(function($) {
    $.fn.findtext = function(s,t,p) {
        var c, d;
        if (!this[0]) d = document.body;
        else d = this[0];
        if (!t || typeof t !== 'string' || t == '') t = '*';
        if (p === true) c = './/'+t+'[contains(text(), "'+s+'")]';
        else c = './/'+t+'[. = "'+s+'"]';
        var es = document.evaluate(c, d, null, XPathResult.ANY_TYPE, null); 
        var e = es.iterateNext();
        var f = false;
        while (e) {
            if (!f) f = $(e);
            else f = f.add($(e));
            e = es.iterateNext();
        }
        return f || $();
    };
})(jQuery);