通过php dom,通过html片段中的超链接查找和替换关键字

pix*_*ine 6 html php replace

我正在尝试使用simple_html_dom php类来创建查找和替换函数,该函数查找关键字并将其替换为关键字定义的链接,关键字为链接文本.

如何<a href="info.php?tag=dexia">Dexia</a> 使用这个类在一个字符串中找到并替换"Dexia" <div><p>The CEO of the Dexia bank has just decided to retire.</p></div>

Gor*_*don 5

这有点棘手,但你可以这样做:

$html = <<< HTML
<div><p>The CEO of the Dexia bank <em>has</em> just decided to retire.</p></div>
HTML;
Run Code Online (Sandbox Code Playgroud)

我添加了一个强调元素,只是为了说明它也适用于内联元素.

建立

$dom = new DOMDocument;
$dom->formatOutput = TRUE;
$dom->loadXML($html);
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('//text()[contains(., "Dexia")]');
Run Code Online (Sandbox Code Playgroud)

上面有趣的事情当然是XPath.它查询加载的DOM以查找DOMText包含针"Dexia"的所有节点.结果是DOMNodeList(像往常一样).

更换

foreach($nodes as $node) {
    $link     = '<a href="info.php?tag=dexia">Dexia</a>';
    $replaced = str_replace('Dexia', $link, $node->wholeText);
    $newNode  = $dom->createDocumentFragment();
    $newNode->appendXML($replaced);
    $node->parentNode->replaceChild($newNode, $node);
}
echo $dom->saveXML($dom->documentElement);
Run Code Online (Sandbox Code Playgroud)

该发现$node将包含字符串的德克夏银行的CEOwholeText,尽管它是内部P因素.那是因为在银行之后$node有一个DOMElement强调的兄弟姐妹.我正在创建链接作为字符串而不是节点,并替换所有出现的"Dexia"(无论字边界 - 这将是一个很好的调用Regex)与它.然后我从结果字符串创建一个并用它替换节点.wholeTextDocumentFragmentDOMText

W3C与PHP

使用DocumentFragement::applyXML()是一种非标准方法,因为该方法不是W3C DOM规范的一部分.

如果您希望使用标准API进行替换,则首先必须将AElement 创建为新的DOMElement.然后,你就必须找到"德夏"的抵消nodeValueDOMText,分裂的DOMText,在那个位置的节点为两个节点.从返回的兄弟中删除Dexia并在第二个之前插入Link Element.使用兄弟节点重复此过程,直到节点中找不到Dexia字符串.以下是Dexia的一次出现:

foreach($nodes as $node) {
    $link = $dom->createElement('a', 'Dexia');
    $link->setAttribute('href', 'info.php?tag=dexia');
    $offset  = strpos($node->nodeValue, 'Dexia');
    $newNode = $node->splitText($offset);
    $newNode->deleteData(0, strlen('Dexia'));
    $node->parentNode->insertBefore($link, $newNode);
}
Run Code Online (Sandbox Code Playgroud)

最后输出

<div>
  <p>The CEO of the <a href="info.php?tag=dexia">Dexia</a> bank <em>has</em> just decided to retire.</p>
</div>
Run Code Online (Sandbox Code Playgroud)