preg_replace add target = & quot; _blank & quot ;, но исключить некоторые экземпляры

У меня проблемы с составлением правильного шаблона RegEx, чтобы добавить target = «_ blank» к моим ссылкам. Чтобы добавить это ко всем ссылкам .. нет проблем, но мне нужно исключить определенные экземпляры на основе шаблона.

Это preg_replace (), который я использую для обновления ВСЕХ ссылок с целью, которые показывают http: // в href

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 или же http://example.com (это будет домен, в котором живет код) из целевой обработки, но если ссылка является абсолютной ссылкой или на другой внешний сайт, который НЕ использует domain.com, тогда я хочу этого.

Попытка добавить шаблон исключения / исключения в этом (<a href="http:[^"]+") доставляет мне неприятности

Спасибо!
Hanji

2

Решение

Поскольку это ваш собственный HTML, измените свое регулярное выражение:

/(<a href="http:[^"]+")>/is
| add here a negative lookahead: (?!\/\/(?:www\.)?example\.com)

Так и становится:

/(<a href="http:(?!\/\/(?:www\.)?example\.com)[^"]+")>/is

Тест на regex101.com; Regex FAQ; Regex для разбора HTML

2

Другие решения

Вот способ, который использует 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"))]';
5

По вопросам рекламы [email protected]