Forum d'entraide PHPFrance

Venez poser vos questions PHP, MySQL, HTML, CSS, Javascript, Gestion de serveurs à la communauté PHPfrance

Vers le contenu

» Masquer les résultats de la recherche

Recherche dynamique PHPfrance

  1. Effectuez une recherche, les résultats s'afficheront dynamiquement ici.

Remplacement sélectif, hors ou dans balises html

Postez ici toutes vos petites astuces de développement, les scripts sympa et vos productions personnelles.
Ainsi vos messages ne seront pas enfouis sous une tonne de questions.

Remplacement sélectif, hors ou dans balises html

Messagepar Ripat 13 Fév 2005, 14:16

J'ai souvent vu des questions concernant le remplacement dans une page html sans toucher à ce qui est encadré par des balises.

Exemple: comment remplacer le mot texte dans la chaîne suivante:
Texte 1 < 2 hors balises<div id="texte">suite du texte<a href="http://texte.com">texte hors balise</a></div> texte final'
sans toucher aux id="texte" et autres href="http://texte.com"? (la présence de 1 < 2 n'est pas innocente!)

Ou l'inverse, modifier le contenu des balises html sans toucher au reste.

J'ai essayé de synthétiser ce genre de traitement. Le groupe de fonctions suivant permet de faire, au choix, un remplacement hors balises html ou dans les balises html (flag 1 ou -1).

La fonction split_balise() accepte de travailler avec :
    str_replace
    ereg_replace
    eregi_replace
    preg_replace

Syntaxe: [ Télécharger ] [ Masquer ]
Code php
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

FONCTIONS POUR REMPLACEMENT SELECTIF, HORS OU DANS BALISE HTML

 pour str_replace ou preg_replace :

 string split_balise(mixed pattern, mixed replacement, string subject, string function [, int flag])



 pour ereg et eregi :

 string split_balise(string pattern, string replacement, string subject, string function [, int flag])

 

 flag [option]:  flag = 1: remplacement HORS balises (défaut)

                flag INT autre que 1: remplacement DANS balises



 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

PREMIERE VERSION (3 fois plus lente)



function mon_rplc($capture1, $capture2, &$de, &$par, $fct, $flag){

  return ($flag == 1)

    ? $fct($de, $par, stripslashes($capture1)).stripslashes($capture2)

    : stripslashes($capture1).$fct($de, $par, stripslashes($capture2));

}



function split_balise($de, $par, $txt, $fct, $flag = 1){

  $eval_fct = "mon_rplc('\$1', '\$2', \$de, \$par, '$fct', '$flag')";

  return preg_replace('#((?:(?!<[/a-z]).)*)([^>]*>|$)#ies', $eval_fct, $txt);

}

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */




function mon_rplc_callback($capture){

  global $arg;

  return ($arg['flag'] == 1)

  ? $arg['fct']($arg['de'], $arg['par'], $capture[1]).$capture[2]

  : $capture[1].$arg['fct']($arg['de'], $arg['par'], $capture[2]);

}





function split_balise($de, $par, $txt, $fct, $flag = 1){

  global $arg;

  $arg = compact('de', 'par', 'fct', 'flag');

  return preg_replace_callback('#((?:(?!<[/a-z]).)*)([^>]*>|$)#si', "mon_rplc_callback", $txt);

}



 


Pour illustrer son fonctionnement, voici quelques exemples:
Syntaxe: [ Télécharger ] [ Masquer ]
Code php
$txt = 'Texte 1 < 2 hors balises<div id="texte">suite du texte<a href="http://texte.com">texte hors balise</a></div> texte final';



// exemple 1

// str_replace ou ereg_replace

// cet exemple remplace 'texte' par 'TEXTE' hors balises (option 1)

   echo  split_balise('texte', 'TEXTE', $txt, 'str_replace', 1);

   echo  split_balise('#texte#', 'TEXTE', $txt, 'preg_replace', 1);
Texte 1 < 2 hors balises<div id="texte">suite du TEXTE<a href="http://texte.com">TEXTE hors balise</a></div> TEXTE final


Syntaxe: [ Télécharger ] [ Masquer ]
Code php
// exemple 2
// str_replace ou ereg_replace
// cet exemple remplace 'texte' par 'TEXTE' dans les balises (option -1)
   echo split_balise('texte', 'TEXTE', $txt, 'str_replace', -1);
Texte 1 < 2 hors balises<div id="TEXTE">suite du texte<a href="http://TEXTE.com">texte hors balise</a></div> texte final


Syntaxe: [ Télécharger ] [ Masquer ]
Code php
// exemple 3
// eregi_replace (insensible à la casse)
// cet exemple remplace 'texte' ou 'Texte' par 'TEXTE' hors balises
   echo split_balise('texte', 'TEXTE', $txt, 'eregi_replace', 1);
TEXTE 1 < 2 hors balises<div id="texte">suite du TEXTE<a href="http://texte.com">TEXTE hors balise</a></div> TEXTE final


Syntaxe: [ Télécharger ] [ Masquer ]
Code php
// exemple 4
// str_replace avec des tableaux en argument
// remplace d'abord 'texte' par 'TEXTE' ensuite tous les 'e' par 'Z'
   $in = array('texte','e');
   $rpl = array('TEXTE','Z');
   echo split_balise($in, $rpl, $txt, 'str_replace', 1);
TZxtZ 1 < 2 hors balisZs<div id="texte">suitZ du TEXTE<a href="http://texte.com">TEXTE hors balisZ</a></div> TEXTE final


Syntaxe: [ Télécharger ] [ Masquer ]
Code php
// exemple 5
// preg_replace avec remplacement de références arrières
// remplacement hors balises (option 1)
   echo split_balise('#(h)(.+?)(s)#s', '$1ORS$3', $txt, 'preg_replace', 1);
Texte 1 < 2 hORSs balises<div id="texte">suite du texte<a href="http://texte.com">texte hORSs balise</a></div> texte final


Syntaxe: [ Télécharger ] [ Masquer ]
Code php
// exemple 6
// preg_replace avec remplacement de références arrières
// remplacement dans balises (option -1)
   echo split_balise('#(id=")(.+?)(")#s', '$1$2_plus_long$3', $txt, 'preg_replace', -1);
Texte 1 < 2 hors balises<div id="texte_plus_long">suite du texte<a href="http://texte.com">texte hors balise</a></div> texte final

Voilà, j'espère que cela pourra vous être utile.

Si vous trouvez des erreurs ou incompatibilités, j'essayerai de les corriger.
Dernière édition par Ripat le 21 Aoû 2005, 09:23, édité 1 fois.
ripat
Ripat
ViPHP
ViPHP
 
Messages: 1380
Inscription: 08 Fév 2005, 10:17
Localisation: Belgique

Messagepar Ripat 16 Aoû 2005, 14:02

Un petit dépoussiérage et dopage s’imposaient.
Et puis, ce post était le dernier de la liste, alors un p’ti up…

On sait que preg_replace_callback est presque toujours plus rapide que preg_replace + option e. Le problème qu’il est plus difficile de passer des arguments pour la fonction invoquée (voir discussion ici).

Un petite gymnastique sur la portée des variables a donc été nécessaire.

Gain : près de 3 fois plus rapide. Comme on peut imaginer que cette fonction sera utilisée sur des pages entières, parfois très lourdes, ce gain est appréciable.


Syntaxe: [ Télécharger ] [ Masquer ]
Code php

function mon_rplc_callback($capture){

  global $arg;

  return ($arg['flag'] == 1)

  ? $arg['fct']($arg['de'], $arg['par'], $capture[1]).$capture[2]

  : $capture[1].$arg['fct']($arg['de'], $arg['par'], $capture[2]);

}





// Même prototype que pour la fonction du premier post.

function split_balise2($de, $par, $txt, $fct, $flag = 1){

  global $arg;

  $arg = compact('de', 'par', 'fct', 'flag');

  return preg_replace_callback('#((?:(?!<[/a-z]).)*)([^>]*>|$)#si', "mon_rplc_callback", $txt);

}

 

Il reste peut-être à optimiser le motif du split, mais je ne vois pas trop comment. S'il y a des amateurs...

Edit: Le premier post modifié avec cette nouvelle version
Dernière édition par Ripat le 21 Aoû 2005, 09:18, édité 1 fois.
ripat
Ripat
ViPHP
ViPHP
 
Messages: 1380
Inscription: 08 Fév 2005, 10:17
Localisation: Belgique

Messagepar Henri 12 Juin 2006, 17:23

Merci pour ce code. J'ai posé la question dans un autre post et on m'a fait remarqué que la réponse se trouvait ici.

J'avais pour ma part ce code
Syntaxe: [ Télécharger ] [ Masquer ]
Code php

$mot = "t[aàäâ]bl[eéèêë]"; //exemple

$replace = "<span class=surligne>\\0</span>";

$texte = eregi_replace ($mot, $replace, $texte);

 

qui me permet de mettre un surlignage par exemple sur le mot table avec toutes les combinaisons possibles de lettres accentuées (sur table, c'est un peu débile, mais sur des noms de sociétés, ce n'est pas inutile). Mais ce remplacement primaire me mettait le souk dans mes tags tableaux ou dans les tags images ...

Je l'ai donc remplacé par
Syntaxe: [ Télécharger ] [ Masquer ]
Code php

$mot = "t[aàäâ]bl[eéèêë]"; //exemple

$replace = "<span class=surligne>\\0</span>";

$texte = split_balise2($mot, $replace, $texte, "eregi_replace", 1);

 


Sur un court exemple, c'est OK. Mais je viens de le lancer sur une page typique de mon site (environ 100 Ko de texte) avec un sacré paquet de tableau et ... rien ! Sauf une stackoverflow de PHP au bout de 3 à 4 minutes.

Pour l'instant, la seule solution que j'ai trouvé, c'est de découper ma page sur les retours-chariots (heureusement assez nombreux) de la page et de faire une boucle.
Henri
Eléphanteau
 
Messages: 332
Inscription: 12 Juin 2006, 16:55

Messagepar Ripat 12 Juin 2006, 17:31

Essaye avec preg_replace, moins gourmand et plus rapide.
ripat
Ripat
ViPHP
ViPHP
 
Messages: 1380
Inscription: 08 Fév 2005, 10:17
Localisation: Belgique

Messagepar Henri 12 Juin 2006, 18:06

Correction :
Il semblerait que la limite du stack overflow se situe aux environs de 430 caractères.

Ca fonctionne avec 430 caractères
Syntaxe: [ Télécharger ] [ Masquer ]
Code php

$texte = "Lorsque vous utilisez SSL, le serveur IIS de Microsoft violera le protocole en fermant

la connexion sans envoyer l'indicateur close_notify. PHP le reportera en tant que

\"SSL: Fatal Protocol Error\" quand vous arrivez à la fin des données. L'astuce est

de baisser le niveau de la directive error_reporting pour ne pas inclure les warnings.

À partir de PHP 4.3.7, le bogue est détecté automatiquement lors de l'ouverture du flux "
;

echo strlen($texte)."<br />";



$mot = "PHP"; //exemple

$replace = "<span class=surligne>\\0</span>";

$texte2 = split_balise2($mot, $replace, $texte, "eregi_replace", 1);

echo $texte2;  

 


La même chose en mettant une lettre de plus à la fin du texte :
PHP has encountered a Stack overflow431
Syntaxe: [ Télécharger ] [ Masquer ]
Code php

$texte = "Lorsque vous utilisez SSL, le serveur IIS de Microsoft violera le protocole en fermant

la connexion sans envoyer l'indicateur close_notify. PHP le reportera en tant que

\"SSL: Fatal Protocol Error\" quand vous arrivez à la fin des données. L'astuce est

de baisser le niveau de la directive error_reporting pour ne pas inclure les warnings.

À partir de PHP 4.3.7, le bogue est détecté automatiquement lors de l'ouverture du flux x"
;



echo strlen($texte)."<br />";



$mot = "PHP"; //exemple

$replace = "<span class=surligne>\\0</span>";

$texte2 = split_balise2($mot, $replace, $texte, "eregi_replace", 1);

echo $texte2;  

 
Dernière édition par Henri le 13 Juin 2006, 11:09, édité 1 fois.
Henri
Eléphanteau
 
Messages: 332
Inscription: 12 Juin 2006, 16:55

Messagepar Henri 12 Juin 2006, 18:30

Ripat a écrit:Essaye avec preg_replace, moins gourmand et plus rapide.


Ouais ... bon ... enfin ... Bref, c'est déjà bien la galère pour les quelques notions de syntaxe ereg, alors la syntaxe preg, comment dire ? j'y suis pas encore. :)

comment traduirais-tu le eregi_replace
Syntaxe: [ Télécharger ] [ Masquer ]
Code php

$mot = "t[aàäâ]bl[eéèêë]";

$replace = "<span class=surligne>\\0</span>";

 

en syntaxe preg ?
Henri
Eléphanteau
 
Messages: 332
Inscription: 12 Juin 2006, 16:55

Messagepar Ripat 12 Juin 2006, 19:04

Tout simplement:

Syntaxe: [ Télécharger ] [ Masquer ]
Code php
$mot = "#\bt[aàäâ]bl[eéèêë]\b#";


J'ai rajouté l'assertion \b pour marquer la séparation de mots. Sinon tu risque de remplacer "table" dans "étable".
ripat
Ripat
ViPHP
ViPHP
 
Messages: 1380
Inscription: 08 Fév 2005, 10:17
Localisation: Belgique

Merci

Messagepar Canhca1221 24 Juil 2009, 12:15

Vraiment bien!

Merci, c'est justement ce que je cherchais

Merci beaucoup
:oops: :lol: :roll:


devis comparatif assurance voiture - Comparatif assurance voiture. Devis immédiat. Bas prix et adaptée. Devis assurance voiture.
Canhca1221
Embryon
 
Messages: 1
Inscription: 24 Juil 2009, 12:05

Messagepar narcisse 24 Juil 2009, 14:12

Quelqu'un a prévu de ré-ouvrir ce post dans trois ans ?
narcisse
Ma première boucle
 
Messages: 111
Inscription: 31 Mar 2009, 14:23

Messagepar zeus 24 Juil 2009, 16:43

C'est sympa de venir dire que ce message a répondu à son besoin.

Lachez du lest les gars ;)
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer
Avatar de l’utilisateur
zeus
Administrateur PHPfrance
Administrateur PHPfrance
 
Messages: 13162
Inscription: 22 Avr 2005, 11:11
Localisation: Lyon

Messagepar dunbar 27 Juil 2009, 17:15

C'est surtout sympa que certains prennent la peine de dire merci.
En plus cela prouve que certains prennent la peine d'utiliser la fonction recherche. :wink:
ImageCe que l'on apprend par l'effort reste toujours ancré beaucoup plus longtemps.
Avatar de l’utilisateur
dunbar
ViPHP
ViPHP
 
Messages: 2279
Inscription: 11 Juil 2006, 23:23
Localisation: Ici

Messagepar savageman 27 Juil 2009, 18:01

Surtout que la fonction présentée est utile. Ceux qui prennent le temps de lire la discussion pourront même suivre les étapes de son optimisation, c'est pas inintéressant non plus !
savageman
J'ai codé une fonction !
 
