Je veux convertir tous les textes d'une chaîne en entités html mais en préservant les balises HTML, par exemple ceci:
<p><font style="color:#FF0000">Camión español</font></p>
devrait être traduit en ceci:
<p><font style="color:#FF0000">Camión español</font></p>
des idées?
Vous pouvez obtenir la liste des correspondances caractère => entité utilisée par htmlentities
, avec la fonction get_html_translation_table
; considérez ce code:
$list = get_html_translation_table(HTML_ENTITIES);
var_dump($list);
(Vous voudrez peut-être vérifier le deuxième paramètre de cette fonction dans le manuel - vous devrez peut-être le définir sur une valeur différente de celle par défaut)
Cela vous donnera quelque chose comme ceci:
array
' ' => string ' ' (length=6)
'¡' => string '¡' (length=7)
'¢' => string '¢' (length=6)
'£' => string '£' (length=7)
'¤' => string '¤' (length=8)
....
....
....
'ÿ' => string 'ÿ' (length=6)
'"' => string '"' (length=6)
'<' => string '<' (length=4)
'>' => string '>' (length=4)
'&' => string '&' (length=5)
Maintenant, supprimez les correspondances dont vous ne voulez pas:
unset($list['"']);
unset($list['<']);
unset($list['>']);
unset($list['&']);
Votre liste contient maintenant toutes les correspondances character => entity utilisées par htmlentites, à l'exception des quelques caractères que vous ne voulez pas encoder.
Et maintenant, il suffit d'extraire la liste des clés et des valeurs:
$search = array_keys($list);
$values = array_values($list);
Et, enfin, vous pouvez utiliser str_replace pour effectuer 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ón español</font></p>' (length=84)
Qui ressemble à ce que vous vouliez ;-)
Edit: eh bien, sauf pour le problème d'encodage (putain UTF-8, je suppose - j'essaie de trouver une solution pour cela, et je vais éditer à nouveau)
Deuxième modification quelques minutes après: il semble que vous devrez utiliser utf8_encode
sur le $search
liste, avant d'appeler str_replace
:-(
Ce qui signifie utiliser quelque chose comme ça:
$search = array_map('utf8_encode', $search);
Entre l'appel à array_keys
et l'appel à str_replace
.
Et, cette fois, vous devriez vraiment obtenir ce que vous vouliez:
string '<p><font style="color:#FF0000">Camión español</font></p>' (length=70)
Et voici la partie complète du 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ón español</font></p>' (length=70)
Cette fois, ça devrait être ok ^^
Cela ne tient pas vraiment sur une seule ligne, ce n'est peut-être pas la solution la plus optimisée; mais cela devrait bien fonctionner, et a l'avantage de vous permettre d'ajouter/supprimer n'importe quel caractère de correspondance => entité dont vous avez besoin ou non.
S'amuser !
Peut-être pas terriblement efficace, mais ça marche
$sample = '<p><font style="color:#FF0000">Camión español</font></p>';
echo htmlspecialchars_decode(
htmlentities($sample, ENT_NOQUOTES, 'UTF-8', false)
, ENT_NOQUOTES
);
Il s'agit d'une version optimisée de la réponse acceptée.
$list = get_html_translation_table(HTML_ENTITIES);
unset($list['"']);
unset($list['<']);
unset($list['>']);
unset($list['&']);
$string = strtr($string, $list);
Aucune solution à court d'un analyseur ne sera correcte dans tous les cas. Le vôtre est un bon cas:
<p><font style="color:#FF0000">Camión español</font></p>
mais voulez-vous également soutenir:
<p><font>true if 5 < a && name == "joe"</font></p>
où vous voulez qu'il sorte:
<p><font>true if 5 < a && name == "joe"</font></p>
Question: Pouvez-vous faire l'encodage AVANT de construire le HTML. En d'autres termes, peut faire quelque chose comme:
"<p><font>" + htmlentities(inner) + "</font></p>"
Vous vous épargnerez beaucoup de chagrin si vous pouvez le faire. Si vous ne le pouvez pas, vous aurez besoin d'un moyen de sauter l'encodage <,> et "(comme décrit ci-dessus), ou simplement de tout encoder, puis de l'annuler (par exemple. replace('<', '<')
)
C'est une fonction que je viens d'écrire qui résout ce problème de manière très élégante:
Tout d'abord, les balises HTML seront extraites de la chaîne, puis htmlentities () est exécuté sur chaque sous-chaîne restante et après cela, les balises HTML d'origine seront insérées à leur ancienne position, ce qui n'entraînera aucune alternance des balises HTML. :-)
S'amuser:
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;
}
Basé sur la réponse de bflesch , j'ai fait quelques changements pour gérer la chaîne contenant less than sign
, greater than sign
et single quote
ou double quotes
.
function htmlentitiesOutsideHTMLTags ($htmlText, $ent)
{
$matches = Array();
$sep = '###HTMLTAG###';
preg_match_all(":</{0,1}[a-z]+[^>]*>:i", $htmlText, $matches);
$tmp = preg_replace(":</{0,1}[a-z]+[^>]*>:i", $sep, $htmlText);
$tmp = explode($sep, $tmp);
for ($i=0; $i<count($tmp); $i++)
$tmp[$i] = htmlentities($tmp[$i], $ent, 'UTF-8', false);
$tmp = join($sep, $tmp);
for ($i=0; $i<count($matches[0]); $i++)
$tmp = preg_replace(":$sep:", $matches[0][$i], $tmp, 1);
return $tmp;
}
Exemple d'utilisation:
$string = '<b>Is 1 < 4?</b>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€</strong><img src="/some/path" /></p></div>';
$string_entities = htmlentitiesOutsideHTMLTags($string, ENT_QUOTES | ENT_HTML401);
var_dump( $string_entities );
La sortie est:
string '<b>Is 1 < 4?</b>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€</strong><img src="/some/path" /></p></div>' (length=150)
Vous pouvez passer tout ent flag
selon le manuel htmlentities
solution à une ligne sans table de traduction ou fonction personnalisée requise:
je sais que c'est une vieille question, mais j'ai récemment dû importer un site statique dans un site wordpress et j'ai dû surmonter ce problème:
voici ma solution qui ne nécessite pas de tripoter les tables de traduction:
htmlspecialchars_decode( htmlentities( html_entity_decode( $string ) ) );
lorsqu'il est appliqué à la chaîne OP:
<p><font style="color:#FF0000">Camión español</font></p>
production:
<p><font style="color:#FF0000">Camión español</font></p>
lorsqu'il est appliqué à la chaîne de Luca:
<b>Is 1 < 4?</b>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€</strong><img src="/some/path" /></p></div>
production:
<b>Is 1 < 4?</b>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€</strong><img src="/some/path" /></p></div>