Algorithme de parsing ...

LocalStone Messages postés 514 Date d'inscription mercredi 19 mars 2003 Statut Membre Dernière intervention 1 mars 2009 - 26 févr. 2007 à 14:48
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 - 28 févr. 2007 à 18:19
Salut à tous,
Une fois n'est pas coutume, j'ai une petite question n'a pas de rapport direct avec le PHP puisque c'est plus une question d'algorithmie.
Je suis en train de faire une petite classe pour parser du HTML. Et pour l'instant, je veux juste savoir si une balise est ouvrante ou fermante ou alors si c'est un noeud de texte, sachant que je ne peux lire la source que mot par mot. Pour cela, ma classe possède une petite méthode jHtmlParser :: readNextToken() qui se charge de faire ça (sachant qu'un token, c'est soit "<", soit ">", soit "/", soit une chaine de caractère entre simple ou double quote soit un mot (html, div, onload, ...)). Je précise que si je fais ce choix de parsing à la volée, c'est pour que le parsing soit le plus rapide possible.
La fonction principale jHtmlParser :: parse() est codée comme cela :

      public function parse()
      {
         $text = '';
         while(!$this -> isEndOfSource())
         {
            $token = $this -> readNextToken();
            if($token == '<')
            {
               if(trim($text) != '')
               {
                  echo "On a un noeud de texte : $text. \n";
               }
               $text = '';
              
               $token = $this -> readNextToken();
               if($token == '/')
               {
                  $token = $this -> readNextToken();
                  echo "on a une balise fermante : $token. \n";
                  $this -> readNextToken();
               }
               else
               {
                  echo "On a une balise ouvrante : $token dont les attributs sont : \n";
                  $attributes = array();
                  while(true)
                  {
                     $token = $this -> readNextToken();
                                          if($token '/') $token $this -> readNextToken();
                     if($token == '>') break;
                    
                     $key = $token;
                     if($this -> readNextToken() != "=")
                        throw new Exception("???");
                     $value = $this -> readNextToken();
                    
                     $attributes[$key] = $value;
                  }
                  echo "Dont les attributs sont : ";
                  print_r($attributes);
               }
            }
            else
            {
               $text .= ' '.$token;
            }
         }
     
      }

Alors l'avantage, c'est que ça marche plutôt bien. Mais le soucis, c'est que c'est moche. Surtout l'astuce pour récuperer les noeuds de texte. Alors si quelqu'un à une bonne solution à proposer ... Je suis preneur !

3 réponses

coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
28 févr. 2007 à 12:56
Salut,

personellement, j'aurais fait une pile, ca permet de verifier en meme temps l'ordre des balises...

le result aurait ete une pile de balises ouvertes, et un tableau de texte

In a dream, I saw me, drop dead... U was there, U cried... It was just a dream, if I die, U won't cry, maybe, U'll be happy

Mon site (articles sur la programmation et programmes)
0
LocalStone Messages postés 514 Date d'inscription mercredi 19 mars 2003 Statut Membre Dernière intervention 1 mars 2009
28 févr. 2007 à 13:44
Euh ... J'ai pas tout compris ! Mais l'idée de la pile est interessante. Tu peux détailler un peu ?
Merci !
LocalStone
0
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
28 févr. 2007 à 18:19
Salut,

en C++ :

tu te fais une class Balise (gestion des attribnuts ect...)
tu te fais une classe ParseurXML (le html etant proche....)

dans ParseurXML, une liste se String et une liste de Balise et une pile string pour le nom des balises (generer des erreurs lors des rencontres de balises croisees par exemples ou balises non fermees)

quand tu croises une balise, tu l'empile et la place dans la liste, quand tu croises la fermeture, tu la depiles. ensuite, soit tu geres le texte avec un truc qui contiendrait le debut et la fin de chaque balise (dans ce cas, la liste de String ne sert a rien) soit dans la liste de String, tu places toutes les chaines entre les balises

In a dream, I saw me, drop dead... U was there, U cried... It was just a dream, if I die, U won't cry, maybe, U'll be happy

Mon site (articles sur la programmation et programmes)
0
Rejoignez-nous