Messages: 185
Inscription: 20 Aoû 2005, 19:10

Re: Remplacement sélectif, hors ou dans balises html

Messagepar Gr33nc0de 27 Nov 2009, 17:39

Bonjour,

Merci c'est très intéressant, cela peut servir.
Gr33nc0de
Embryon
 
Messages: 8
Inscription: 26 Nov 2009, 17:53

Re: Remplacement sélectif, hors ou dans balises html

Messagepar totodonat 30 Déc 2010, 20:37

Bonjour,

merci pour ces infos précieuses.
j'ai un probleme :

lorsque la chaine de caractère traitée est trop longue (+ de 5000 caractères),
alors le script ne marche pas, et le navigateur propose d'enregistrer la page php.
:(

que faire ?
totodonat
Embryon
 
Messages: 1
Inscription: 30 Déc 2010, 20:28

Re: Remplacement sélectif, hors ou dans balises html

Messagepar stealth35 02 Jan 2011, 18:45

totodonat a écrit:Bonjour,

merci pour ces infos précieuses.
j'ai un probleme :

lorsque la chaine de caractère traitée est trop longue (+ de 5000 caractères),
alors le script ne marche pas, et le navigateur propose d'enregistrer la page php.
:(

que faire ?


il faut utilisé un outils adapter comme DOMDocument, avec un requete xpath pour sélectionner ton texte :wink:
stealth35
ViPHP
ViPHP
 
Messages: 5465
Inscription: 27 Déc 2009, 17:58


Retourner vers Vos contributions

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 1 invité