Php preg_替换忽略图像标记
我有下面的regexp,其中我搜索一个尚未链接的特定单词,并添加链接Php preg_替换忽略图像标记,php,regex,preg-replace,Php,Regex,Preg Replace,我有下面的regexp,其中我搜索一个尚未链接的特定单词,并添加链接 foreach($_MY_LINKS as $_word=>$_link) { $_link = "/{$lang}/$_link"; str_replace("//","/",$_link); $search = "/(\b$_word\b)(?!
foreach($_MY_LINKS as $_word=>$_link)
{
$_link = "/{$lang}/$_link";
str_replace("//","/",$_link);
$search = "/(\b$_word\b)(?!(.*)<\/a>)/mu";
$re_link = '<a href="'.$_link.'">$1</a>';
$page_content = preg_replace($search, $re_link, $page_content);
}
foreach($\u我的链接为$\u word=>$\u链接)
{
$\u link=“/{$lang}/$\u link”;
str_替换(“//”、“/”、$\u链接);
$search=“/(\b$\u word\b)(?!(.*)/mu”;
$re_link='';
$page\u content=preg\u replace($search、$re\u link、$page\u content);
}
它可以很好地处理纯文本
我的问题是,如果我有带图像标签的富文本,并且我试图添加链接的单词在图像alt中,它会替换这个单词,我不希望这样
<img src="myimage.jpg" alt="word">
变成
<img src="myimage.jpg" alt="<a href="mylink">word</a>">
所以我假设我必须从我的规则中排除img标签,但我不知道怎么做
感谢您的帮助您不应该只使用正则表达式。要修改HTML,请使用HTML解析器。这允许您直接匹配文本节点-避免对其他节点(如属性)进行修改 Xpath表达式
//text()[not(祖先::a)]
匹配文档中没有a
祖先元素的任何文本节点,因此任何不是链接的文本都已匹配。它可以变得更加具体,比如//body//text()[not(祖先::a)和not(祖先::脚本)]
在下一步中,使用搜索字符串将文本节点的内容拆分为多个部分。字符串应按长度排序(最长优先)PREG_SPLIT_DELIM_CAPTURE
确保返回的列表也包含搜索字符串
现在,文本节点的替换片段是build。文档片段是一个节点列表,可以像DOM方法中的节点一样使用。调用DOMNode::replaceChild
将用片段中的所有节点替换目标节点
迭代分割动作a
中的部分,为任何搜索词添加元素。其他部分作为文本节点添加
文本内容示例:在searchword之后
- 文本节点:
之前
- 元素节点:
a
带有文本内容searchword
- 文本节点:
之后
以下是一个工作示例:
$html = <<<'HTML'
<html>
<body>
<div>foo</div>
<div>foo bar</div>
<a href="#">foo bar</a>
<img alt="foo bar"/>
</body>
</html>
HTML;
// bootstrap html
$document = new DOMDocument();
$document->loadHTML($html);
$xpath = new DOMXpath($document);
$searchFor = [
'bar' => 'linkOne.html',
'foo' => 'linkTwo.html'
];
// compile words into a pcre pattern
$pattern = '((\b'.
implode(
'|',
array_map(
fn($value) => preg_quote($value),
array_keys($searchFor)
)
).'\b))';
// iterate text nodes not inside an "a" element
foreach ($xpath->evaluate('//text()[not(ancestor::a)]') as $text) {
// split text at search words
$parts = preg_split($pattern, $text->textContent, -1, PREG_SPLIT_DELIM_CAPTURE);
$fragment = $document->createDocumentFragment();
$modified = FALSE;
foreach ($parts as $part) {
// if it is a search word
if ($href = $searchFor[$part] ?? false) {
// add link
$fragment->appendChild(
$a = $document->createElement('a')
);
$a->setAttribute('href', $href);
$a->textContent = $part;
$modified = TRUE;
} else {
// add text
$fragment->appendChild(
$document->createTextNode($part)
);
}
}
if ($modified) {
// replace original text node with new node list
$text->parentNode->replaceChild($fragment, $text);
}
}
echo $document->saveHTML();
$html='linkTwo.html'
];
//将单词编译成pcre模式
$pattern='(\b'。
内爆(
'|',
数组映射(
fn($value)=>preg_quote($value),
数组_键($searchFor)
)
)“\b”);
//迭代不在“a”元素内的文本节点
foreach($xpath->evaluate('//text()[not(祖先::a)])为$text){
//在搜索词处拆分文本
$parts=preg\u split($pattern,$text->textContent,-1,preg\u split\u DELIM\u CAPTURE);
$fragment=$document->createDocumentFragment();
$modified=FALSE;
foreach($parts作为$part){
//如果是搜索词
如果($href=$searchFor[$part]??false){
//添加链接
$fragment->appendChild(
$a=$document->createElement('a')
);
$a->setAttribute('href',$href);
$a->textContent=$part;
$modified=TRUE;
}否则{
//添加文本
$fragment->appendChild(
$document->createTextNode($part)
);
}
}
如果($修改){
//用新节点列表替换原始文本节点
$text->parentNode->replaceChild($fragment,$text);
}
}
echo$document->saveHTML();
输出: