Обратный обход DOM с помощью JavaScript - PullRequest
0 голосов
/ 08 марта 2012

Мне любопытно узнать, можно ли искать во всем DOM с помощью регулярного выражения, которое затем может по существу идентифицировать путь, используемый для доступа к соответствующему узлу. Другими словами, я хочу найти все совпадения шаблона, скажем, слова «привет», и из этого я хочу определить его ветвление в DOM или родительском контейнере, по крайней мере.

Применение соответствия регулярному выражению, очевидно, находит совпадения, но не учитывает контекст, в котором они были найдены в DOM. Есть ли способ переопределить это совпадение, чтобы также распечатать или связать местоположение совпадения? Если нет (при условии, что регулярное выражение не будет анализировать дерево DOM таким же образом), есть ли какие-либо предложения для достижения желаемых результатов?

Ответы [ 2 ]

1 голос
/ 08 марта 2012

Вы можете просмотреть документ или какой-либо родительский элемент и проверить каждый текстовый узел, возвращая массив узлов, в которых есть данные, соответствующие вашему тексту поиска.

Это дает вам массив фактических данных.совпадающие узлы, если вы хотите как-то ими манипулировать.

Или, если вы просто хотите прочитать пути к каждому совпадению, вы можете вернуть пути вместо узлов.

Этот примерпринимает три функции - одну для рекурсии дерева, поиска текстовых узлов, одну для отслеживания нисходящего узла от корня и одну для соответствия тексту и возврата пути к его узлу в виде строки.Первые два можно использовать повторно, третий отключить.

document.deepText= function(node, fun){
    var A= [], tem;
    fun= fun || function(n){
        return n
    };
    if(node){
        node= node.firstChild;
        while(node!= null){
            if(node.nodeType== 3){
                tem= fun(node);
                if(tem!= undefined) A[A.length]= tem;
            }
            else A= A.concat(document.deepText(node, fun));
            node= node.nextSibling;
        }
    }
    return A;
}

// возвращает массив родительских элементов

document.descent= function(node, pa){
    var A= [];
    pa= pa || document.documentElement;
    while(node){
        A[A.length]= node;
        if(node== pa) return A.reverse();
        node= node.parentNode;
    }
}

// Этот возвращает массив, содержащий 'paths'каждому подходящему узлу

// почти все потрачено на создание строк для путей

// передаем ему регулярное выражение или строку

function pathstoText(rx, pa){
    pa= pa || document.body;
    if(!(rx instanceof RegExp)) rx= RegExp('\\b'+rx+'\\b', 'g');
    var matches= document.deepText(pa, function(itm){
        if(rx.test(itm.data)){
            return document.descent(itm).map(function(who){
                if(who.nodeType== 3) return '="'+who.data.match(rx)+'"';
                var n= 1, sib= who.previousSibling, tag= who.tagName;
                if(who.id) return tag+'#'+who.id;
                else{
                    while(sib){
                        if(sib.tagName=== tag)++n;
                        sib= sib.previousSibling;
                    }
                    if(n== 1) n= '';
                    else n= '#'+n;
                    return who.tagName+n;
                }
            }).join('> ');
        }
    });
    return matches.join('\n');
}

//Несколько примеров

pathstoText('Help') //finds 'Help' on a button

HTML> BODY> DIV#evalBlock> DIV#evalBar> BUTTON#button_009> ="Help"

pathstoText (/ \ bcamp [\ w] * / ig)

 finds 'Camp,camping,etc on a page
found in 2nd paragraph of div #page3, 
found 2 instances in fifth paragraph on div#page6,
and so on.

HTML> BODY> DIV#bookview> DIV#pagespread> DIV#page3> P#2>= "Camp"
HTML> BODY> DIV#bookview> DIV#pagespread> DIV#page3> P#4>= "camp"
HTML> BODY> DIV#bookview> DIV#pagespread> DIV#page3> P#12>= "camping" 
HTML> BODY> DIV#bookview> DIV#pagespread> DIV#page4> P#3>= "camp"
HTML> BODY> DIV#bookview> DIV#pagespread> DIV#page4> P#7>= "camp"
HTML> BODY> DIV#bookview> DIV#pagespread> DIV#page5> P#3>= "Camp"
HTML> BODY> DIV#bookview> DIV#pagespread> DIV#page5> P#5>= "camp"
HTML> BODY> DIV#bookview> DIV#pagespread> DIV#page5> P#7>= "camp"
HTML> BODY> DIV#bookview> DIV#pagespread> DIV#page6> P#5>= "camp,camp"

// о да -

if(!Array.prototype.map){
    Array.prototype.map= function(fun, scope){
        var T= this, L= T.length, A= Array(L), i= 0;
        if(typeof fun== 'function'){
            while(i< L){
                if(i in T){
                    A[i]= fun.call(scope, T[i], i, T);
                }
                ++i;
            }
            return A;
        }
    }
}
0 голосов
/ 08 марта 2012

Мне любопытно узнать, можно ли выполнить поиск по всему DOM с помощью регулярного выражения, которое затем может по существу идентифицировать путь, используемый для достижения соответствующего узла.

Ну, это теоретически возможно , но очень больно (читай: ты не хочешь этого делать).Вам гораздо лучше использовать парсер для разбора HTML.

...