正则表达式:仅在标记中匹配文本节点

时间:2013-11-25 13:27:56

标签: javascript jquery html regex dom

我一直在制作一个高亮剧本。第一个结果可以在substring selector with jquery?

找到

脚本http://jsfiddle.net/TPg9p/3/

但不幸的是它只适用于简单的字符串。我希望它能够使用包含标签的字符串。

示例:

<li>sample string li span style="color:red" id 
    <span id="toto" style="color:red">color id</span> 
    abcde
</li>

因此,如果用户搜索span,它应仅匹配<li>内部和标记span之前的范围,而不匹配标记span本身。然后匹配的字符串替换为<span class="highlight">span</span>对于属性的其他属性或内容也是如此。应忽略开始标记和结束标记内的任何内容。

因为HTML是关于DOM和节点的。我们可以将此字符串解析为节点,然后只选择要替换它的文本节点吗?

请通过更新上面的jsFiddle来回答。

已更新

Tibos的工作解决方案演示:http://jsfiddle.net/TPg9p/10/

2 个答案:

答案 0 :(得分:1)

免责声明:您应该在此使用HTML解析器而不是regexp。

您正在寻找的正则表达式是:

/span(?=[^>]*<)/

使用示例:

var str = '<li>sample string li span style="color:red" id ' + 
    '<span id="toto" style="color:red">color id</span> ' +
    'abcde' +
    '</li>';
var keyword = 'span';
var regexp = new RegExp(keyword + '(?=[^>]*<)');
str.replace(regexp, '<span class="highlight">$&</span>');

<之前跟着>后,正则表达式与您的单词匹配。

编辑:看看你没有有效的HTML(不是以标签开头,以标签结尾),你可以改变你的正则表达式来检查字符串的结尾而不是开头的字符串。标记:

/span(?=[^>]*(?:<|$))/

DEMO:http://jsfiddle.net/TPg9p/8/

编辑:添加了正则表达式转义:.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') 这个答案简明扼要:Is there a RegExp.escape function in Javascript?

答案 1 :(得分:1)

不要尝试使用正则表达式获取正确的字符串,而只使用textNodes:

$('#submit').click(function () {
    var replacePattern = new RegExp(
        $('#search').val().replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 
        'gi');
    $('#sample').children().addBack().not('.highlight')
      .contents().filter(function() {
        return this.nodeType === 3;
    }).replaceWith(function(){
        return this.data.replace(replacePattern, '<b class="highlight">$&</b>');
    });
});

Demo

说明:首先收集#sample元素及其后代(仅指向,如果使用children();当然也可以使用find(*)元素。然后.highlight元素从该选择中被过滤掉 - 它显然是可选的,但是对于我在已经突出显示的内容中突出显示它没有任何意义。

获得所有元素(待处理)之后,使用.contents()收集所有他们的子项 - 并过滤集合(使用nodeType检查),以便只保留文本节点。最后,您在该集合上运行.replaceWith()

请注意,模式定义位于replaceWith回调函数之外(因为在单击处理期间它基本上应该是一个常量值)。