найти и заменить ключевые слова гиперссылками во фрагменте html через php dom - PullRequest
6 голосов
/ 30 июня 2010

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

1 Ответ

5 голосов
/ 30 июня 2010

Это несколько сложно, но вы могли бы сделать это следующим образом:

$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 будет содержать строку Генеральный директорБанк Дексиа для wholeText, несмотря на то, что он находится внутри элемента P.Это потому, что у $node есть родной брат DOMElement с акцентом после банка .Я создаю ссылку как строку вместо узла и заменяю все вхождения Dexia (независимо от границы слова - это было бы хорошим вызовом для Regex) в wholeText с ним.Затем я создаю DocumentFragment из полученной строки и заменяю ее узлом DOMText.

W3C против PHP

Использование DocumentFragement::applyXML() является нестандартным подходом, поскольку этот метод не является частью спецификаций DOM W3C.

Если вы хотите выполнить замену стандартным API, вам сначала нужно создать элемент A как новый DOMElement.Тогда вам нужно найти смещение «Dexia» в nodeValue DOMText и разделить узел DOMText на два узла в этой позиции.Удалите Dexia из возвращенного брата и вставьте элемент Link перед вторым.Повторите эту процедуру с одноуровневым узлом, пока в узле не будет найдено больше строк 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...