[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
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
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...
|