Perle, tu m'ennuies avec tes expressions

Perle, tu m'ennuies avec tes expressions - PHP - Programmation

Marsh Posté le 05-01-2004 à 21:16:19    

C'est pourtant pas compliqué mais ca marche pas...
 
Je souhaite rechercher tout ce qui est contenu entre la balise [STRUCTURE="valeur"] et la balise [\STRUCTURE].
 
Malheureusement ce qui ce trouve entre ces balises peut aussi être d'autres balises structure comme ceci:
 
[STRUCTURE="valeur1"]
   [STRUCTURE="valeur2"]
   blabla
   [/STRUCTURE]
[/STRUCTURE]
[STRUCTURE="valeur2"]
blabla
[/STRUCTURE]
 
dans cet exemple je souhaite capturer:
 
[STRUCTURE="valeur1"]
   [STRUCTURE="valeur2"]
   blabla
   [/STRUCTURE]
[/STRUCTURE]
 
Ceci montre que mon expression régulière ne fonctionne pas:
 
/\[STRUCTURE=\"?$structName\"?\]([\W\S]*)\[\/STRUCTURE\]/im
 
Avez-vous en vous le moyen de m'aider !!!


---------------
.:coin:.
Reply

Marsh Posté le 05-01-2004 à 21:16:19   

Reply

Marsh Posté le 05-01-2004 à 21:18:51    

Le langage que tu veux parser releve de l'analyse syntaxique. Or les expressions regulières ne sont pas capable de faire ça proprement à moins de hacker des trucs crades qui marchent "la plupart du temps".
 
Il faut te tourner vers l'écriture d'un vrai parser [:cupra]


---------------
From now on, you will speak only when spoken to, and the first and last words out of your filthy sewers will be "Sir!"
Reply

Marsh Posté le 05-01-2004 à 21:21:44    

Et moi qui pensais que les expressions régulière pouvaient tout faire !!!  :sweat:


---------------
.:coin:.
Reply

Marsh Posté le 05-01-2004 à 21:23:30    

regex -> analyse lexicale et c'est déjà pas mal


---------------
From now on, you will speak only when spoken to, and the first and last words out of your filthy sewers will be "Sir!"
Reply

Marsh Posté le 05-01-2004 à 21:29:11    

y'a moyen avec preg_replace_callback.
tu fais un callback qui regarde si il reste encores des balises [structure]. Si oui, tu reviens sur ton preg_replace_callback, sinon tu arretes.  
 
C'est un peu crade mais ca fonctionne plutot bien et rapidement

Reply

Marsh Posté le 05-01-2004 à 23:03:31    

J'ai trouvé quelquechose d'intérressant dans la documentation PHP :
http://fr.php.net/manual/fr/pcre.pattern.syntax.php
tout en bas de la page à propos des ... masques récursifs  :love:  
 
Exemple :

Code :
  1. <?php
  2. if (preg_match ("/
  3. \(
  4. (
  5.  (
  6.   [^()]+ |
  7.   (?R)
  8.  )*
  9. )
  10. \)/x", "(ae(a)ae((d)))((b))(c)", $matches)) {
  11. echo $matches[1];
  12. }
  13. ?>


 
(option x pour ne pas prendre en compte les espaces pour la présentation ... quoique bof les tab)
 
cela retournera :
ae(a)ae((d))
donc c'est bien ce que tu veux, à part le problème que tu veux une balise avec un paramètre spécifique et que celle à l'intérieur n'ont pas forcemment le même paramètre.
 
J'ai essayé ceci ...  mais cela impose qu'il n'y ai que des balises STRUCTURE mais bon je pense qu'on doit pouvoir s'arranger :
 

Code :
  1. <?php
  2. $valeur = "toto";
  3. $string = "[STRUCTURE=tata]dfgdfg
  4. [/STRUCTURE]
  5. [STRUCTURE=toto]dfg
  6. [STRUCTURE=\"titi\"]dfgdfg
  7. [/STRUCTURE]
  8. [/STRUCTURE]
  9. ";
  10. preg_match ("/(\[STRUCTURE=\"?$valeur\"?\].*)$/xs", $string, $matches);
  11. print_r ($matches);
  12. preg_match ("/
  13. \[STRUCTURE=\"?\w*\"?\]
  14. (
  15.  (
  16.   [^\[\]]+ |
  17.   (?R)
  18.  )*
  19. )
  20. \[\/STRUCTURE\]
  21. /xm", $matches[1], $matches);
  22. echo $matches[1];
  23. ?>


 
qui renvoie :

Code :
  1. dfg
  2.         [STRUCTURE="titi"]dfgdfg
  3.         [/STRUCTURE]


donc exactement ce que tu veux !!!!
 
bon explication : je récupère d'abord une chaîne de caractère telle qu'elle commence juste avant la première balise ayant pour paramètre $valeur (donc "toto" ). Ensuite j'applique l'expression régulière avec masque récursif (tel que expliqué dans le manuel ... À Lire et essayer !) et je n'ai pas besoin de me préoccuper de récupérer le contenu de la première balise avec le bon paramètre, vu que la chaîne commence maintenant avec la bonne balise. Et Hop Magie  :love:  
 
Essaie avec d'autres chaînes au cas où mais ça devrait marcher "normalement" ... Sinon reste à voir pour qu'on puisse mettre d'autres balises que STRUCTURE (je vais dormir là  :sleep: )
 
Bye et bon courage  :hello:


Message édité par Tentacle le 05-01-2004 à 23:04:33
Reply

Marsh Posté le 06-01-2004 à 11:19:57    

J'avais vu (?R) y'a pas longtemps. Le probleme est que, comme le masque imbriquée enregistré est uniquement le dernier, l'interet est plutot limité. Si il y avait un moyen pour enregistrer tous les masques imbriqués ou non, ca serait la tres interessant !

Reply

Marsh Posté le 06-01-2004 à 17:15:14    

Merci Tentacle mais cela ne fonctionne pas parfaitement, en effet ton code ne traite pas correctement ma page:  
http://www.canard.ch/template.html
 
Reprenons tout depuis le début... Je cherche à parser en php du code html contenant des balises du type:
 
[NomBalise=Valeur]
   Contenu html...
[/NomBalise]
 
Prenons le code exemple suivant:
--------------------------------
 

Code :
  1. [STRUCTURE=main]
  2.    Contenu_1
  3.    [STRUCTURE=sub1]
  4.       Contenu_2
  5.       [STRUCTURE=subSub1]
  6.          Contenu_3
  7.       [/STRUCTURE]
  8.    [/STRUCTURE]
  9.    Contenu_4
  10.    [STRUCTURE=sub2]
  11.       Contenu_5
  12.    [/STRUCTURE]
  13.    [STRUCTURE=sub3]
  14.       [TEXT=bonjour]
  15.    [/STRUCTURE]
  16. [/STRUCTURE]


 
Je souhaite obtenir un tableau contenant chaque contenu de structure sans les structure internes
 
Exemple:
--------
 
[main]    => Contenu_1\nContenu_4
[sub1]    => Contenu_2
[subSub1] => Contenu_3
[sub2]    => Contenu_5
[sub3]    => [TEXT=bonjour]
 
J'avais pensé traiter les choses récursivement avec des expressions régulières mais celles-ci ne sont pas capable de faire si compliqué...
 
Je pensais ensuite utiliser les expressions régulière simplement pour me trouver les balises mais à partir de cela tout ce corse....
 
Admettons que je puisse récupérer la position du pointeur après le début de la première balise j'imagine le code suivant:
 
 

Code :
  1. $string = texte_a_analyser;
  2. while($data = SearchContent($string)) {
  3.    $string             = $data[contenu];
  4.    $struct[$data[tag]] = $data[nettoye];
  5. }
  6. function SearchContent($string) {
  7.    $i=0;
  8.    if($tag = SearchTag($string)) {
  9.       //On capture le contenu de la première balise reconnue
  10.       $inTag = TexteEntre($tag['start'],$tag['stop'], $string);
  11.  
  12.       //Ensuite on tente d'éliminer les balises internes
  13.       $inTagCleaned = $inTag;
  14.       while(SearchTag($inTagCleaned)) {
  15.          $inTagCleaned= TexteEntre(0              , $tag['start'], $inTagCleaned);
  16.          $inTagCleaned= TexteEntre($tag['end'], endOfFile($inTag), $inTagCleaned);
  17.       }
  18.       return $data = array('contenu' => $inTag, 'nettoye' => $inTagCleaned, 'tag' => $tag['tag']);
  19.    }
  20.    else return FALSE;
  21. }
  22. function SearchTag($string) {
  23.    $tag     = FALSE;
  24.    do {
  25.      if($p = SearchStartTag($string)) {
  26.         $pattern = "/\[STRUCTURE=\"?([a-z0-9_]*)\"?\]/i";
  27.         Preg_match($pattern,$string, $parts)
  28.         $tag['name'] = $parts[1];
  29.         $tag['start']= $p;
  30.         $i++;
  31.      }
  32.      if($p = SearchStopTag($string)) {
  33.         $i--;
  34.         $tag['stop']= $p;
  35.      }
  36.    } while(!$i);
  37.    return $pointer;
  38. }


 
Je trouve ce code très très très moche mais bon.. En plus il marche pas car je ne sais pas comment récupérer la position du pointeur après le tag trouvé...


Message édité par kalios le 06-01-2004 à 17:20:13

---------------
.:coin:.
Reply

Marsh Posté le 06-01-2004 à 17:54:28    

question con: tu pourrais pas faire du XML, comme tout le monde?

Reply

Marsh Posté le 06-01-2004 à 17:59:44    

gizmo a écrit :

question con: tu pourrais pas faire du XML, comme tout le monde?


 
Réponse bête: Non !!
 
Dans un éditeur html que la plulart des newbies utilisent: Dreamweaver, ou pire encore, front page, les balises xml sont invisibles...  
 
deux avantages des balises carrées: Elle sont visible directement dans la preview du code et elle ne se confondent pas avec le code html...


---------------
.:coin:.
Reply

Marsh Posté le 06-01-2004 à 17:59:44   

Reply

Marsh Posté le 06-01-2004 à 22:04:33    

Essaie cela :
 

Code :
  1. <?php
  2. function ExtractTags ($String, &$TagList, $TagName) {
  3. $Content = "";
  4. while (TRUE) {
  5.  if (preg_match ("/^(.*?)
  6.   (?:
  7.    (\[$TagName\=\"?(\w+)\"?\]) |
  8.    \[\/$TagName\]
  9.   )
  10.   (.*)$/msx", $String, $Matches)) {
  11.   $String = $Matches[4];
  12.   $Content .= $Matches[1];
  13.   if ($Matches[2]) { // Nouvelle Balise
  14.    list ($TagList[$Matches[3]], $String) = ExtractTags ($String, $TagList, $TagName);
  15.   } else { // Fermeture de Balise
  16.    return array ($Content, $String);
  17.   }
  18.  } else { // On a trouvé aucune balise ...
  19.   return array ($Content, $String);
  20.  }
  21. }
  22. }
  23. $TagList = array ();
  24. $String = "
  25. [STRUCTURE=main]
  26. Contenu_1
  27. [STRUCTURE=sub1]
  28.   Contenu_2
  29.   [STRUCTURE=subSub1]
  30.      Contenu_3
  31.   [/STRUCTURE] 
  32. [/STRUCTURE]
  33. Contenu_4
  34. [STRUCTURE=sub2]
  35.   Contenu_5
  36. [/STRUCTURE]
  37. [STRUCTURE=sub3]
  38.   [TEXT=bonjour]
  39. [/STRUCTURE]
  40. [/STRUCTURE]";
  41. ExtractTags ($String, $TagList, "STRUCTURE" );
  42. print_r ($TagList);
  43. ?>


 
Le résultat est dans $TagList;
Ya des trucs pas très beaux comme le fait de passer la string à l'appel et au retour de chaque fonction.
 
Enfin essaie voir si ça marche, et par contre voit si tu as besoin d'effacer tout les retours chariots et les tabulations qui apparaissent ...

Reply

Marsh Posté le 06-01-2004 à 22:14:15    

C'est joli, bravo.. Merci..  
 
Euh, je sais plus quoi dire...
 
Ca fonctionne à merveille...


---------------
.:coin:.
Reply

Marsh Posté le 06-01-2004 à 22:22:31    

Kalios a écrit :

C'est joli, bravo.. Merci..  
 
Euh, je sais plus quoi dire...
 
Ca fonctionne à merveille...
 


 
non sérieux, je sais vraiment plus quoi dire...


---------------
.:coin:.
Reply

Marsh Posté le 06-01-2004 à 22:44:50    

Kalios a écrit :


 
non sérieux, je sais vraiment plus quoi dire...


 
j'ai un peu maché le travail ? :) mais ça remet dans le bain ! Content d'avoir pu être utile.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed