getElementsByTagName () эквивалентный для textNodes

Есть ли любой способ получить набор всех textNode объекты в рамках документа?

getElementsByTagName() работает отлично для Элементов, но textNodes не являются Элементы.

Обновление: Я понимаю, что это может быть выполнено путем обхода DOM - как многие ниже предполагают. Я знаю, как записать функцию DOM-walker, которая смотрит на каждый узел в документе. Я надеялся, что был некоторый собственный браузером способ сделать это. В конце концов, немного странно, что я могу добраться весь <input>s с единственным встроенным вызовом, но не всеми textNodes.

73
задан levik 5 April 2010 в 21:57
поделиться

2 ответа

Обновление :

Я обрисовал в общих чертах некоторые базовые тесты производительности для каждого из этих 6 методов за 1000 запусков. getElementsByTagName - самый быстрый, но он выполняет половинчатую работу, так как он выбирает не все элементы, а только один конкретный тип тега (я думаю, p ) и слепо предполагает, что его firstChild - это текстовый элемент. Возможно, он немного ошибочен, но он предназначен для демонстрации и сравнения его производительности с TreeWalker . Запустите тесты на jsfiddle , чтобы увидеть результаты.

  1. Использование TreeWalker
  2. Пользовательский итеративный обход
  3. Пользовательский рекурсивный обход
  4. Запрос Xpath
  5. querySelectorAll
  6. getElementsByTagName

Предположим на мгновение, что существует метод, позволяющий получить все Текстовые узлы изначально. Вам все равно придется пройти по каждому результирующему текстовому узлу и вызвать узел .nodeValue , чтобы получить фактический текст, как если бы вы делали это с любым узлом DOM. Таким образом, проблема производительности заключается не в переборе текстовых узлов, а в переборе всех узлов, не являющихся текстовыми, и проверке их типа. Я бы сказал (основываясь на результатах), что TreeWalker работает так же быстро, как getElementsByTagName , если не быстрее (даже с затрудненной игрой getElementsByTagName).

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

Источник для каждого метода:

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

Рекурсивный обход дерева

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

Итерационный обход дерева

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 (гандикап)

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 */
    }
}

Также вы можете найти это обсуждение полезно - http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node

109
ответ дан 24 November 2019 в 12:21
поделиться
 document.deepText= function(hoo, fun){
        var A= [], tem;
        if(hoo){
            hoo= hoo.firstChild;
            while(hoo!= null){
                if(hoo.nodeType== 3){
                    if(typeof fun== 'function'){
                        tem= fun(hoo);
                        if(tem!= undefined) A[A.length]= tem;
                    }
                    else A[A.length]= hoo;
                }
                else A= A.concat(document.deepText(hoo, fun));
                hoo= hoo.nextSibling;
            }
        }
        return A;
    }

/* Вы можете вернуть массив всех потомков текстовых узлов некоторого родительского элемента, или вы можете передать ему некоторую функцию и сделать что-то (найти или заменить или что-то еще) с текстом на месте.

Этот пример возвращает текст не пробельных текстовых узлов в теле:

var A= document.deepText(document.body, function(t){
    var tem= t.data;
    return /\S/.test(tem)? tem: undefined;
});
alert(A.join('\n'))

*/

Удобно для поиска и замены, выделения и т.д.

1
ответ дан 24 November 2019 в 12:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: