2013-07-15 53 views
0

我需要在我的html页面的属性称号执行的每一个环节上的正则表达式,基于以下规则:更换链接标题

  1. 链接等于锚文本。
  2. 链接确实不是有标题属性。

我写了这个代码:

$x = 'gg <a href="#">Anchor 1</a>, <a href="#" title="text">Anchor 2</a>'; 
echo preg_replace('/\<a([^<]*)(?!title)>([^<]+)\<\/a/isu', '<a${1} title="${2}">${2}</a', $x); 

但我得到这个意外结果:

gg <a href="#" title="Anchor 1">Anchor 1</a>, <a href="#" title="text" title="Anchor 2">Anchor 2</a> 

第二个环节有2个title属性。为什么这不按预期工作?我该如何解决它?

+0

使用html dom解析器来执行此操作,而不是正则表达式 – DevZer0

+0

lookahead断言''!'不掩盖'[^ <] *'占位符。这只是你放置它的地方。 – mario

+0

[添加一个nofollow属性来链接,如果没有使用PHP标题标记](http://stackoverflow.com/questions/6160645/add-a-nofollow-attribute-to-link-if-no-title-使用php) – mario

回答

1

在你的表达:

<a([^<]*) 

这一路匹配到下一个开括号,而是由>在表达进一步下降停止;在此期间它跳过了(?!title)

这就是说,这个问题最好在HTML域而不是文本域表示:

$contents = <<<'EOS' 
gg <a href="#">Anchor 1</a>, <a href="#" title="text">Anchor 2</a> 
EOS; 

$doc = new DOMDocument; 
$doc->loadHTML($contents); 
// find all anchors 
foreach ($doc->getElementsByTagName('a') as $anchor) { 
     if (!$anchor->hasAttribute('title')) { 
       $anchor->setAttribute('title', $anchor->textContent); 
     } 
} 

echo $doc->saveHTML(); 

仅保存你感兴趣的节点中,你将不得不使用这种结构的:

foreach ($doc->getElementsByTagName('p')->item(0)->childNodes as $childNode) { 
     echo $doc->saveHTML($childNode); 
} 
+0

这很好,thx,但DOMDocument添加doctype和html标签,但我需要修改partials html块 – gvozd1989

+0

@ gvozd1989我也给出了一个解决方案。 –

+0

谢谢!是工作。 – gvozd1989