Algorithme de parsing ...

Signaler
Messages postés
514
Date d'inscription
mercredi 19 mars 2003
Statut
Membre
Dernière intervention
1 mars 2009
-
Messages postés
12303
Date d'inscription
mardi 10 février 2004
Statut
Modérateur
Dernière intervention
30 juillet 2012
-
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

Messages postés
12303
Date d'inscription
mardi 10 février 2004
Statut
Modérateur
Dernière intervention
30 juillet 2012
39
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)
Messages postés
514
Date d'inscription
mercredi 19 mars 2003
Statut
Membre
Dernière intervention
1 mars 2009

Euh ... J'ai pas tout compris ! Mais l'idée de la pile est interessante. Tu peux détailler un peu ?
Merci !
LocalStone
Messages postés
12303
Date d'inscription
mardi 10 février 2004
Statut
Modérateur
Dernière intervention
30 juillet 2012
39
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)