getElementsByTagName() 等效于 textNodes [英] getElementsByTagName() equivalent for textNodes

查看:37
本文介绍了getElementsByTagName() 等效于 textNodes的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法获取文档中所有 textNode 对象的集合?

getElementsByTagName() 适用于 Elements,但 textNodes 不是 Elements.

更新:我意识到这可以通过遍历 DOM 来实现 - 正如以下许多建议的那样.我知道如何编写一个 DOM-walker 函数来查看文档中的每个节点.我希望有一些浏览器原生的方式来做到这一点.毕竟,我可以通过单个内置调用获取所有 ,但不是所有 textNode ,这有点奇怪.

解决方案

更新:

我已经对这 6 种方法中的每一种进行了 1000 次运行的一些基本性能测试.getElementsByTagName 是最快的,但它做了一半的工作,因为它没有选择所有元素,而是只选择一种特定类型的标签(我认为 p)并盲目假设它的 firstChild 是一个文本元素.它可能没有什么缺陷,但用于演示目的并将其性能与 TreeWalker 进行比较.自己在 jsfiddle 上运行测试以查看结果.

  1. 使用 TreeWalker
  2. 自定义迭代遍历
  3. 自定义递归遍历
  4. Xpath 查询
  5. querySelectorAll
  6. getElementsByTagName

让我们暂时假设有一种方法可以让您本地获取所有 Text 节点.您仍然需要遍历每个结果文本节点并调用 node.nodeValue 来获取实际文本,就像处理任何 DOM 节点一样.所以性能问题不在于遍历文本节点,而是遍历所有非文本节点并检查它们的类型.我认为(根据结果)TreeWalker 的执行速度与 getElementsByTagName 一样快,如果不是更快的话(即使 getElementsByTagName 播放有障碍).

<前>每个测试运行 1000 次.方法 总计 ms 平均 ms--------------------------------------------------文档.树行者 301 0.301迭代遍历器 769 0.769递归遍历器 7352 7.352XPath 查询 1849 1.849querySelectorAll 1725 1.725getElementsByTagName 212 0.212


每种方法的来源:

树行者

function nativeTreeWalker() {var walker = document.createTreeWalker(文档正文,NodeFilter.SHOW_TEXT,空值,错误的);无功节点;var textNodes = [];while(node = walker.nextNode()) {textNodes.push(node.nodeValue);}}

递归树遍历

function customRecursiveTreeWalker() {var 结果 = [];(函数 findTextNodes(当前){for(var i = 0; i < current.childNodes.length; i++) {var child = current.childNodes[i];如果(子节点类型 == 3){result.push(child.nodeValue);}别的 {findTextNodes(child);}}})(document.body);}

迭代树遍历

function customIterativeTreeWalker() {var 结果 = [];var root = document.body;var node = root.childNodes[0];而(节点!= null){if(node.nodeType == 3) {/* 在这里修复了一个错误.谢谢@theazureshadow */结果.推(节点.节点值);}如果(节点.hasChildNodes()){节点 = node.firstChild;}别的 {while(node.nextSibling == null && node != root) {节点 = node.parentNode;}节点 = node.nextSibling;}}}

querySelectorAll

function nativeSelector() {var elements = document.querySelectorAll("body, body *");/* 在这里修复了一个错误.谢谢@theazureshadow */var 结果 = [];var 孩子;for(var i = 0; i 

getElementsByTagName(障碍)

function getElementsByTagName() {var elements = document.getElementsByTagName("p");var 结果 = [];for(var i = 0; i 

XPath

function xpathSelector() {var xpathResult = document.evaluate(//*/文本()",文档,空值,XPathResult.ORDERED_NODE_ITERATOR_TYPE,空值);var 结果 = [], res;while(res = xpathResult.iterateNext()) {结果.推(res.nodeValue);/* 在这里修复了一个错误.谢谢@theazureshadow */}}

此外,您可能会发现此讨论很有帮助 - http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node

Is there any way to get the collection of all textNode objects within a document?

getElementsByTagName() works great for Elements, but textNodes are not Elements.

Update: I realize this can be accomplished by walking the DOM - as many below suggest. I know how to write a DOM-walker function that looks at every node in the document. I was hoping there was some browser-native way to do it. After all it's a little strange that I can get all the <input>s with a single built-in call, but not all textNodes.

解决方案

Update:

I have outlined some basic performance tests for each of these 6 methods over 1000 runs. getElementsByTagName is the fastest but it does a half-assed job, as it does not select all elements, but only one particular type of tag ( i think p) and blindly assumes that its firstChild is a text element. It might be little flawed but its there for demonstration purpose and comparing its performance to TreeWalker. Run the tests yourselves on jsfiddle to see the results.

  1. Using a TreeWalker
  2. Custom Iterative Traversal
  3. Custom Recursive Traversal
  4. Xpath query
  5. querySelectorAll
  6. getElementsByTagName

Let's assume for a moment that there is a method that allows you to get all Text nodes natively. You would still have to traverse each resulting text node and call node.nodeValue to get the actual text as you would do with any DOM Node. So the issue of performance is not with iterating through text nodes, but iterating through all nodes that are not text and checking their type. I would argue (based on the results) that TreeWalker performs just as fast as getElementsByTagName, if not faster (even with getElementsByTagName playing handicapped).

Ran each test 1000 times.

Method                  Total ms        Average ms
--------------------------------------------------
document.TreeWalker          301            0.301
Iterative Traverser          769            0.769
Recursive Traverser         7352            7.352
XPath query                 1849            1.849
querySelectorAll            1725            1.725
getElementsByTagName         212            0.212


Source for each method:

TreeWalker

function nativeTreeWalker() {
    var walker = document.createTreeWalker(
        document.body, 
        NodeFilter.SHOW_TEXT, 
        null, 
        false
    );

    var node;
    var textNodes = [];

    while(node = walker.nextNode()) {
        textNodes.push(node.nodeValue);
    }
}

Recursive Tree Traversal

function customRecursiveTreeWalker() {
    var result = [];

    (function findTextNodes(current) {
        for(var i = 0; i < current.childNodes.length; i++) {
            var child = current.childNodes[i];
            if(child.nodeType == 3) {
                result.push(child.nodeValue);
            }
            else {
                findTextNodes(child);
            }
        }
    })(document.body);
}

Iterative Tree Traversal

function customIterativeTreeWalker() {
    var result = [];
    var root = document.body;

    var node = root.childNodes[0];
    while(node != null) {
        if(node.nodeType == 3) { /* Fixed a bug here. Thanks @theazureshadow */
            result.push(node.nodeValue);
        }

        if(node.hasChildNodes()) {
            node = node.firstChild;
        }
        else {
            while(node.nextSibling == null && node != root) {
                node = node.parentNode;
            }
            node = node.nextSibling;
        }
    }
}

querySelectorAll

function nativeSelector() {
    var elements = document.querySelectorAll("body, body *"); /* Fixed a bug here. Thanks @theazureshadow */
    var results = [];
    var child;
    for(var i = 0; i < elements.length; i++) {
        child = elements[i].childNodes[0];
        if(elements[i].hasChildNodes() && child.nodeType == 3) {
            results.push(child.nodeValue);
        }
    }
}

getElementsByTagName (handicap)

function getElementsByTagName() {
    var elements = document.getElementsByTagName("p");
    var results = [];
    for(var i = 0; i < elements.length; i++) {
        results.push(elements[i].childNodes[0].nodeValue);
    }
}

XPath

function xpathSelector() {
    var xpathResult = document.evaluate(
        "//*/text()", 
        document, 
        null, 
        XPathResult.ORDERED_NODE_ITERATOR_TYPE, 
        null
    );

    var results = [], res;
    while(res = xpathResult.iterateNext()) {
        results.push(res.nodeValue);  /* Fixed a bug here. Thanks @theazureshadow */
    }
}

Also, you might find this discussion helpful - http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node

这篇关于getElementsByTagName() 等效于 textNodes的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