IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

[Système] Remplacer une balise, SAUF si elle est imbriqué dans une autre balise


Sujet :

Langage PHP

  1. #1
    Membre régulier
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2006
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Freelance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 65
    Points : 79
    Points
    79
    Par défaut [Système] Remplacer une balise, SAUF si elle est imbriqué dans une autre balise
    Salut,

    Voila mon pb:
    Je voudrais remplacer toutes les balises <include....></include> par un texte
    SAUF si cette balise est imbriqué dans des balises <no>
    ex: <no> ... <include....></include> ... </no>

    Pour l'instant je remplace les balise <include> avec un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $vResult = preg_replace_callback('#<include .*\/include *>#Ui','_dyna_faicCallback',$aText);
    Mais je n'arrive pas a trouvé de solution pour le gérer SAUF...

    A+... Thierry

  2. #2
    Rédacteur
    Avatar de _Mac_
    Profil pro
    Inscrit en
    Août 2005
    Messages
    9 601
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 9 601
    Points : 12 977
    Points
    12 977
    Par défaut
    Le sauf, c'est pas vraiment prévu dans les expressions régulières, malheureusement. A mon avis, le plus simple, mais ça dépend énormément de la façon dont est structurée ta chaîne à traiter, c'est de faire un premier test pour identifier les lignes où <include> n'est pas dans un <no>. Mais le pb, c'est de pouvoir faire ça : ça suppose qu'il n'y a qu'un <include> possible par ligne et ça, c'est pas garanti, j'imagine...

  3. #3
    Membre régulier
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2006
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Freelance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 65
    Points : 79
    Points
    79
    Par défaut
    Salut Mac,

    La chaine a traiter est un fichier HTML standart et il peut y avoir plusieurs <include> (non imbriqués).
    En fait c'est un systéme de Templates et les <include> sont remplacés par du code HTML avant d'etre affiché.

    A+... Thierry

  4. #4
    Membre régulier
    Inscrit en
    Mai 2007
    Messages
    127
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 127
    Points : 71
    Points
    71
    Par défaut
    Comme ca je vois deux possibilités :
    1. Avant de remplacer tes includes, tu vérifie (par un preg_match) que tu n'a pas d'autres includes imbriqués. Si oui, tu agis en conséquences

    2. Tu fait un preg_replace_callback sur ta commande, et dans ta fonction de callback, tu rappele ta fonction de callback s'il retrouve un include dans la chaine récupéré. Cela sous-entends que tu a déjà spécifié par quoi il fallait remplacer tous tes includes. C'est la solution qui me semblerait la mieux adapté, bien que je ne concois pas que l'idée soit tres optimisée.

  5. #5
    Membre éclairé Avatar de Korko Fain
    Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    632
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2005
    Messages : 632
    Points : 718
    Points
    718
    Par défaut
    Si ta balise include est DIRECTEMENT précédée ou suivie respectivement d'une balise <no> ou </no> on peux le savoir mais sinon ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #(?<!<no>)<include>.*?</include>(?!</no>)#
    PS : Je vien de coder ça mais je n'ai pas encore pu le tester (pas acces ftp ni serveur php là ou je suis), essaye et dit moi si ça fonctionne ça devrait résoudre ton probleme si c'est bon.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    function preg_replace_inverse($regexnot, $regex, $replacement, $subject)
    {
    	// On recherche tout ce qu'on ne veux pas
    	$matches = preg_split($regexnot, $subject, -1, PREG_SPLIT_OFFSET_CAPTURE);
     
    	$offset = 0;
     
    	// Pour chaque chaine qui ne correspond pas à la regex non voulue
    	foreach( $matches as $match )
    	{
    		// On stock la longueur de la chaine originale (pour la remplacer)
    		$size = strlen($match[0]);
     
    		// On remplace la valeur de la chaine
    		$match[0] = preg_replace($regex, $replacement, $match[0]);
     
    		// On remplace dans la chaine d'origine
    		substr_replace($subject, $match[0], $match[1]+$offset, $size);
    		// Gestion de l'offset car si le texte remplacé est plus long ou plus court 
    		// la position d'insertion ($match[1]) change
    		$offset += strlen($match[0])-$size;
    	}
     
    	// Maintenant on retourne la chaine modifiée
    	return $subject;
    }
     
    preg_replace_inverse('#<no>.*?</no>#is', '#<include.*>.*</include>#U', $replaceValue, $string);
    Edit : Ajout de la fonction callback et edit du premier pour ajouter offset
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    function preg_replace_callback_inverse($regexnot, $regex, $callback, $subject)
    {
    	// On recherche tout ce qu'on ne veux pas
    	$matches = preg_split($regexnot, $subject, -1, PREG_SPLIT_OFFSET_CAPTURE);
     
    	$offset = 0;
     
    	// Pour chaque chaine qui ne correspond pas à la regex non voulue
    	foreach( $matches as $match )
    	{
    		// On stock la longueur de la chaine originale (pour la remplacer)
    		$size = strlen($match[0]);
     
    		// On remplace la valeur de la chaine
    		$match[0] = preg_replace_callback($regex, $callback, $match[0]);
     
    		// On remplace dans la chaine d'origine
    		substr_replace($subject, $match[0], $match[1]+$offset, $size);			
    		// Gestion de l'offset car si le texte remplacé est plus long ou plus court 
    		// la position d'insertion ($match[1]) change
    		$offset += strlen($match[0])-$size;
    	}
     
    	// Maintenant on retourne la chaine modifiée
    	return $subject;
    }
     
    preg_replace_callback_inverse('#<no>.*?</no>#is', '#<include.*>.*</include>#Ui', '_dyna_faicCallback', $string);

  6. #6
    Membre régulier
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2006
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Freelance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 65
    Points : 79
    Points
    79
    Par défaut
    Merci Korko pour ta réponse.

    J'ai tésté ton code et y ai apporté quelques modifications

    La regex pour la recherche des <no> est devenue #<no>.*</no>#Uis
    Non vorace, Non sensible a la casse et le . remplace aussi les retour a la ligne (\n) courants dans les fichiers HTML

    J'ai rajouter la gestion d'un offset qui permet de compenser les pertes ou les gains en caractéres apporté par les remplacements precedents

    Et enfin j'utilise preg_replace_callback a la place de preg_replace, mais cela c'est en fonction de l'utilisation que l'on veux en faire par la suite.

    A ton avis, toi qui a l'air calé dans les preg_xxxx comment qualifierez tu ce code ? Bidouille <-+-> Fiable ?
    Histoire de savoir s'il faut que je continue a cherché une autre solution ou si je peut implementer cette solution dans mon code ?

    En tout cas Merci... J'attends ta réponse (ou d'autres) avant de cloturer ce post.

    A+... Thierry

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    	function preg_replace_inverse($regexnot, $regex, $callBackFunction, $subject)
    	{
    		// On recherche tout ce qu'on ne veux pas
    		$matches = preg_split($regexnot, $subject, -1, PREG_SPLIT_OFFSET_CAPTURE);
     
    		$vOffset = 0;
     
    		// Pour chaque chaine qui ne correspond pas à la regex non voulue
    		foreach( $matches as $match )
    		{
    			// On stock la longueur de la chaine originale (pour la remplacer)
    			$size = strlen($match[0]);
     
    			// On remplace la valeur de la chaine
    			$vNewText = preg_replace_callback($regex,$callBackFunction,$match[0]);
     
    			// On remplace dans la chaine d'origine
    			//echo "substr_replace($subject, $match[0], $match[1], $size)\n";
    			$subject = substr_replace($subject, $vNewText, $match[1]+$vOffset, $size);
     
    			// Gestion de l'offset car si le texte remplacé est plus long ou plus court 
    			// la position d'insertion ($match[1]) change
    			$vOffset+= strlen($vNewText)-$size;
    		}
     
    	// Maintenant on retourne la chaine modifiée
    	return $subject;
    	}
     
    	$vTextFinal = preg_replace_inverse('#<no>.*</no>#Uis', '#<include.*>.*</include>#Ui', '_dyna_faicCallback', $vTextOrig);

  7. #7
    Membre éclairé Avatar de Korko Fain
    Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    632
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2005
    Messages : 632
    Points : 718
    Points
    718
    Par défaut
    Ta oublier une , la => $callBackFunction$subject ^^

    Oui en effet, c'est bien l'ajout de l'offset je l'avait oublié

    N'oublie pas de définir ta fonction de callback :p

    Je te conseillerai (histoire de faire plus propre) de renommer la fonction en
    preg_replace_callback_inverse ^^

    Sinon pour la regex c'est bien. A la place du U tu aurais pu mettre .*? mais c'est exactement la meme chose.

  8. #8
    Membre régulier
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2006
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Freelance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 65
    Points : 79
    Points
    79
    Par défaut
    La fonction de callback existe et marche bien, mais etant donnée quelle utilise d'autres fonction (pour l'extraction des attributs de la balise HTML etc...) je ne l'ai volontairement pas mise pour ne pas encombrer le code.

    Merci encore et a+ ... Thierry

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 20/05/2015, 17h49
  2. Réponses: 2
    Dernier message: 05/03/2008, 16h12
  3. Supprimer une colonne d'une feuille si elle est vide dans une autre
    Par xave dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 27/02/2008, 14h05
  4. Réponses: 4
    Dernier message: 22/02/2007, 10h01
  5. Réponses: 7
    Dernier message: 25/10/2005, 15h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo