正则表达式替换HTML内容

3
我是一个有用的助手,可以为您翻译文本。以下是您需要翻译的内容:

我正在尝试使用正则表达式替换HTML内容。

来自:

<A HREF="ZZZ">test test ZZZ<SPAN>ZZZ test test</SPAN></A>

为了

<A HREF="ZZZ">test test AAA<SPAN>AAA test test</SPAN></A>

请注意,仅替换HTML标签外的单词从ZZZ到AAA。 有什么想法吗?非常感谢您的帮助。

2
请阅读此问题的第一个答案:RegEx match open tags except XHTML self-contained tags - Mat
1
感谢Mat的推荐。阅读链接后,我简化了问题,因为我知道HTML将是“常规”类型的HTML。 - iwan
1
那么你误读了那个链接。不要使用正则表达式来解析HTML,它太复杂了。使用一个(X)HTML解析器。 - Mat
5个回答

7
您可以遍历所有节点,在文本节点中替换文本(.nodeType == 3):
类似下面的代码:
element.find('*:contains(ZZZ)').contents().each(function () {
    if (this.nodeType === 3)
        this.nodeValue = this.nodeValue.replace(/ZZZ/g,'AAA')
})

或者不使用jQuery:

function replaceText(element, from, to) {
    for (var child = element.firstChild; child !== null; child = child.nextSibling) {
        if (child.nodeType === 3)
            this.nodeValue = this.nodeValue.replace(from,to)
        else if (child.nodeType === 1)
            replaceText(child, from, to);
    }
}

replaceText(element, /ZZZ/g, 'AAA');

textContent 对于文本节点并不是普遍支持的。请使用 nodeValuedata 属性代替。此外,如果传递给字符串的 replace() 方法的第一个参数是一个字符串,则只会替换该字符串的第一次出现。请改用带有全局标志的正则表达式(例如 /ZZZ/g)来替换所有出现的字符串。 - Tim Down
嗨Suor,你的JS函数回答了我描述的问题。但是我刚意识到我过于简化实际问题了。我需要从ZZZ更改为类似于<span class="highlight>AAA</span>的东西,并且上面的函数--将把<span>标签呈现为“文本”,而不是HTML。 - iwan
然后,您应该创建该span节点并将其插入其中。您可以使用var html = this.nodeValue.replace(from, to); $(this).replaceWith(html)而不是简单的nodeValue赋值。如果没有jQuery,这可能会更棘手,但仍然是可能的。 - Suor

2
在这种情况下,最好的想法肯定不是单独使用正则表达式。至少不只用正则表达式。JavaScript一定有一个HTML解析器吧?
如果您真的必须使用正则表达式,可以尝试查找每个紧随"ZZZ"之后且在任何">"之前的"<"。代码如下:
ZZZ(?=[^>]*<)

这可能会出现严重的问题,如果代码中包含HTML注释或脚本块,或者格式不正确。

没错,这很有道理 - HTML注释,脚本块或任何其他xhtml CDATA都会混淆事情,无论您使用什么正则表达式。 - Tao

0

试试这个:

var str = '<DIV>ZZZ test test</DIV><A HREF="ZZZ">test test ZZZ</A>';
var rpl = str.match(/href=\"(\w*)\"/i)[1];
console.log(str.replace(new RegExp(rpl + "(?=[^>]*<)", "gi"), "XXX"));

0
你尝试过这个吗:
替换:
>([^<>]*)(ZZZ)([^<>]*)<

使用:

>$1AAA$3<

但是要小心第一个评论中链接的帖子中的所有明智建议!


小心!?我不是有意的,对不起...请考虑所有明智的建议... - sergio
嗨Sergio,感谢您的建议,我喜欢您的想法。它几乎可以工作,但还不完美,它给了我--<A HREF="ZZZ"/>测试测试AAA</SPAN>ZZZ测试测试</SPAN></A>。 - iwan
试试这个链接:http://regexr.com?2tpq1,这是一个基于Flash的正则表达式引擎,初始化了我的建议...它似乎可以正常工作...你是否使用了“g”标志(用于全局替换)? - sergio

0

假设有一个格式良好、带有外部/包含标签(如<html>)的HTML文档,我认为最简单的方法是查找><符号:

/(\>[^\>\<]*)ZZZ([^\>\<]*\<)/$1AAA$2/

如果你正在处理可能没有封闭标签的HTML片段,那么情况会变得更加复杂,你需要允许字符串的开头和结尾。
示例JS(抱歉,我错过了标签):
alert('<A HREF="ZZZ">test test ZZZ<SPAN>ZZZ test test</SPAN></A>'.replace(/(\>[^\>\<]*)ZZZ([^\>\<]*\<)/g, "$1AAA$2"));
解释:对于每个以>开头的匹配项:
  • 接着是任意数量的既不是>也不是<的字符:[^\>\<]*
  • 然后是"ZZZ"
  • 接着是任意数量的既不是>也不是<的字符:[^\>\<]*
  • 最后以<结尾:\<

替换为:

  • ZZZ之前的所有内容,用第一个捕获组(括号)标记:$1
  • AAA
  • ZZZ之后的所有内容,用第二个捕获组(括号)标记:$2

使用"g"(全局)选项确保替换所有可能的匹配项。


谢谢TAO,你太棒了。如果你能简要解释一下正则表达式,那就太有帮助了,再次感谢。 - iwan
完成了,希望有所帮助。如果可能的话,我建议您使用DOM遍历方法,正如@Suor的答案和@Tim Down的评论中所概述的那样;这种类型的解决方案始终更可靠。正如@Jens所指出的那样,此答案中的正则表达式解决方案可能会在某些情况下出现问题。 - Tao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接