【问题标题】:How to use document.evaluate() and XPath to get a list of elements?如何使用 document.evaluate() 和 XPath 获取元素列表?
【发布时间】:2021-03-05 02:19:55
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 你读过这个吗? developer.mozilla.org/en-US/docs/…如果您无法解决该文档的问题,请显示您当前的代码。
  • 我会经历这个! @Quasimodo'sclone
  • 你能解决这个问题吗?
  • 是的,我解决了@Yoiku!

标签: javascript xpath


【解决方案1】:

在 Chrome 中,有一个更简单的解决方案,在this document 中描述,至少在控制台中:

$x(path)

它与上面的getElementsByXPath 功能相同,但更容易调试。

【讨论】:

    【解决方案2】:

    试试这个:

    function getListOfElementsByXPath(xpath) {
        var result = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null);
        return result;
    }
    

    然后调用它:

    var results = getListOfElementsByXPath("//YOUR_XPATH");
    while (node = results.iterateNext()) {
         console.log(node);
    }
    

    【讨论】:

      【解决方案3】:

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

      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;
      }
      

      像这样使用它:

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

      【讨论】:

      • 无法从“XPathResult”读取“snapshotLength”属性:结果类型不是快照。
      • 嗯..我第一次尝试使用它。看起来我得到了相同的“结果类型不是快照”,无论是文档、浏览器还是查询(一个简单的://div)。 resultType 始终为 4,无法获取快照。
      • 好的,我明白了(来自 Community Ans,down below)。结果是一个迭代器。
      【解决方案4】:

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

      几个小时后,我运行了插件:仅在“p”元素中搜索单词“architecture”,找到部分匹配的字符串(&lt;p&gt;todays architecture in Europe&lt;/p&gt; 的“true”)而不是整个文本的匹配项(&lt;h2&gt;architecture&lt;/h2&gt;) .

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

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

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

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

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

      或仅完全匹配

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

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

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

      (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);
      

      【讨论】:

        【解决方案5】:

        来自文档

        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 );
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-15
          • 2012-04-23
          • 2015-09-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多