htmlentities in PHP, ma preservando i tag html
-
21-09-2019 - |
Domanda
voglio convertire tutti i testi in una stringa in entità HTML, ma preservando i tag HTML, ad esempio questo:
<p><font style="color:#FF0000">Camión español</font></p>
dovrebbe essere tradotto in questo modo:
<p><font style="color:#FF0000">Camión español</font></p>
tutte le idee?
Soluzione
È possibile ottenere l'elenco di carattere corrispondenze => un'entità usata da htmlentities
, con la funzione get_html_translation_table
; considerare questo codice:
$list = get_html_translation_table(HTML_ENTITIES);
var_dump($list);
(si potrebbe voler controllare il secondo parametro a tale funzione nel manuale - forse è necessario impostarlo su un valore diverso da quello predefinito)
Si otterrà qualcosa di simile:
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)
Ora, rimuovere le corrispondenze non si vuole:
unset($list['"']);
unset($list['<']);
unset($list['>']);
unset($list['&']);
Il tuo elenco, ora, ha tutto il carattere corrispondenze => un'entità usata da htmlentites, tranne i pochi caratteri non si desidera codificare.
E ora, non resta che estrarre l'elenco di chiavi e valori:
$search = array_keys($list);
$values = array_values($list);
E, infine, è possibile utilizzare str_replace per fare la sostituzione:
$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);
E si ottiene:
string '<p><font style="color:#FF0000">Camión español</font></p>' (length=84)
che assomiglia a quello che si voleva; -)
Edit: bene, tranne per il problema di codifica (maledetto UTF-8, suppongo - Sto cercando di trovare una soluzione per questo, e permetterà di modificare di nuovo)
Seconda modifica paio di minuti dopo: sembra dovrete usare utf8_encode
sulla lista $search
, prima di chiamare str_replace
: - (
Il che significa usare qualcosa di simile a questo:
$search = array_map('utf8_encode', $search);
Tra la chiamata alla array_keys
e la chiamata a str_replace
.
E, questa volta, si dovrebbe davvero ottenere ciò che si voleva:
string '<p><font style="color:#FF0000">Camión español</font></p>' (length=70)
E qui è la parte piena di codice:
$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);
E l'output completo:
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)
Questa volta, dovrebbe essere ok ^^
Essa non si adatta in realtà in una sola riga, è potrebbe non essere la soluzione più ottimizzata; ma dovrebbe funzionare bene, e ha il vantaggio di permettere di aggiungere / rimuovere qualsiasi carattere corrispondenza => entità è necessario o meno.
Buon divertimento!
Altri suggerimenti
Potrebbe non essere terribilmente efficace, ma funziona
$sample = '<p><font style="color:#FF0000">Camión español</font></p>';
echo htmlspecialchars_decode(
htmlentities($sample, ENT_NOQUOTES, 'UTF-8', false)
, ENT_NOQUOTES
);
Questa versione è ottimizzata della risposta accettata.
$list = get_html_translation_table(HTML_ENTITIES);
unset($list['"']);
unset($list['<']);
unset($list['>']);
unset($list['&']);
$string = strtr($string, $list);
No soluzione a breve di un parser sta per essere corretto per tutti i casi. Il vostro è un buon esempio:
<p><font style="color:#FF0000">Camión español</font></p>
, ma si fa anche si vuole sostenere:
<p><font>true if 5 < a && name == "joe"</font></p>
dove vuoi che a venire fuori come:
<p><font>true if 5 < a && name == "joe"</font></p>
Domanda: Si può fare la codifica prima di costruire il codice HTML. In altre parole, si può fare qualcosa di simile:
"<p><font>" + htmlentities(inner) + "</font></p>"
Potrai risparmiare un sacco di dolore, se si può fare. Se non è possibile, avrete bisogno di un certo modo di saltare la codifica <,>, e "(come descritto sopra), o semplicemente codificare tutto, e poi annullarla (ad es. replace('<', '<')
)
Questa è una funzione che ho appena scritto che risolve questo problema in un modo molto elegante:
Prima di tutto, i tag HTML verrà estratto dalla stringa, quindi htmlentities () viene eseguito su ogni stringa rimanente e dopo che i tag HTML originali saranno inseriti nella loro vecchia posizione conseguente nessun alternanza dei tag HTML . : -)
Buon divertimento:
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;
}
In base alla risposta di bflesch , ho fatto alcune modifiche per gestire stringa contenente less than sign
, greater than sign
e 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;
}
Esempio di utilizzo:
$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 );
L'uscita è:
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)
È possibile passare qualsiasi ent flag
secondo il htmlentities manuale
soluzione one-linea con NO funzione di tabella di conversione o personalizzato richiesto:
So che questa è una vecchia questione, ma di recente ho dovuto importare un sito statico in un sito WordPress e ha dovuto superare questo problema:
Questa è la mia soluzione che non richiede giocherellare con tabelle di conversione:
htmlspecialchars_decode( htmlentities( html_entity_decode( $string ) ) );
quando applicato alla stringa del PO:
<p><font style="color:#FF0000">Camión español</font></p>
uscita:
<p><font style="color:#FF0000">Camión español</font></p>
quando applicato alla stringa di 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>
uscita:
<b>Is 1 < 4?</b>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€</strong><img src="/some/path" /></p></div>