2011-05-18 93 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