我实际上已经在这里看到了这个问题,但它们都不是我想要的......让我说我有以下这句话:
Line 1 - This is a TEST phrase.
Line 2 - This is a <img src="TEST" /> image.
Line 3 - This is a <a href="somelink/TEST">TEST</a> link.
好的,简单吧?我正在尝试以下代码:
$linkPin = '#(\b)TEST(\b)(?![^<]*>)#i';
$linkRpl = '$1<a href="newurl">TEST</a>$2';
$html = preg_replace($linkPin, $linkRpl, $html);
正如您所看到的,它需要单词TEST,并将其替换为要测试的链接。我现在正在使用的正则表达式很好,以避免替换第2行中的TEST,它也避免替换第3行的href中的TEST。但是,它仍然替换第3行中标记中封装的文本,我最终用:
Line 1 - This is a <a href="newurl">TEST</a> phrase.
Line 2 - This is a <img src="TEST" /> image.
Line 3 - This is a <a href="somelink/TEST"><a href="newurl">TEST</a></a> link.
我不想这样做,因为它在第3行中创建了错误的代码。我不仅要忽略标记内部的匹配,还要封装它们。 (记得要记下第2行中的/&gt;)
答案 0 :(得分:1)
老实说,我会使用DomDocument和Xpath执行此操作:
//First, create a simple html string around the text.
$html = '<html><body><div id="#content">'.$text.'</div></body></html>';
$dom = new DomDocument();
$dom->loadHtml($html);
$xpath = new DomXpath($dom);
$query = '//*[not(name() = "a") and contains(., "TEST")]';
$nodes = $xpath->query($query);
//Force it to an array to break the reference so iterating works properly
$nodes = iterator_to_array($nodes);
$replaceNode = function ($node) {
$text = $node->wholeText;
$text = str_replace('TEST', '<a href="TEST">TEST</a>', '');
$fragment = $node->ownerDocument->createDocumentFragment();
$fragment->appendXML($text);
$node->parentNode->replaceChild($fragment, $node);
}
foreach ($nodes as $node) {
if ($node instanceof DomText) {
$replaceNode($node, 'TEST');
} else {
foreach ($node->childNodes as $child) {
if ($child instanceof DomText) {
$replaceNode($node, 'TEST');
}
}
}
}
这应该对你有用,因为它会忽略a
个元素中的所有文本,并且只会直接替换匹配标记内的文本。
答案 1 :(得分:0)
好的......我想我想出了一个更好的解决方案......
$noMatch = '(</a>|</h\d+>)';
$linkUrl = 'http://www.test.com/test/'.$link['page_slug'];
$linkPin = '#(?!(?:[^<]+>|[^>]+'.$noMatch.'))\b'.preg_quote($link['page_name']).'\b#i';
$linkRpl = '<a href="'.$linkUrl.'">'.$link['page_name'].'</a>';
$page['HTML'] = preg_replace($linkPin, $linkRpl, $page['HTML']);
使用此代码,它不会处理<a>
代码和<h#>
代码中的任何文字。我想,我想添加任何新的排除项,只需要添加到$ noMatch。
这种方法我错了吗?