使用JavaScript反转DOM遍历

时间:2012-03-08 15:26:54

标签: javascript regex dom path traversal

我很想知道是否可以使用正则表达式搜索整个DOM,然后可以基本上识别用于到达匹配节点的路径。所以换句话说,我想找到一个模式的所有匹配,让我们说“hello”这个词,并且我希望至少在DOM或容器父中识别它的分支。

应用正则表达式匹配显然会找到匹配项,但忽略了保留在DOM中找到它们的位置的上下文。有没有办法覆盖此匹配以打印或关联匹配的位置?如果不是(假设正则表达式不会以相同的方式解析DOM树),是否有任何建议可以达到预期的结果?

2 个答案:

答案 0 :(得分:1)

您可以浏览文档或某些父元素,并检查每个文本节点, 返回包含与搜索文本匹配的数据的节点数组。

如果你想以某种方式操作它们,它会为你提供一个匹配的实际节点数组。

或者,如果您只想读取每个匹配的路径,则可以返回路径而不是节点。

这个例子有三个函数 - 一个递归树,寻找文本节点, 一个跟踪从根下降的节点, 和一个匹配文本并将路径作为字符串返回到其节点。 前两个是可重复使用的,第三个是一次性的。

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

//这个返回一个数组,其中包含每个匹配节点的“路径”

//几乎所有这些都用于为路径制作字符串

//传递正则表达式或字符串

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

答案 1 :(得分:0)

  

我很想知道是否可以使用正则表达式搜索整个DOM   然后,这可以基本上确定用于到达的路径   匹配节点。

嗯,理论上它是possible,但非常痛苦(读:你不想这样做)。使用解析器解析HTML会好得多。