1

我需要能够解析一些文本并找到标记具有 target="_blank".... 的所有实例,并且对于每个匹配项,添加(例如):此链接在结束标记之前的新窗口中打开。

例如:

前:

<a href="http://any-website-on-the-internet-or-local-path" target="_blank">Go here now</a>

后:

<a href="http://any-website-on-the-internet-or-local-path" target="_blank">Go here now<span>(This link opens in a new window)</span></a>

这是一个 PHP 站点,所以我假设 preg_replace() 将是方法......我只是没有正确编写正则表达式的技能。

提前感谢任何人可以提供的任何帮助。

4

5 回答 5

8

你不应该使用正则表达式来解析 HTML,除非在非常明确和受控的情况下。

相反,请尝试使用内置解析器:

$dom = new DOMDocument();
$dom->loadHTML($your_html_source);
$xpath = new DOMXPath($dom);
$links = $xpath->query("//a[@target='_blank']");
foreach($links as $link) {
    $link->appendChild($dom->createTextNode(" (This link opens in a new window)"));
}
$output = $dom->saveHTML();

或者,如果这是输出到浏览器,你可以只使用 CSS:

a[target='_blank']:after {
    content: ' (This link opens in a new window)';
}
于 2013-04-23T18:52:17.940 回答
1

这将适用于锚标签替换....

$string = str_replace('<a ','<a target="_blank" ',$string);
于 2014-02-25T04:30:04.687 回答
0

@Kolink 是对的,但是有我的 RegExp 版本。

$string = '<p>mess</p><a href="http://google.com.br/" target="blank" class=\"bother\">Google</a><p>mess</p>';
echo preg_replace("/(\<a.*?target=\"blank\".*?>)(.*?)(\<\/a\>)/miU","$1$2(This link opens in a new window)$3",$string);
于 2013-04-23T19:07:02.957 回答
-1

这可以完成工作:

$newText = '<span>(This link opens in a new window)</span>';
$pattern = '~<a\s[^>]*?\btarget\s*=(?:\s*([\'"])_blank\1|_blank\b)[^>]*>[^<]*(?:<(?!/a>)[^<]*)*\K~i';
echo preg_replace($pattern, $newText, $html);

然而,这种直接的字符串方法也可以替换 css 或 javascript 代码中的注释 html 部分、字符串或注释,并最终替换为 javascript 文字正则表达式,这充其量是不需要的,最坏的情况是根本不需要。这就是为什么如果你想避免这些陷阱,你应该使用 DOM 方法。您所要做的就是将一个新节点附加到具有所需属性的每个链接:

$dom = new DOMDocument;
libxml_use_internal_errors(true);
$dom->loadHTML($html);
$xp = new DOMXPath($dom);
$nodeList = $xp->query('//a[@target="_blank"]');

foreach($nodeList as $node) {
    $newNode = dom->createElement('span', '(This link opens in a new window)');
    $node->appendChild($newNode);
}

$html = $dom->saveHTML();

最后,最后一个选择是完全不更改 html 并使用 css:

a[target="_blank"]::after {
    content: " (This link opens in a new window)";
    font-style: italic;
    color: red;
}
于 2013-04-23T20:08:49.560 回答
-2

您将无法编写将评估无限长字符串的正则表达式。我建议:

$h = explode('>', $html);

这将使您有机会像任何其他数组一样遍历它,然后执行以下操作:

foreach($h as $k){
    if(!preg_match('/^<a href=/', $k){
        continue;
        }elseif(!preg_match(/target="_blank")/, $k){
        continue;
        }else{
        $h[$k + 1] .= '(open in new window);
        }
    }
$html = implode('>', $h);

这就是我处理此类问题的方式。当然,我只是把它从我的头顶扔掉了,并且保证可以按原样工作,但是对你的确切逻辑进行一些可能的调整,你就会得到你需要的东西。

于 2013-04-23T18:59:56.650 回答