quot - htmlentities en PHP pero preservando las etiquetas html
php htmlspecialchars_decode (7)
En función de la respuesta de bflesch , realicé algunos cambios para administrar una cadena que contenga less than sign
, greater than sign
y single quote
o 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;
}
Ejemplo de uso:
$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 salida es:
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)
Puede pasar cualquier ent flag
acuerdo con el manual de htmlentities
Quiero convertir todos los textos en una cadena en entidades html pero conservando las etiquetas HTML, por ejemplo esto:
<p><font style="color:#FF0000">Camión español</font></p>
debe traducirse en esto:
<p><font style="color:#FF0000">Camión español</font></p>
¿algunas ideas?
Esta es la versión optimizada de la respuesta aceptada.
$list = get_html_translation_table(HTML_ENTITIES);
unset($list[''"'']);
unset($list[''<'']);
unset($list[''>'']);
unset($list[''&'']);
$string = strtr($string, $list);
Esta es una función que acabo de escribir que resuelve este problema de una manera muy elegante:
En primer lugar, las etiquetas HTML se extraerán de la cadena, luego se ejecutará htmlentities () en cada subcadena restante y luego las etiquetas HTML originales se insertarán en su posición anterior, lo que no ocasionará la alternancia de las etiquetas HTML. :-)
Que te diviertas:
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;
}
Ninguna solución, salvo un analizador, será correcta para todos los casos. El tuyo es un buen caso:
<p><font style="color:#FF0000">Camión español</font></p>
pero también quieres apoyar:
<p><font>true if 5 < a && name == "joe"</font></p>
donde quieres que salga como:
<p><font>true if 5 < a && name == "joe"</font></p>
Pregunta: ¿Puedes hacer la codificación ANTES de construir el HTML? En otras palabras, puede hacer algo como:
"<p><font>" + htmlentities(inner) + "</font></p>"
Te ahorrarás mucho dolor si puedes hacer eso. Si no puede, necesitará alguna forma de omitir la codificación <,> y "(como se describió anteriormente), o simplemente codificarlo todo, y luego deshacerlo (por ejemplo, replace(''<'', ''<'')
)
Puede obtener la lista de correspondencias carácter => entidad utilizada por htmlentities
, con la función get_html_translation_table
; considera este código:
$list = get_html_translation_table(HTML_ENTITIES);
var_dump($list);
(Es posible que desee verificar el segundo parámetro para esa función en el manual; tal vez necesite establecerlo en un valor diferente al predeterminado)
Te conseguirá algo como esto:
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)
Ahora, elimine las correspondencias que no desea:
unset($list[''"'']);
unset($list[''<'']);
unset($list[''>'']);
unset($list[''&'']);
Su lista, ahora, tiene todas las correspondencias character => entidad utilizada por htmlentites, excepto los pocos caracteres que no desea codificar.
Y ahora, solo tiene que extraer la lista de claves y valores:
$search = array_keys($list);
$values = array_values($list);
Y, finalmente, puede usar str_replace para hacer el reemplazo:
$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);
Y obtienes:
string ''<p><font style="color:#FF0000">Camión español</font></p>'' (length=84)
Que se parece a lo que querías ;-)
Edición: bueno, excepto por el problema de codificación (maldito UTF-8, supongo, estoy tratando de encontrar una solución para eso, y voy a editar de nuevo)
En segundo lugar, edita un par de minutos después: parece que tendrás que usar utf8_encode
en la lista $search
, antes de llamar a str_replace
:-(
Lo que significa usar algo como esto:
$search = array_map(''utf8_encode'', $search);
Entre la llamada a array_keys
y la llamada a str_replace
.
Y, esta vez, realmente deberías obtener lo que querías:
string ''<p><font style="color:#FF0000">Camión español</font></p>'' (length=70)
Y aquí está la porción completa del código:
$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);
Y la salida completa:
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)
Esta vez, debería estar bien ^^
Realmente no cabe en una línea, puede que no sea la solución más optimizada; pero debería funcionar bien, y tiene la ventaja de permitirle agregar / eliminar cualquier carácter de correspondencia => entidad que necesite o no.
Que te diviertas !
Puede que no sea terriblemente eficiente, pero funciona
$sample = ''<p><font style="color:#FF0000">Camión español</font></p>'';
echo htmlspecialchars_decode(
htmlentities($sample, ENT_NOQUOTES, ''UTF-8'', false)
, ENT_NOQUOTES
);
Se necesita una solución de una línea con NO tabla de traducción o función personalizada:
Sé que esta es una vieja pregunta, pero recientemente tuve que importar un sitio estático en un sitio de wordpress y tuve que superar este problema:
aquí está mi solución que no requiere htmlspecialchars_decode( htmlentities( html_entity_decode( $string ) ) );
tablas de traducción: htmlspecialchars_decode( htmlentities( html_entity_decode( $string ) ) );
cuando se aplica a la cadena de OP:
<p><font style="color:#FF0000">Camión español</font></p>
salida:
<p><font style="color:#FF0000">Camión español</font></p>
cuando se aplica a la cuerda 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>
salida:
<b>Is 1 < 4?</b>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€</strong><img src="/some/path" /></p></div>
EDITAR: esto funciona especialmente bien "blanqueando" la cadena de entrada primero:
$string = preg_replace( ''/[^/x00-/x7F]/'', null, $string ); htmlspecialchars_decode( htmlentities( html_entity_decode( $string ) ) );
ahora $ string es muuuy bonito !!