che è un po 'complicato, ma si poteva fare in questo modo:
$html = <<< HTML
<div><p>The CEO of the Dexia bank <em>has</em> just decided to retire.</p></div>
HTML;
Ho aggiunto un elemento enfasi solo per illustrare che funziona con elementi in linea troppo.
Setup
$dom = new DOMDocument;
$dom->formatOutput = TRUE;
$dom->loadXML($html);
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('//text()[contains(., "Dexia")]');
La cosa interessante sopra è il XPath naturalmente. Interroga il DOM caricato per tutti i nodi DOMText
contenenti l'ago "Dexia". Il risultato è DOMNodeList
(come al solito).
La sostituzione
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);
Il trovato $node
conterrà la stringa Il CEO della banca Dexia per wholeText
, nonostante sia all'interno dell'elemento P
. Questo perché $node
ha un fratello DOMElement
con l'enfasi dopo banca. Sto creando il collegamento come una stringa invece di un nodo e sostituisco tutte le occorrenze di "Dexia" (indipendentemente dal limite della parola - che sarebbe una buona chiamata per Regex) nello stesso wholeText
. Quindi creo un DocumentFragment
dalla stringa risultante e sostituisco il nodo DOMText
con esso.
W3C vs PHP
Utilizzando DocumentFragement::applyXML()
è un approccio non standard, poiché il metodo non è parte del W3C DOM Spec.
Se si desidera eseguire la sostituzione con l'API standard, è necessario creare prima l'elemento A
come nuovo DOMElement
. Quindi dovresti trovare l'offset di "Dexia" nello nodeValue
dello DOMText
e dividere il nodo DOMText
in due nodi in quella posizione. Rimuovi Dexia dal fratello restituito e inserisci l'elemento Link, prima del secondo. Ripeti questa procedura con il nodo fratello finché non vengono trovate più stringhe di Dexia nel nodo. Ecco come farlo per un'occorrenza di 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);
}
E infine l'uscita
<div>
<p>The CEO of the <a href="info.php?tag=dexia">Dexia</a> bank <em>has</em> just decided to retire.</p>
</div>
Dovete usare simple_html_dom? Questo sembra qualcosa che potrebbe essere realizzato con regex usando preg_replace. –
@threendib HTML non è regolare. – Gordon