JeuWeb - Crée ton jeu par navigateur
[XSL] Fermer balises html - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : [XSL] Fermer balises html (/showthread.php?tid=5580)

Pages : 1 2


[XSL] Fermer balises html - Wells - 23-07-2011

Lorsqu'on parse un xml contenant du html via xsl, ce genre de chaines ne sont pas correctes:

Code :
<p align="left"><p class="center">hfhgfhgf</p> <br /> <br /> <br /> <u>hgf<b>hgfh</b>gfh <br /> <br /> <br /> <br /> <font style="font-family:Georgia">hhttrhtrytryr[tytftre<font color="#3366CC">e]</font></u></p></font>

Les balises sont bien toutes fermées mais mal imbriqué (la "font" démare dans le "p" mais se fermer en dehors)

Avez vous vent de méthodes pour compléter des fermetures fermantes oubliés et les mettres au bon endroit?


RE: [XSL] Fermer balises html - Slavick - 23-07-2011

Je ne connais pas de solution qui pourrait corriger ce problème. Je trouve bête de devoir faire du post-traitement de données incorrectes ; alors que si c'est correct à la source, il n'y a pas besoin de faire de corrections.

A moins que tu n'es aucun contrôle sur la source de tes données...


RE: [XSL] Fermer balises html - Sephi-Chan - 23-07-2011

C'est un peu l'horreur ce HTML. D'où provient-il ? Ne peut-il rien avoir de mieux en entrée ? :/

Il existe bien des parser HTML capables de corriger du code moisi.
En Ruby, il y a Nokogiri mais je ne sais pas si il existe un équivalent si puissant en PHP.


fucked_html = '...'
document = Nokogiri.parse(fucked_html)
clean_html = document.to_html

Depuis la source que tu as donné, voici le résultat :

Citation :<p align="left">
<p class="center">hfhgfhgf</p>
<br><br><br>
<u>
hgf
<b>hgfh</b>
gfh
<br><br><br><br>
<font style="font-family:Georgia">
hhttrhtrytryr[tytftre<font color="#3366CC">e]</font>
</font>
</u>
</p>



RE: [XSL] Fermer balises html - Kassak - 23-07-2011

Le site W3C propose aussi un outil pour nettoyer le code html lorsque tu valides une page Wink

Avec ton code on obtient ça :

<style type="text/css">
span.c4 {text-decoration: underline}
span.c3 {font-family:Georgia}
span.c2 {color: #3366CC}
p.c1 {text-align: left}
</style>
</head>
<body>
<p class="c1"></p>
<p class="center">hfhgfhgf</p>
<br>
<br>
<br>
<span class="c4">hgf<strong>hgfh</strong>gfh<br>
<br>
<br>
<br>
<span class="c3">hhttrhtrytryr[tytftre<span class="c2">e]</span></span></span><span class="c3"><br>
<br></span>

Après je sais pas ce que ça vaut ! C'est sûrement plutôt moisi Wink


RE: [XSL] Fermer balises html - php_addict - 23-07-2011

à tester, mais en php:

--> http://simplehtmldom.sourceforge.net/ (Supports invalid HTM)
--> http://docs.php.net/manual/en/domdocument.loadhtml.php


RE: [XSL] Fermer balises html - Wells - 25-07-2011

J'ai fait ce petit bout de code qui corrige les problemes les plus courant (oublie de fermeture de balise)

Code :
<?php
class WChainesHTML
    {
    public $debug=0;
    public $nb_balise_ouvrante=0;
    public $nb_balise_fermante=0;
    public $Texte;
    public $decalage=0;
    public $Balises=array('u','a','p','i','div','span','font','b','center');
    
    function __tostring() {return "Cette classe permet de fermer les balises html en trop.";}
    

    //Constructeur
    function __construct($texte)
        {
        $this->Texte=$texte;
        if($this->debug==1) echo "<br>".htmlentities($this->Texte,ENT_IGNORE, "UTF-8");            
            
        //pour chaque balise qu'on vérifie
        foreach($this->Balises as $balise)
            {
            $this->nb_balise_ouvrante = substr_count($this->Texte,'<'.$balise.'>')+substr_count($this->Texte,'<'.$balise.' ');
            $this->nb_balise_fermante = substr_count($this->Texte,'</'.$balise.'>');
            if($this->debug==1) echo "<br>".$balise.'/'.$this->nb_balise_ouvrante.'/'.$this->nb_balise_fermante."<br>";
        
            if($this->nb_balise_ouvrante!=$this->nb_balise_fermante)
                {
                if($this->nb_balise_ouvrante>$this->nb_balise_fermante) $this->ajoute_chaine_fermante($balise);
                if($this->nb_balise_ouvrante<$this->nb_balise_fermante) $this->ajoute_chaine_ouvrante($balise);
                if($this->debug==1) echo "<br>".htmlentities($this->Texte,ENT_IGNORE, "UTF-8").'<hr>';
                }
            }
        
        if($this->debug==1) {
        echo "<br><br><br>".htmlentities($this->Texte,ENT_IGNORE, "UTF-8");
        echo "<br>";
        for($i=0;$i<strlen($this->Texte);$i++)
            echo $i.'-'.substr($this->Texte,$i,1)."<br>";}
        }
    
    
    function trouve_chaine_ouvrante($texte,$balise)
        {
        $po=0;$POSITIONS_OUVRANTES=array();
        $text_temp=$texte;
        do
            {
            $pos_pure=strpos($text_temp,'<'.$balise.' ');
            if($po>0) $pos=$pos_pure+$POSITIONS_OUVRANTES[$po-1]+2+strlen($balise);
            else $pos=$pos_pure;
            $text_temp=substr($text_temp,$pos_pure+2+strlen($balise),strlen($text_temp)-$pos_pure-2-strlen($balise));
            if($pos>-1) {$POSITIONS_OUVRANTES[$po]=$pos; $po++;}
            }
        while(!strpos($text_temp,'<'.$balise.' ')===false);
        
        
        $po=0;$POSITIONS_OUVRANTES2=array();
        $text_temp=$texte;
        do
            {
            $pos_pure=strpos($text_temp,'<'.$balise.'>');
            if($po>0) $pos=$pos_pure+$POSITIONS_OUVRANTES2[$po-1]+2+strlen($balise);
            else $pos=$pos_pure;
            $text_temp=substr($text_temp,$pos_pure+2+strlen($balise),strlen($text_temp)-$pos_pure-2-strlen($balise));
            if($pos>-1) {$POSITIONS_OUVRANTES2[$po]=$pos; $po++;}
            }
        while(!strpos($text_temp,'<'.$balise.'>')===false);
    
        return array_merge($POSITIONS_OUVRANTES,$POSITIONS_OUVRANTES2);
        }
        
    function trouve_chaine_fermante($texte,$balise)
        {
        $po=0;$POSITIONS_FERMANTES=array();
        $text_temp=$texte;
        do
            {
            $pos_pure=strpos($text_temp,'</'.$balise.'>');
            if($po>0) $pos=$pos_pure+$POSITIONS_FERMANTES[$po-1]+3+strlen($balise);
            else $pos=$pos_pure;
            $text_temp=substr($text_temp,$pos_pure+3+strlen($balise),strlen($text_temp)-$pos_pure-3-strlen($balise));
            if($pos>-1) {$POSITIONS_FERMANTES[$po]=$pos; $po++;}
            }
        while(!strpos($text_temp,'</'.$balise.'>')===false);
            
        return $POSITIONS_FERMANTES;
        }
    
    function ajoute_chaine_fermante($balise)
        {
        //on récupére les positions des balises ouvrantes et fermantes
        $POSITIONS_OUVRANTES=$this->trouve_chaine_ouvrante($this->Texte,$balise);sort($POSITIONS_OUVRANTES);
        if($this->debug==1) echo "<br>"; if($this->debug==1) print_r($POSITIONS_OUVRANTES);
        $POSITIONS_FERMANTES=$this->trouve_chaine_fermante($this->Texte,$balise);sort($POSITIONS_FERMANTES);
        if($this->debug==1) echo "<br>"; if($this->debug==1) print_r($POSITIONS_FERMANTES);
            
        foreach($POSITIONS_OUVRANTES as $cle=>$position)
            {
            $pos1=$position+$this->decalage;
            if(array_key_exists($cle+1,$POSITIONS_OUVRANTES)) $pos2=$POSITIONS_OUVRANTES[$cle+1]+$this->decalage;
            else $pos2=0;
            if($this->debug==1) echo "<br>".$pos1.'/'.$pos2;    
    
            //si il y a au moins une balise fermante
            $pos_fermante=-1;
            if(count($POSITIONS_FERMANTES)>0)
                {foreach($POSITIONS_FERMANTES as $cle=>$positionf) if($positionf>$pos1) {$pos_fermante=$positionf+$this->decalage; break;}}
            else
                $pos_fermante=-2;
                
            //si la balise fermante est entre deux balises ouvrantes, on ferme directement
            if($pos_fermante>0 and $pos_fermante>$pos2)
                {
                $fermeture= strpos($this->Texte,'>',$pos1);
                if($this->debug==1) echo "<br>".$fermeture;    
                $this->Texte=substr($this->Texte,0,$fermeture+1).'</'.$balise.'>'.substr($this->Texte,$fermeture+1,strlen($this->Texte)-$fermeture-1);
                $this->nb_balise_fermante++;
                $this->decalage+=strlen('</'.$balise.'>');
                }
            elseif($pos_fermante==-2)//si on est à la fin, on ferme
                {
                $fermeture= strpos($this->Texte,'>',$pos1);
                $this->Texte=substr($this->Texte,0,$fermeture+1).'</'.$balise.'>'.substr($this->Texte,$fermeture+1,strlen($this->Texte)-$fermeture-1);
                $this->nb_balise_fermante++;
                $this->decalage+=strlen('</'.$balise.'>');
                }
                
            if($this->nb_balise_ouvrante==$this->nb_balise_fermante) break;
            }
        }
    
    function ajoute_chaine_ouvrante($balise)
        {
        //on récupére les positions des balises ouvrantes et fermantes
        $POSITIONS_OUVRANTES=$this->trouve_chaine_ouvrante($this->Texte,$balise);
        if($this->debug==1) echo "<br>"; if($this->debug==1) print_r($POSITIONS_OUVRANTES);
        $POSITIONS_FERMANTES=$this->trouve_chaine_fermante($this->Texte,$balise);
        if($this->debug==1) echo "<br>"; if($this->debug==1) print_r($POSITIONS_FERMANTES);
            
        foreach($POSITIONS_FERMANTES as $cle=>$position)
            {
            $pos1=$position+$this->decalage;
            if(array_key_exists($cle-1,$POSITIONS_FERMANTES)) $pos2=$POSITIONS_FERMANTES[$cle-1]+$this->decalage;
            else $pos2=1000000;
            if($this->debug==1) echo "<br>".$pos2.'/'.$pos1;    
    
            //si il y a au moins une balise fermante
            $pos_ouvr=10000000;
            if(count($POSITIONS_OUVRANTES)>0)
                {foreach($POSITIONS_OUVRANTES as $cle=>$positiono) if($positiono<$pos1) {$pos_ouvr=$positiono+$this->decalage; break;}}
            else
                $pos_ouvr=20000000;
                
            //si la balise fermante est entre deux balises ouvrantes, on ferme directement
            if($pos_ouvr<10000000 and $pos_ouvr>$pos2)
                {
                $this->Texte=substr($this->Texte,0,$pos1).'<'.$balise.'>'.substr($this->Texte,$pos1,strlen($this->Texte)-$pos1);
                $this->nb_balise_ouvrante++;
                $this->decalage+=strlen('</'.$balise.'>')-1;
                }
            elseif($pos_ouvr==20000000)//si on est à la fin, on ferme
                {
                $this->Texte=substr($this->Texte,0,$pos1).'<'.$balise.'>'.substr($this->Texte,$pos1,strlen($this->Texte)-$pos1);
                $this->nb_balise_ouvrante++;
                $this->decalage+=strlen('</'.$balise.'>')-1;
                }
                
            if($this->nb_balise_ouvrante==$this->nb_balise_fermante) break;
            }
        }
    }
?>

Maintenant il ne gere par l'imbrication foireuse dans tous les cas.

Par exemple:
Code :
<p>test<font>a</p></font>
rendra du code html mais ne sera pas valide.

Ton code ruby est il capable de corriger ca?









RE: [XSL] Fermer balises html - Roworll - 25-07-2011

Tu as jeté un œil à la classe Tidy de PHP ?


RE: [XSL] Fermer balises html - Arius Vistoon - 25-07-2011

(23-07-2011, 02:40 AM)Slavick a écrit : Je ne connais pas de solution qui pourrait corriger ce problème. Je trouve bête de devoir faire du post-traitement de données incorrectes ; alors que si c'est correct à la source, il n'y a pas besoin de faire de corrections.

A moins que tu n'es aucun contrôle sur la source de tes données...

Tout pareil !
donc tu n'as aucun contrôle sur les données sources c'est bien cela ? Tu reçois donc un flux incertain (potentiellement malveillant) que tu dois transformer ?


RE: [XSL] Fermer balises html - Viciousity - 25-07-2011

Heu avant de t'aider, c'est pour du BBCode ? :S


RE: [XSL] Fermer balises html - Argorate - 26-07-2011

(25-07-2011, 05:49 PM)Arius Vistoon a écrit :
(23-07-2011, 02:40 AM)Slavick a écrit : Je ne connais pas de solution qui pourrait corriger ce problème. Je trouve bête de devoir faire du post-traitement de données incorrectes ; alors que si c'est correct à la source, il n'y a pas besoin de faire de corrections.

A moins que tu n'es aucun contrôle sur la source de tes données...

Tout pareil !
donc tu n'as aucun contrôle sur les données sources c'est bien cela ? Tu reçois donc un flux incertain (potentiellement malveillant) que tu dois transformer ?

C'est pour un forum, vous n'avez forcement pas le controle de se que va taper le client... Wink