【问题标题】:Find all text nodes in HTML page [duplicate]查找 HTML 页面中的所有文本节点 [重复]
【发布时间】:2012-05-24 02:22:04
【问题描述】:

对于this question,我需要找到特定节点下的所有文本节点。我可以这样做:

function textNodesUnder(root){
  var textNodes = [];
  addTextNodes(root);
  [].forEach.call(root.querySelectorAll('*'),addTextNodes);
  return textNodes;

  function addTextNodes(el){
    textNodes = textNodes.concat(
      [].filter.call(el.childNodes,function(k){
        return k.nodeType==Node.TEXT_NODE;
      })
    );
  }
}

但是,鉴于使用 XPath 可以简单地查询 .//text() 并完成它,这似乎并不优雅。

在 IE9+、Safari5+、Chrome19+、Firefox12+、Opera11+ 上获取 HTML 文档中特定元素下的所有文本节点的最简单方法是什么?

“最简单”被粗略地定义为“高效且短,无需打高尔夫球”。

【问题讨论】:

  • 噢,混蛋。谢谢,杰克,我确实搜索过,但没有找到那个问题。
  • 是的,我也不知道为什么它也没有出现在侧边栏中,但是我在谷歌搜索时找到了它:)

标签: javascript html


【解决方案1】:

基于@kennebec 的回答,相同逻辑的稍微紧凑的实现:

function textNodesUnder(node){
  var all = [];
  for (node=node.firstChild;node;node=node.nextSibling){
    if (node.nodeType==3) all.push(node);
    else all = all.concat(textNodesUnder(node));
  }
  return all;
}

但是,使用createTreeWalker 更快、更紧凑、更优雅,这样浏览器会为您过滤掉除文本节点之外的所有内容:

function textNodesUnder(el){
  var n, a=[], walk=document.createTreeWalker(el,NodeFilter.SHOW_TEXT,null,false);
  while(n=walk.nextNode()) a.push(n);
  return a;
}

【讨论】:

  • @julmot 在我的计算机上,使用 Chrome v50 查找此页面上的所有文本节点,使用第一种技术需要 1900μs,但使用 TreeWalker 技术需要 220μs。所以,快 8 到 9 倍。
  • 为了排除 <script> 元素的内容,我不得不调整它:gist.github.com/Daniel-Hug/1415b4d027e3e9854456f4e812ea2ce1
  • 如果您使用 TreeWalker 方法并且想要排除 Web_Designer 提到的脚本或样式标签,您可以将过滤器作为第三个参数传递给 createTreeWalker
  • @VinayPai - 警告:filter 仅在 a node that has passed the whatToShow check 上运行,因此在这种情况下,您不能使用方便的 NodeFilter.SHOW_TEXT,而是必须添加额外的逻辑通过nodeType 或其他方式手动过滤文本节点。
  • @Web_Designer - 仍在使用 document.createTreeWalker() 的替代方案:gist.github.com/Sphinxxxx/ed372d176c5c2c1fd9ea1d8d6801989b
【解决方案2】:
function deepText(node){
    var A= [];
    if(node){
        node= node.firstChild;
        while(node!= null){
            if(node.nodeType== 3) A[A.length]=node;
            else A= A.concat(deepText(node));
            node= node.nextSibling;
        }
    }
    return A;
}

【讨论】:

  • 没有!= nullwhile (node) 怎么样?
  • 甚至for (node=node.firstChild;node;node=node.nextSibling){ … }
  • 我担心递归解决方案可能会遇到堆栈限制问题,但I see now that this is unlikely
  • 一旦您知道第一个(父)节点是子节点,node.nextSibling 唯一可能的值就是另一个子节点或 null。
猜你喜欢
  • 2012-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多