preg_replace add target ="_ blank",但排除某些实例

han*_*nji 2 php regex html-parsing

我无法将正确的RegEx模式组合到我的链接中添加target ="_ blank".要将其添加到所有链接..没问题,但我需要根据模式排除某些实例.

这是preg_replace()我用来更新目标的所有链接,在href中显示http://

preg_replace('/(<a href="http:[^"]+")>/is','\\1 target="_blank">',$content);
Run Code Online (Sandbox Code Playgroud)

这是我想要获得的场景

link1 /somepage.htm (no target="_blank") Above works
link2 http://www.somesiteexternal.com/ (add target="_blank") Above works
link3 http://www.example.com/somepage.htm (no target="_blank") this is where I'm having a problem.
Run Code Online (Sandbox Code Playgroud)

我想从目标处理中排除http://www.example.comhttp://example.com(这将是代码所在的域),但是如果链接是绝对链接或另一个外部站点那不是使用domain.com然后我想要那个.

试图在此添加排除/异常模式(<a href="http:[^"]+")给我带来麻烦.

谢谢!韩纸

Cas*_*yte 5

以下是使用DOM操作获取所需内容的方法.

$dom = new DOMDocument;
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($dom);

$linkNodeList = $xpath->query('//a[starts-with(@href, "http://")]');

$targetAttr = $dom->createAttribute('target');

foreach($linkNodeList as $linkNode) {
    if (!$linkNode->hasAttribute('target'))
        $linkNode->appendChild($targetAttr);
    $linkNode->setAttribute('target', '_blank');
}

$html = $dom->saveHTML();
Run Code Online (Sandbox Code Playgroud)

注意:由于某种原因,LIBXML _...常量有时没有定义,所以你可以在之前添加它来解决这个问题:

if (!defined('LIBXML_HTML_NOIMPLIED'))
  define('LIBXML_HTML_NOIMPLIED', 8192);
if (!defined('LIBXML_HTML_NODEFDTD'))
  define ('LIBXML_HTML_NODEFDTD', 4);
Run Code Online (Sandbox Code Playgroud)

如果要排除特定域,可以parse_url在foreach循环中使用和添加条件(这是最简单的方法):

$forbidden_host = 'example.com';

foreach($linkNodeList as $linkNode) {
    $host = parse_url($linkNode->getAttribute('href'),  PHP_URL_HOST);
    $host = preg_replace('~\Awww\.~', '', strtolower($host));
    if ($host === $forbidden_host)
        continue;

    if (!$linkNode->hasAttribute('target'))
        $linkNode->appendChild($targetAttr);

    $linkNode->setAttribute('target', '_blank');

}
Run Code Online (Sandbox Code Playgroud)

或者您可以在xpath查询中插入条件:

$query = '//a[starts-with(@href, "http://") and not(starts-with(@href, "http://www.example.com") or starts-with(@href, "http://example.com"))]';
Run Code Online (Sandbox Code Playgroud)