2011-05-18 64 views
2

我试图用正则表达式替换HTML内容。替换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匹配开放标签,除了XHTML独立标签](http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags) – Mat 2011-05-18 07:31:32

+1

谢谢你的垫子介绍。阅读链接后,我简化了这个问题,因为我知道HTML将是“常规”类型的HTML。 – iwan 2011-05-18 07:40:50

+1

然后你误读了那个链接。不要使用正则表达式来解析HTML,这太复杂了。使用(X)HTML解析器。 – Mat 2011-05-18 07:42:08

回答

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”(全局)选项可确保替换所有可能的匹配项。

+0

谢谢TAO,你太棒了..如果你有关于正则表达式的简单解释会有帮助,再次感谢... – iwan 2011-05-18 15:21:03

+0

完成,希望有所帮助。如果可能的话,我建议您使用DOM遍历方法,如@ Suor的回答和@Tim Down的评论所述;这种类型的解决方案将始终更可靠。正如@Jens指出的那样,这个答案中的正则表达式解决方案在某些情况下可能会中断。 – Tao 2011-05-18 15:34:30

1

在这种情况下最好的想法是肯定不使用正则表达式来做到这一点。至少不是自己的。 JavaScript肯定有一个HTML解析器的地方?

如果您确实必须使用正则表达式,则可以尝试在任何“>”之前查找ZZZ的后面跟有“<”的每个实例。这看起来像

ZZZ(?=[^>]*<) 

如果代码包含HTML注释或脚本块,或者结构不正确,这可能会崩溃。

+0

是的,这是有道理的 - 无论你想出什么正则表达式 – Tao 2011-05-18 07:40:07

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< 

但要注意在后所有精明的建议链接在首先对你的问题发表评论!

+0

要小心!HTML注释,脚本块或任何其他xhtml CDATA会搞砸!我不是故意的,抱歉...考虑到所有的精明建议.... – sergio 2011-05-18 07:51:09

+0

您好sergio,感谢您的建议,我喜欢你的想法..它几乎可以工作,但并不完美,但它给了我 - - 测试测试AAA ZZZ测试测试< /A > – iwan 2011-05-18 15:09:52

+0

尝试此链接:http://regexr.com?2tpq1,它是基于闪存的正则表达式引擎初始化与我的建议...它似乎工作好吧...你使用“g”标志(全局替换)? – sergio 2011-05-18 15:21:32

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'); 
+0

'textContent'并不普遍支持文本节点。改为使用'nodeValue'或'data'属性。另外,如果传递给字符串的replace()方法的第一个参数是一个字符串,则只会替换该字符串的第一个匹配项。使用具有全局标志的正则表达式(例如'/ ZZZ/g')来代替所有的事件。 – 2011-05-18 08:31:15

+0

嗨苏尔,你的JS函数正在回答我描述的问题。但我只是意识到我简化了实际问题。我需要从ZZZ更改为类似于 AAA,以上功能 - 将标记呈现为”文本“而不是HTML – iwan 2011-05-18 14:25:36

+0

然后,您应该创建该跨度节点并将其插入。做'var html = this.nodeValue.replace(from,to); $(this).replaceWith(html)'而不是简单的nodeValue赋值,它会更棘手,但可能没有jQuery。 – Suor 2011-05-21 05:59:01