【问题标题】:Reverse DOM traversing with JavaScript使用 JavaScript 反向遍历 DOM
【发布时间】:2012-03-26 01:59:12
【问题描述】:

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

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

【问题讨论】:

  • 正则表达式在这里没有帮助。如果没有成熟的 HTML 解析器,您如何知道“hello”是否在元素、属性...注释...是否是元素名称本身...?在这种情况下,任何你想用正则表达式做的事情,你都可以使用indexOf。除此之外的任何事情,我都不相信正则表达式可以处理。
  • (在此处插入指向stackoverflow.com/q/1732348/319403 的必填链接。)

标签: javascript regex dom path traversal


【解决方案1】:

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

嗯,理论上是possible,但非常痛苦(阅读:你不想那样做)。你最好使用解析器来解析 HTML。

【讨论】:

  • 假设这一切都在 JavaScript 中完成,听起来事情会变得有点麻烦。是时候翻阅书籍以确定值得使用的东西了。
  • @user1257332,就用JS中可用的DOM搜索文本节点?
【解决方案2】:

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

如果您想以某种方式操作它们,这将为您提供匹配的实际节点数组。

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    • 2015-02-08
    • 2010-09-21
    • 2021-08-26
    相关资源
    最近更新 更多