【问题标题】:In JavaScript, how can I replace text in an HTML page without affecting the tags?在 JavaScript 中,如何在不影响标签的情况下替换 HTML 页面中的文本?
【发布时间】:2010-11-29 11:41:34
【问题描述】:

我试图弄清楚如何用 Javascript 进行替换。我正在查看页面的整个正文,并想替换 H​​TML 标记中不匹配的关键字。

这是一个例子:

<body>
  <span id="keyword">blah</span>
  <div>
    blah blah keyword blah<br />
    whatever keyword whatever
  </div>
</body>

<script type="text/javascript">
var replace_terms = {
  'keyword':{'url':'http://en.wikipedia.org/','target':'_blank'}
}

jQuery.each(replace_terms, function(i, val) {
  var re = new RegExp(i, "gi");
  $('body').html(
    $('body').html().replace(re, '<a href="'+ val['url'] +'" target="'+val['target']+'">' + i + '</a>')
  );
});

</script>

我希望替换不在 HTML 标记内(&lt;&gt; 之间)的所有“关键字”实例。

如果“关键字”在 scriptstyle 元素内,我想我也需要忽略。

【问题讨论】:

  • 根据定义,整个页面不是在 HTML 标记内吗?
  • 是的。我在示例中的 HTML 没有通过。我的意思是我不想替换标签的任何属性。
  • 我认为他的意思是在括号内(如属性名称/值)。
  • 在标签中是在之间。在 和 > 之间将在一个元素中:)

标签: javascript regex dom


【解决方案1】:

不要使用正则表达式来解析 HTML。 [X][HT]ML 不是常规语言,无法可靠地使用正则表达式进行处理。你的浏览器内置了一个很好的 HTML 解析器;让它承担计算标签所在位置的压力。

你也不想在 body 上处理 html()/innerHTML。这将序列化并重新解析整个页面,这会很慢并且会丢失任何无法在 HTML 中序列化的信息,例如事件处理程序、表单值和其他 JavaScript 引用。

这是一种似乎对我有用的使用 DOM 的方法:

function replaceInElement(element, find, replace) {
    // iterate over child nodes in reverse, as replacement may increase
    // length of child node list.
    for (var i= element.childNodes.length; i-->0;) {
        var child= element.childNodes[i];
        if (child.nodeType==1) { // ELEMENT_NODE
            var tag= child.nodeName.toLowerCase();
            if (tag!='style' && tag!='script') // special case, don't touch CDATA elements
                replaceInElement(child, find, replace);
        } else if (child.nodeType==3) { // TEXT_NODE
            replaceInText(child, find, replace);
        }
    }
}
function replaceInText(text, find, replace) {
    var match;
    var matches= [];
    while (match= find.exec(text.data))
        matches.push(match);
    for (var i= matches.length; i-->0;) {
        match= matches[i];
        text.splitText(match.index);
        text.nextSibling.splitText(match[0].length);
        text.parentNode.replaceChild(replace(match), text.nextSibling);
    }
}

// keywords to match. This *must* be a 'g'lobal regexp or it'll fail bad
var find= /\b(keyword|whatever)\b/gi;

// replace matched strings with wiki links
replaceInElement(document.body, find, function(match) {
    var link= document.createElement('a');
    link.href= 'http://en.wikipedia.org/wiki/'+match[0];
    link.appendChild(document.createTextNode(match[0]));
    return link;
});

【讨论】:

  • i--&gt;0 聪明。我以前从未见过。
  • 我不能为此而自豪,这是在类 C 语言中进行反向迭代的习惯用法! :-)
  • 我通常只使用i--,如:for (var i=100; i--; )
  • 是的,这也适用于下限 0。明确的 &gt;0 也是一种防御措施,用于 i 可能开始为负数(这将无限循环)的情况。
  • 我喜欢i--&gt;0 的地方在于,我首先将它读作 i→0 或“i 接近零”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-16
  • 2020-02-26
  • 1970-01-01
  • 2011-08-18
  • 2021-08-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多