2009-10-06 32 views
0

我需要一個正則表達式(以PHP的方式工作)用英式英語單詞替換HTML中的美式英語單詞。所以顏色會被顏色,米等等所取代[我知道米也是英式英語單詞,但是我們將使用它的副本將始終指距離單位而不是測量設備]。該模式需要在以下(稍微)的例子準確工作(雖然我有過實際的輸入無法控制這些可能存在):我需要什麼樣的正則表達式?

<span style="color:red">This is the color red</span> 

[不應取代色彩的HTML標籤,但應更換它在句中]

<p>Color: red</p> 

[應更換字]

<p>Tony Brammeter lives 2000 meters from his sister</p> 

[應更換米字,但不是在名稱]

我知道有些情況下替換不會有用(例如,如果他的名字是Tony Meter),但這些情況非常罕見,我們可以在他們出現時處理它們。

回答

5

不應該用正則表達式處理Html/xml,它真的是難以生成一個匹配anything。但是你可以使用內置的dom extension遞歸處理您的字符串:

# Warning: untested code! 
function process($node, $replaceRules) { 
    foreach ($node->children as $childNode) { 
     if ($childNode instanceof DOMTextNode) { 
      $text = pre_replace(
       array_keys(replaceRules), 
       array_values($replaceRules), 
       $childNode->wholeText 
      ); 
      $node->replaceChild($childNode, new DOMTextNode($text)); 
     } else { 
      process($childNode, $replaceRules); 
     } 
    } 
} 
$replaceRules = array(
    '/\bcolor\b/i' => 'colour', 
    '/\bmeter\b/i' => 'metre', 
); 
$doc = new DOMDocument(); 
$doc->loadHtml($htmlString); 
process($doc, $replaceRules); 
$htmlString = $doc->saveHTML(); 
+0

很酷。這似乎運作良好。我必須對代碼進行一些更改才能使其正常工作(DOMTextNode不適用於我,而DOMText則是這樣;交換$ node-> replaceChild等參數),但到目前爲止它看起來工作得很好。唯一的一個小問題是我想在字符串上做這件事,並且使用新的DOMDocument將字符串轉換爲HTML頁面,其中包含doctype和f,並將其封裝在html和body標籤中。我可以使用標準的str_replace等刪除它(或者,有沒有更好的方法,不創建這些呢? – Apemantus

0

您不需要明確使用正則表達式。您可以嘗試str_replace函數,或者如果您需要它不區分大小寫,請使用str_ireplace函數。

例子:

$str = "<p>Color: red</p>"; 
$new_str = str_ireplace ('%color%', 'colour', $str); 

你可以傳遞一個數組所有你想要搜索的內容,而不是字符串的話。

+0

除了我相當肯定會失敗#1和他的例子#3;後者需要邊界檢查(基於PCRE的正則表達式中的\ bword \ b),前者至少需要基本的標記檢查。 – Twisol

4

我覺得你寧願需要一本字典,甚至可能需要一些語法分析才能正確工作,因爲你無法控制輸入。純粹的正則表達式解決方案並不能真正處理這種數據。

所以我建議先想出一個需要替換的單詞列表,這些單詞不僅是「顏色」和「米」。 Wikipedia has some information on the topic

1

你不希望這個正則表達式。正則表達式本質上是無狀態的,並且您需要一些狀態度量來區分「在html標記中」和「在數據中」之間的區別。

您希望將HTML解析器與str_replace之類的東西結合使用,甚至更好地使用正如Lucero所建議的語法字典和內容。

1

第二個問題更簡單 - 當單詞邊界存在單詞邊界時,您想更換: - 這將確保您不會更換Brammeter中的表。

第一個問題更難。您不希望替換HTML實體中的單詞 - 「<」>個字符之間沒有任何內容。所以,你的比賽必須確保你最後一次看到>或沒有,但從來沒有隻是<。這要麼很難,並且需要lookahead/lookbehind assertions的某種組合,或者在正則表達式中根本不可能。

實現狀態機的腳本在這裏工作會更好。