2011-12-02 67 views
0

對於正則表達式我還是比較新的,並且覺得我的代碼太貪婪。我正在嘗試爲一段代碼中的現有鏈接添加一個id屬性。我的功能是這樣的:將id屬性添加到通過PHP正則表達式的超鏈接

function addClassHref($str) { 
//$str = stripslashes($str); 
$preg = "/<[\s]*a[\s]*href=[\s]*[\"\']?([\w.-]*)[\"\']?[^>]*>(.*?)<\/a>/i"; 
preg_match_all($preg, $str, $match); 
foreach ($match[1] as $key => $val) { 
    $pattern[] = '/' . preg_quote($match[0][$key], '/') . '/'; 
    $replace[] = "<a id='buttonRed' href='$val'>{$match[2][$key]}</a>"; 
} 
return preg_replace($pattern, $replace, $str); 
} 

這增加了我想要的id標籤,但它打破了超鏈接。例如:

如果原來的代碼是:<a href="http://www.google.com">Link</a>

而不是<a id="class" href="http://www.google.com">Link</a>

這是給 <a id="class" href="http">Link</a>

任何建議或想法?

+0

'id'屬性必須是唯一的。你應該使用['preg_replace_callback'](http://php.net/preg_replace_callback)而不是首先匹配,然後使用['preg_replace'](http://php.net/preg_replace)。 – mario

+0

你沒有要求它,而對於輸出修改它通常是愚蠢的,所以評論:沒有正則表達式,這將更簡單,例如QueryPath'htmlqp($ html) - > find(「a」)FOREACH attr(「id」,「buttonRed」。($ i ++));' – mario

回答

1

你已經有了一些overcomplications在你的正則表達式:)

而且,沒有必要對環路preg_replace()將達到搜索模式的所有實例相關的字符串中。下面的第一個正則表達式將採用標籤中的所有內容,並在最後添加id屬性。

$str = '<a href="http://www.google.com">Link</a>' . "\n" . 
'<a href="http://www.yahoo.com">Link</a>' . "\n" . 
'<a href="http://www.microsoft.com">Link</a>'; 

$p = "{<\s*a\s*(href=[^>]*)>([^<]*)</a>}i"; 
$r = "<a $1 id=\"class\">$2</a>"; 

echo preg_replace($p, $r, $str); 

如果你只是想捕捉的HREF屬性,你可以做到以下幾點:

$p = '{<\s*a\s*href=["\']([^"\']*)["\'][^>]*>([^<]*)</a>}i'; 
$r = "<a href='$1' id='class'>$2</a>"; 
+0

這是行得通的,但不會影響其他標籤。例如,如果target =「_ blank」被設置。它仍會達到相同的結果嗎?這些是用戶生成的鏈接,如果設置了目標,我想確保它不受影響。 – wiseman7687

+0

正則表達式將a *標籤中的*所有*都添加到標籤中,並簡單地添加id =「class」屬性。你正在尋找*僅*捕獲href屬性? – rdlowrey

+0

澄清我想離開鏈接ALONE,但添加id屬性被設置爲所請求的字符串中的每個鏈接上的類。 – wiseman7687

2

不要使用正則表達式解析XML或HTML。

$doc = new DOMDocument(); 
$doc->loadHTML($html); 
$all_a = $doc->getElementsByTagName('a'); 
$firsta = $all_a->item(0); 
$firsta->setAttribute('id', 'idvalue'); 
echo $doc->saveHTML($firsta); 
+0

+1雖然可能不需要這個特定的任務,但DOM解析通常是DOM修改的最佳選擇 - 特別是代替正則表達式。 – Wiseguy

1

你的第一個子模式([\w.-]*)不匹配:,因而它停在 「HTTP」。

難道你不能只用一個簡單的str_replace()這個?如果這是你所做的一切,那麼正則表達式看起來好像過火了。

$str = str_replace('<a ', '<a id="someID" ', $str); 
+0

問題是這些是用戶生成的鏈接。例如,如果他們設置target =「_ blank」,它會被單獨留下嗎?我對preg_match相對比較陌生,但我想確保腳本不會被我猜得太過分,而只是取代每一次完全匹配? – wiseman7687

+0

@ wiseman7687是的,在我上面的例子中,你只會影響' Wiseguy