60 votes

htmlentities en PHP mais en préservant les balises html

Je veux convertir tous les textes dans une chaîne de caractères en entités html mais en préservant les balises HTML, par exemple comme ceci:

<p><font style="color:#FF0000">Camión español</font></p>

doivent être traduits en ceci:

<p><font style="color:#FF0000">Cami&oacute;n espa&ntilde;ol</font></p>

des idées?

69voto

Pascal MARTIN Points 195780

Vous pouvez obtenir la liste des correspondances de caractères => entité utilisée par htmlentities, avec la fonction get_html_translation_table ; envisager ce code :

$list = get_html_translation_table(HTML_ENTITIES);
var_dump($list);

(Vous voudrez peut-être consulter le deuxième paramètre à cette fonction dans le manuel, peut-être que vous aurez besoin de le mettre à une valeur différente de celle par défaut)

Il sera vous obtenez quelque chose comme ceci :

array
  ' ' => string '&nbsp;' (length=6)
  '¡' => string '&iexcl;' (length=7)
  '¢' => string '&cent;' (length=6)
  '£' => string '&pound;' (length=7)
  '¤' => string '&curren;' (length=8)
  ....
  ....
  ....
  'ÿ' => string '&yuml;' (length=6)
  '"' => string '&quot;' (length=6)
  '<' => string '&lt;' (length=4)
  '>' => string '&gt;' (length=4)
  '&' => string '&amp;' (length=5)

Maintenant, retirez les correspondances que vous ne voulez pas :

unset($list['"']);
unset($list['<']);
unset($list['>']);
unset($list['&']);

Votre liste, maintenant, de toutes les correspondances de caractères => entité utilisée par htmlentites, sauf quelques-uns des personnages que vous ne voulez pas de l'encodage.

Et maintenant, vous avez juste à extraire la liste des clés et valeurs :

$search = array_keys($list);
$values = array_values($list);

Et, enfin, vous pouvez utiliser str_replace pour faire le remplacement :

$str_in = '<p><font style="color:#FF0000">Camión español</font></p>';
$str_out = str_replace($search, $values, $str_in);
var_dump($str_out);

Et vous obtenez :

string '<p><font style="color:#FF0000">Cami&Atilde;&sup3;n espa&Atilde;&plusmn;ol</font></p>' (length=84)

Qui ressemble à ce que tu voulais ;-)


Edit : bien, sauf pour le problème d'encodage (putain UTF-8, je suppose-j'essaie de trouver une solution pour que, et de modifier à nouveau)

Edit deuxième couple de minutes après : il semble que vous devez utiliser utf8_encode sur le $search liste avant d'appeler str_replace :-(

Ce qui signifie en utilisant quelque chose comme ceci :

$search = array_map('utf8_encode', $search);

Entre l'appel à l' array_keys , et l'appel d' str_replace.

Et, cette fois, vous devriez vraiment obtenir ce que tu voulais :

string '<p><font style="color:#FF0000">Cami&oacute;n espa&ntilde;ol</font></p>' (length=70)


Et ici, c'est la pleine partie de code :

$list = get_html_translation_table(HTML_ENTITIES);
unset($list['"']);
unset($list['<']);
unset($list['>']);
unset($list['&']);

$search = array_keys($list);
$values = array_values($list);
$search = array_map('utf8_encode', $search);

$str_in = '<p><font style="color:#FF0000">Camión español</font></p>';
$str_out = str_replace($search, $values, $str_in);
var_dump($str_in, $str_out);

Et la sortie complète :

string '<p><font style="color:#FF0000">Camión español</font></p>' (length=58)
string '<p><font style="color:#FF0000">Cami&oacute;n espa&ntilde;ol</font></p>' (length=70)

Cette fois, il devrait être ok ^^
Il ne rentre pas vraiment dans une ligne, est peut-être pas le plus optimisé solution, mais il devrait fonctionner très bien, et a l'avantage de vous permettre d'ajouter/supprimer toute correspondance personnage => entité dont vous avez besoin ou pas.

Amusez-vous !

18voto

Peter Bailey Points 62125

Pourrait ne pas être terriblement efficace, mais il fonctionne

$sample = '<p><font style="color:#FF0000">Camión español</font></p>';

echo htmlspecialchars_decode( htmlentities( $sample, ENT_NOQUOTES, 'UTF-8', false ), ENT_NOQUOTES );

7voto

SileNT Points 443

C'est la version optimisée de la accepté de répondre.

$list = get_html_translation_table(HTML_ENTITIES);
unset($list['"']);
unset($list['<']);
unset($list['>']);
unset($list['&']);

$string = strtr($string, $list);

5voto

ndp Points 8959

Pas de solution à court d'un analyseur va être correct pour tous les cas. Le vôtre est une bonne affaire:

<p><font style="color:#FF0000">Camión español</font></p>

mais voulez-vous aussi à l'appui:

<p><font>true if 5 < a && name == "joe"</font></p>

où vous voulez en sortir:

<p><font>true if 5 &lt; a &amp;&amp; name == &quot;joe&quot;</font></p>

Question: Pouvez-vous faire de l'encodage AVANT de générer le code HTML. En d'autres termes peut faire quelque chose comme:

"<p><font>" + htmlentities(inner) + "</font></p>"

Vous vous éviterez beaucoup de chagrin si vous pouvez le faire. Si vous ne pouvez pas, vous aurez besoin d'une certaine manière afin de sauter d'encodage <, >, et " (comme décrit ci-dessus), ou simplement encoder tout ça, et puis l'annuler (par exemple. replace('&lt;', '<'))

3voto

bflesch Points 323

C'est une fonction que j'ai juste écrit ce qui résout ce problème dans un moyen très élégant:

Tout d'abord, les balises HTML seront extraits de la chaîne, puis htmlentities() est exécutée sur toutes les sous-chaîne et après que, à l'origine des balises HTML seront insérés à leur ancienne position, ce qui entraîne dans les pas de l'alternance des balises HTML. :-)

Amusez-vous:

function htmlentitiesOutsideHTMLTags ($htmlText)
{
    $matches = Array();
    $sep = '###HTMLTAG###';

    preg_match_all("@<[^>]*>@", $htmlText, $matches);   
    $tmp = preg_replace("@(<[^>]*>)@", $sep, $htmlText);
    $tmp = explode($sep, $tmp);

    for ($i=0; $i<count($tmp); $i++)
        $tmp[$i] = htmlentities($tmp[$i]);

    $tmp = join($sep, $tmp);

    for ($i=0; $i<count($matches[0]); $i++)
        $tmp = preg_replace("@$sep@", $matches[0][$i], $tmp, 1);

    return $tmp;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X