|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Bonjour,
j'ai un module de recherche sur un site. Et sur la page de résultats, je surligne le résultat. OK ça marche. $Contenu = eregi_replace($quoi, "<span class=\"highlight\">\\0</span>", $Contenu); Oui mais, le seul souci c'est que ça me casse le code à l'intérieur des liens interactifs puisque ça ajoute le span class. Du style : <a href="http://www.<span class="highlight">trucmuche</span>.com">mon lien</a> Comment dire $Contenu = eregi_replace sauf là où c'est encadré par <a href et le > suivant ?... C'est possible ça ? Merci pour l'aide |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
paul a écrit :
> C'est possible ça ? > Merci pour l'aide Attention, la solution que je vais te proposer est très bourrin, ça peut éventuellement consommer beaucoup de mémoire. L'astuce consisterait à utiliser un parser de HTML/XML : DOMDocument <http://fr2.php.net/manual/fr/ref.dom.php> avec DOMXpath <http://fr2.php.net/manual/fr/function.dom-domxpath-construct.php>, puis en traitant les résultant de la requête avec preg_match. Par exemple, pas testé et fait de tête (j'vais pas tout faire non plus :p) : <?php $word = 'toto' ; $doc = DOMDocument::loadHTML($output) ; $doc->validate() ; $finder = new DOMXPath('//text()') ; foreach($finder as $textNode) { // L'expression régulière ci-dessous ne détectera que la première occurrence du mot $word. if(preg_match('`^(.*)\b('.$word.')\b(.*)$`', $textNode.value, $matches)) { $hlSpan = $doc->createElement('span', $word) ; $hlSpan->setAttribute('class', 'highlight') ; $beforeNode = $textNode.ownderDocument.createTextNode($matches[1]) ; $afterNode = $textNode.ownderDocument.createTextNode($matches[3]) ; $textNode.parentNode.appendChild($beforeText) ; $textNode.parentNode.appendChild($hlSpan) ; $textNode.parentNode.appendChild($afterText) ; $textNode.parentNode.removeChild($textNode) ; } } echo $doc->saveHTML() ; ?> Les remarques sur ma façon de coder sont les bienvenues, ou sur des erreurs aussi. Bon début de semaine à tous ! -- Mickaël Wolff aka Lupus Michaelis http://lupusmic.org |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
Le 01/10/2007 10:20, paul a écrit :
> > j'ai un module de recherche sur un site. Et sur la page de résultats, je > surligne le résultat. OK ça marche. > > $Contenu = eregi_replace($quoi, "<span class=\"highlight\">\\0</span>", > $Contenu); > > Oui mais, le seul souci c'est que ça me casse le code à l'intérieur des > liens interactifs puisque ça ajoute le span class. Du style : > <a href="http://www.<span class="highlight">trucmuche</span>.com">mon > lien</a> > > Comment dire $Contenu = eregi_replace sauf là où c'est encadré par <a > href et le > suivant ?... Le plus simple (et le plus sûr) me semble être d'utiliser un analyseur syntaxique de HTML qui te construit un arbre, et tu n'as plus qu'à faire le remplacement dans les feuilles avant de générer le résultat. Avec des expressions rationnelles tu ne peux faire que du bricolage. Essayons tout de même de bricoler. Je suppose que $quoi contient un mot, avec donc des lettres le plus souvent, mais pas de signes de ponctuation et surtout pas d'espaces. Pour éviter le problème que tu signales, tu peux vérifier avec une « assertion arrière » que le mot est précédé d'un espace ou du caractère « > » et rien d'autre : (?<=\s|>) Par la même occasion tu peux aussi vérifier qu'il se termine à une frontière de mot : \b Cela donnera donc : $contenu = preg_replace("/?<=\s|>)$quoi\b/", "<span class='highlight'>$0</span>", $contenu); Note que l'on ne peut pas à ma connaissance utiliser d'assertion arrière allant chercher le « a href » car elle ne serait pas de longueur fixe. Une autre méthode consisterait à rechercher toutes les chaînes comprises entre « > » et « < » et à effectuer le remplacement que tu souhaites dans chacune de ces chaînes. Par exemple : function ma_fonction($matches) { return preg_replace("/$quoi/", "<span class='highlight'>$0</span>", $matches[0]); } $contenu = preg_replace_callback("/>.*</sU", "ma_fonction", $contenu); |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
Le 01/10/2007 13:17, Olivier Miakinen a écrit :
> (?<=\s|>) Ok à priori. > $contenu = preg_replace("/?<=\s|>)$quoi\b/", ^^ Il manque une parenthèse ici. Il y a peut-être d'autres erreurs car je n'ai rien testé. |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
Bonjour,
Petite correction rapide, car j'ai bien évidemment oublié une étape cruciale en allant trop vite, qui est l'évaluation du XPath. Mickael Wolff a écrit : > $doc = DOMDocument::loadHTML($output) ; > $doc->validate() ; > - $finder = new DOMXPath('//text()') ; + $finder = new DOMXPath($doc) ; > - foreach($nodes as $textNode) + foreach($finder->evaluate('//text()') as $textNode) > { -- Mickaël Wolff aka Lupus Michaelis http://lupusmic.org |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
In article <4700d4e4$1@neottia.net>,
Olivier Miakinen <om+news@miakinen.net> wrote: > Le 01/10/2007 10:20, paul a écrit : > > > > j'ai un module de recherche sur un site. Et sur la page de résultats, je > > surligne le résultat. OK ça marche. > > > > $Contenu = eregi_replace($quoi, "<span class=\"highlight\">\\0</span>", > > $Contenu); > > > > Oui mais, le seul souci c'est que ça me casse le code à l'intérieur des > > liens interactifs puisque ça ajoute le span class. Du style : > > <a href="http://www.<span class="highlight">trucmuche</span>.com">mon > > lien</a> > > > > Comment dire $Contenu = eregi_replace sauf là où c'est encadré par <a > > href et le > suivant ?... > > Essayons tout de même de bricoler. Je suppose que $quoi contient un > mot, avec donc des lettres le plus souvent, mais pas de signes de > ponctuation et surtout pas d'espaces. Pour éviter le problème que tu > signales, tu peux vérifier avec une « assertion arrière » que le mot > est précédé d'un espace ou du caractère « > » et rien d'autre Ben je n'interdis pas de faire des recherches sur plusieurs mots et éventuellement avec de la ponctuation... ça semble bien fonctionner d'ailleurs... > > > Une autre méthode consisterait à rechercher toutes les chaînes comprises > entre « > » et « < » et à effectuer le remplacement que tu souhaites > dans chacune de ces chaînes. Par exemple : > function ma_fonction($matches) { > return preg_replace("/$quoi/", "<span class='highlight'>$0</span>", > $matches[0]); > } > $contenu = preg_replace_callback("/>.*</sU", "ma_fonction", $contenu); Pas mal vu, sauf qu'il n'y a malheureusement pas forcément de lien dans le contenu !... ;-) C'est pour ça que je disais que s'il y a un ou des liens il faudrait ne pas intervenir avec le eregi_replace entre les <a href et le > suivant. |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
Le 02/10/2007 09:35, paul a écrit :
> > Ben je n'interdis pas de faire des recherches sur plusieurs mots et > éventuellement avec de la ponctuation... ça semble bien fonctionner > d'ailleurs... Donc, tu autorises aussi les recherches sur « link rel="stylesheet" », sur « meta http-equiv » et ainsi de suite ? Dans ce cas je ne vois pas pourquoi le contenu des attributs href serait le seul à protéger. >> Une autre méthode consisterait à rechercher toutes les chaînes comprises >> entre « > » et « < » et à effectuer le remplacement que tu souhaites >> dans chacune de ces chaînes. Par exemple : >> function ma_fonction($matches) { >> return preg_replace("/$quoi/", "<span class='highlight'>$0</span>", >> $matches[0]); >> } >> $contenu = preg_replace_callback("/>.*</sU", "ma_fonction", $contenu); > > Pas mal vu, sauf qu'il n'y a malheureusement pas forcément de lien dans > le contenu !... Je ne comprends pas ta remarque. Il n'y aura *jamais* de lien dans le contenu, en tout cas jamais de balises <a> ou </a>, et justement il me semble que c'est ce que tu cherches : modifier le contenu pour mettre certains mots en évidence, mais ne surtout pas toucher aux balises HTML, dont les liens. > C'est pour ça que je disais que s'il y a un ou des liens il faudrait ne > pas intervenir avec le eregi_replace entre les <a href et le > suivant. Si tu ne prends que ce qui se trouve entre un > fermant et le < ouvrant qui suit, ça ne changera pas ce qui se trouve entre un < ouvrant et le > fermant correspondant. Bien sûr, il faudrait peut-être affiner si jamais tu t'autorisais à mettre dans le contenu des « > » non encodés en « > », mais j'ai supposé que ce n'était pas le cas. |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
In article <4701f78b$1@neottia.net>,
Olivier Miakinen <om+news@miakinen.net> wrote: > >> Une autre méthode consisterait à rechercher toutes les chaînes comprises > >> entre « > » et « < » et à effectuer le remplacement que tu souhaites > >> dans chacune de ces chaînes. Par exemple : > >> function ma_fonction($matches) { > >> return preg_replace("/$quoi/", "<span class='highlight'>$0</span>", > >> $matches[0]); > >> } > >> $contenu = preg_replace_callback("/>.*</sU", "ma_fonction", $contenu); > > > > Pas mal vu, sauf qu'il n'y a malheureusement pas forcément de lien dans > > le contenu !... > > Je ne comprends pas ta remarque. cf plus bas > > C'est pour ça que je disais que s'il y a un ou des liens il faudrait ne > > pas intervenir avec le eregi_replace entre les <a href et le > suivant. > > Si tu ne prends que ce qui se trouve entre un > fermant et le < ouvrant > qui suit, ça ne changera pas ce qui se trouve entre un < ouvrant et le > > fermant correspondant. Mais euh... s'il n'y a pas de lien dans le contenu, le preg_replace ne retournera rien, non ?... |
|
![]() |
| Outils de la discussion | |
|
|