php - Regex/DOMDocument - 匹配和替换不在链接中的文本

标签 php regex xpath preg-replace domdocument

我需要以不区分大小写的方式查找并替换所有文本匹配,除非文本位于 anchor 标记内 - 例如:

<p>Match this text and replace it</p>
<p>Don't <a href="/">match this text</a></p>
<p>We still need to match this text and replace it</p>

搜索“匹配此文本”只会替换第一个实例和最后一个实例。

[编辑] 根据 Gordon 的评论,在这种情况下最好使用 DOMDocument。我对 DOMDocument 扩展一点也不熟悉,并且非常感谢此功能的一些基本示例。

最佳答案

这是一个 UTF-8 安全解决方案,它不仅适用于格式正确的文档,还适用于文档片段。

需要 mb_convert_encoding,因为 loadHtml() 似乎在 UTF-8 编码方面存在错误(请参阅 herehere )。

mb_substr 正在从输出中修剪正文标记,这样您就可以恢复原始内容,而无需任何其他标记。

<?php
$html = '<p>Match this text and replace it</p>
<p>Don\'t <a href="/">match this text</a></p>
<p>We still need to match this text and replace itŐŰ</p>
<p>This is <a href="#">a link <span>with <strong>don\'t match this text</strong> content</span></a></p>';

$dom = new DOMDocument();
// loadXml needs properly formatted documents, so it's better to use loadHtml, but it needs a hack to properly handle UTF-8 encoding
$dom->loadHtml(mb_convert_encoding($html, 'HTML-ENTITIES', "UTF-8"));

$xpath = new DOMXPath($dom);

foreach($xpath->query('//text()[not(ancestor::a)]') as $node)
{
    $replaced = str_ireplace('match this text', 'MATCH', $node->wholeText);
    $newNode  = $dom->createDocumentFragment();
    $newNode->appendXML($replaced);
    $node->parentNode->replaceChild($newNode, $node);
}

// get only the body tag with its contents, then trim the body tag itself to get only the original content
echo mb_substr($dom->saveXML($xpath->query('//body')->item(0)), 6, -7, "UTF-8");

引用文献:
1. find and replace keywords by hyperlinks in an html fragment, via php dom
2. Regex / DOMDocument - match and replace text not in a link
3. php problem with russian language
4. Why Does DOM Change Encoding?

我阅读了该主题的数十个答案,因此,如果我忘记了某人,我很抱歉(请发表评论,在这种情况下我也会添加您的答案)。

感谢 Gordon 和 stillstand 对 my other answer 发表评论.

关于php - Regex/DOMDocument - 匹配和替换不在链接中的文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4044812/

相关文章:

php - 在数据库中搜索字符串是否存在(php、mysql)

php - 如何将 Unicode 转义序列转换为 PHP 中的文本?

angularjs - 选择 ng-repeat 复选框 Selenium

xpath - HtmlAgilityPack,使用 XPath 包含方法和谓词

xpath - Selenium IDE 和 xpath - 在表中查找文本/行并选择单选框

javascript - onclick模态按钮调用php函数

IPv6 的 PHP preg_match 问题

regex - 如何在XSLT 1.0中使用正则表达式?

java - 正则表达式 YouTube IFRAME

php - 递归正则表达式中的 If-else 未按预期工作