preg_replace 添加 target="_blank",但排除某些实例
preg_replace add target="_blank", but exclude certain instances
我在组合正确的 RegEx 模式以将 target="_blank" 添加到我的 link 时遇到问题。将其添加到所有 links.. 没问题,但我需要根据模式排除某些实例。
这是我用来更新所有 link 的 preg_replace() 目标,在 href
中显示 http://
preg_replace('/(<a href="http:[^"]+")>/is','\1 target="_blank">',$content);
这是我正在尝试获取的场景
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.
我想从目标处理中排除 http://www.example.com or http://example.com(这将是代码所在的域),但是如果 link 是绝对 link 或另一个外部不使用 domain.com 的网站,那么我想要那个。
试图在此 (<a href="http:[^"]+")
中添加 exclude/exception 模式给我带来了麻烦。
谢谢!
汉字
这是使用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();
注意:由于某些原因,LIBXML_...常量有时未定义,因此您可以通过在前面添加来解决问题:
if (!defined('LIBXML_HTML_NOIMPLIED'))
define('LIBXML_HTML_NOIMPLIED', 8192);
if (!defined('LIBXML_HTML_NODEFDTD'))
define ('LIBXML_HTML_NODEFDTD', 4);
如果要排除特定域,可以使用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');
}
或者您可以在 xpath 查询中插入条件:
$query = '//a[starts-with(@href, "http://") and not(starts-with(@href, "http://www.example.com") or starts-with(@href, "http://example.com"))]';
因为这似乎是你自己的 html,请修改你的正则表达式:
/(<a href="http:[^"]+")>/is
| add here a negative lookahead: (?!\/\/(?:www\.)?example\.com)
所以变成:
/(<a href="http:(?!\/\/(?:www\.)?example\.com)[^"]+")>/is
Test at regex101.com; Regex FAQ; Regex to parse HTML
我在组合正确的 RegEx 模式以将 target="_blank" 添加到我的 link 时遇到问题。将其添加到所有 links.. 没问题,但我需要根据模式排除某些实例。
这是我用来更新所有 link 的 preg_replace() 目标,在 href
中显示 http://preg_replace('/(<a href="http:[^"]+")>/is','\1 target="_blank">',$content);
这是我正在尝试获取的场景
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.
我想从目标处理中排除 http://www.example.com or http://example.com(这将是代码所在的域),但是如果 link 是绝对 link 或另一个外部不使用 domain.com 的网站,那么我想要那个。
试图在此 (<a href="http:[^"]+")
中添加 exclude/exception 模式给我带来了麻烦。
谢谢! 汉字
这是使用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();
注意:由于某些原因,LIBXML_...常量有时未定义,因此您可以通过在前面添加来解决问题:
if (!defined('LIBXML_HTML_NOIMPLIED'))
define('LIBXML_HTML_NOIMPLIED', 8192);
if (!defined('LIBXML_HTML_NODEFDTD'))
define ('LIBXML_HTML_NODEFDTD', 4);
如果要排除特定域,可以使用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');
}
或者您可以在 xpath 查询中插入条件:
$query = '//a[starts-with(@href, "http://") and not(starts-with(@href, "http://www.example.com") or starts-with(@href, "http://example.com"))]';
因为这似乎是你自己的 html,请修改你的正则表达式:
/(<a href="http:[^"]+")>/is
| add here a negative lookahead: (?!\/\/(?:www\.)?example\.com)
所以变成:
/(<a href="http:(?!\/\/(?:www\.)?example\.com)[^"]+")>/is
Test at regex101.com; Regex FAQ; Regex to parse HTML