我需要根据以下规则在html页面的属性标题中的每个链接上执行正则表达式:
我写了这段代码:
$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个标题属性。为什么这不按预期工作?我该如何解决?
答案 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);
}