Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php preg_替换忽略图像标记_Php_Regex_Preg Replace - Fatal编程技术网

Php preg_替换忽略图像标记

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)(?!

我有下面的regexp,其中我搜索一个尚未链接的特定单词,并添加链接

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();
输出: