Я пытаюсь использовать класс simple_html_dom php для создания функции поиска и замены, которая ищет ключевые слова и заменяет их ссылкой на определение ключевого слова с ключевым словом в качестве текста ссылки.
Как я могу найти и заменить «Dexia» <a href="info.php?tag=dexia">Dexia</a>
с помощью этого класса внутри строки, такой как <div><p>The CEO of the Dexia bank has just decided to retire.</p></div>
?
Это несколько сложно, но вы можете сделать это так:
$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 для всех узлов 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);
Найденный $node
будет содержать строку CEO банка Dexia для wholeText
, несмотря на wholeText
, что он находится внутри элемента P
Это связано с тем, что в $node
есть DOMElement
с акцентом после банка . Я создаю ссылку как строку вместо узла и заменяю все вхождения «Dexia» (независимо от границы слова – это будет хороший вызов для Regex) во всем wholeText
с ним. Затем я создаю DocumentFragment
из полученной строки и заменяю DOMText
узлом DOMText
.
W3C против PHP
Использование DocumentFragement::applyXML()
– нестандартный подход, потому что этот метод не является частью спецификаций DOM W3C.
Если вы захотите выполнить замену стандартным API, вам сначала нужно создать элемент A
в качестве нового DOMElement
. Затем вам нужно будет найти смещение «Dexia» в nodeValue
DOMText
и разделить узел DOMText
на два узла в этой позиции. Удалите Dexia из возвращенного брата и вставьте элемент Link, перед вторым. Повторите эту процедуру с помощью узла-брата, пока в узле не будет найдено никаких строк 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>