2014-02-16 54 views
1

我有串HTML標記的文字:用PHP正則表達式轉換HTML標題

<p>Some random text</p> 
<h2>This is a heading</h2> 
<p>More text</p> 

我想將其轉換成類似的東西:

<p>Some random text</p> 
<h2 id="This_is_a_heading">This is a heading</h2> 
<p>More text</p> 

這個簡單的代碼幾乎做的:

$patterns = array('#(<h2>)(.*)(</h2>)#i'); 
$replace = array('<h2 id="\2">\2</h2>'); 
$text = preg_replace($patterns, $replace, $text); 

但我仍然不知道如何與underscores在更換屬性,我結束了這$text

<p>Some random text</p> 
<h2 id="This is a heading">This is a heading</h2> 
<p>More text</p> 

我試圖尋找現在的幾個小時,但沒有運氣。請幫忙。

+1

您最好用html解析器。注意,如果你想在替換上運行另一個替換,你需要preg_replace_callback。 – Jerry

回答

1

使用HTML解析器

這是去解析HTML的推薦方式。除非您確定HTML字符串的格式完全固定,否則正則表達式處理不足,您必須使用HTML解析器。下面是使用DOMDocument類,船舶與PHP的解決方案:

$dom = new DOMDocument; 
$errorState = libxml_use_internal_errors(true); 
$dom->loadHTML($text); 
foreach ($dom->getElementsByTagName('h2') as $tag) { 
    $nodeValue = (string) $tag->nodeValue; 
    $id = str_replace(' ', '_', $nodeValue); 
    $tag->setAttribute('id', $id); 
} 

echo $dom->saveHTML(); 

使用正則表達式

對於一個簡單的替換,DOM解析器可能是矯枉過正。如果你不關心結果的準確性那麼多,那麼你可以用來使用正則表達式來完成任務。請注意,如果標記包含其他屬性或額外的標籤,則這可能會中斷。

在這種情況下,您的preg_replace()將無法​​正常工作,因爲它無法修改反向引用。改爲使用preg_replace_callback()

$text = preg_replace_callback('#(<h2>)(.*)(</h2>)#i', function ($m) { 
    $id = str_replace(' ', '_',$m[2]); 
    return "<h2 id=\"$id\"></h2>"; 
}, $text); 
+0

謝謝,兩個版本完美地工作。 :-) – mocniak

+0

@mocniak:很高興有幫助! (我已經更新了包含更多解釋的答案 - 我希望你覺得它有用:) –