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

我如何使用此类在<a href="info.php?tag=dexia">Dexia</a>之类的字符串中使用<div><p>The CEO of the Dexia bank has just decided to retire.</p></div>查找和替换“Dexia”?

最佳答案

这有点棘手,但是您可以通过以下方式做到这一点:

$html = <<< HTML
<div><p>The CEO of the Dexia bank <em>has</em> just decided to retire.</p></div>
HTML;

我添加了强调元素只是为了说明它也可以与内联元素一起使用。

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

上面有趣的是,当然是XPath。它在加载的DOM中查询包含针“Dexia”的所有DOMText节点。结果是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);

找到的$node将包含字符串wholeText的Dexia银行的CEO,尽管它位于P元素内。那是因为$node有一个兄弟DOMElement,重点放在库之后。我将链接创建为字符串而不是节点,并用它替换wholeText中所有出现的“Dexia”(无论单词边界如何-对Regex都是很好的调用)。然后,我根据结果字符串创建一个DocumentFragment,并用它替换DOMText节点。

W3C和PHP

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

如果要使用标准API进行替换,则首先必须将A元素创建为新的DOMElement。然后,您必须在nodeValueDOMText中找到“Dexia”的偏移量,并将DOMText节点拆分为该位置的两个节点。从返回的同级中删除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);
}

,最后输出
<div>
  <p>The CEO of the <a href="info.php?tag=dexia">Dexia</a> bank <em>has</em> just decided to retire.</p>
</div>

关于php - 通过php dom通过html片段中的超链接查找和替换关键字,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3151064/

10-11 06:00