替换链接标题

时间:2013-07-15 13:20:58

标签: php regex preg-replace

我需要根据以下规则在html页面的属性标题中的每个链接上执行正则表达式:

  1. 该链接等于锚文本。
  2. 该链接具有标题属性。
  3. 我写了这段代码:

    $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个标题属性。为什么这不按预期工作?我该如何解决?

1 个答案:

答案 0 :(得分: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);
}