正则表达式,避免PHP中的HTML标记

时间:2011-01-11 14:52:01

标签: php html regex

我实际上已经在这里看到了这个问题,但它们都不是我想要的......让我说我有以下这句话:

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;)

2 个答案:

答案 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。

这种方法我错了吗?