найти и заменить ключевые слова гиперссылками в html-фрагменте, через php dom

Я пытаюсь использовать класс 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>