htmlentities в PHP, но сохранение html-тегов

Я хочу преобразовать все тексты в строку в html-объекты, но сохраняя теги HTML, например:

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

следует перевести на это:

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

есть идеи?

Вы можете получить список соответствий character => entity, используемый htmlentities , с функцией get_html_translation_table ; рассмотрите этот код:

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

(Возможно, вы захотите проверить второй параметр на эту функцию в руководстве – возможно, вам нужно будет установить значение, отличное от значения по умолчанию)

Это даст вам что-то вроде этого:

 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) 

Теперь удалите соответствующие вам соответствия:

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

Теперь ваш список имеет все атрибуты character =>, которые используются htmlentites, за исключением нескольких символов, которые вы не хотите кодировать.

И теперь вам просто нужно извлечь список ключей и значений:

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

И, наконец, вы можете использовать str_replace для замены:

 $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); 

И вы получаете:

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

Который выглядит так, как вы хотели 😉

Edit: ну, кроме проблемы с кодировкой (черт побери UTF-8, я полагаю, я пытаюсь найти решение для этого и снова отредактировать)

Второе редактирование через пару минут после: похоже, вам нужно будет использовать utf8_encode в списке $search , прежде чем вызывать str_replace 🙁

Это означает использование чего-то вроде этого:

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

Между вызовом array_keys и вызовом str_replace .

И на этот раз вам действительно нужно получить то, что вы хотели:

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

И вот полная часть кода:

 $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); с $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); с $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); с $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); с $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); 

И полный вывод:

 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) 

На этот раз это должно быть нормально ^^
Это не очень подходит в одной строке, возможно, это не самое оптимизированное решение; но он должен работать нормально и имеет то преимущество, что вы можете добавить / удалить любой соответствующий символ => объект, который вам нужен, или нет.

Повеселись !

Не может быть ужасно эффективным, но он работает

 $sample = '<p><font style="color:#FF0000">Camión español</font></p>'; echo htmlspecialchars_decode( htmlentities($sample, ENT_NOQUOTES, 'UTF-8', false) , ENT_NOQUOTES ); 

Это оптимизированная версия принятого ответа.

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

Никакое решение, не содержащее синтаксический анализатор, будет правильным для всех случаев. Ваш хороший пример:

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

но вы также хотите поддержать:

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

где вы хотите, чтобы он появился как:

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

Вопрос: Можете ли вы сделать кодировку ДО того, как вы создаете HTML. Другими словами, можно сделать что-то вроде:

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

Вы можете сэкономить много горя, если сможете это сделать. Если вы не можете, вам нужно каким-то образом пропустить кодировку <,> и "(как описано выше) или просто закодировать все, а затем отменить (например, replace('&lt;', '<') )

Это функция, которую я только что написал, которая решает эту проблему очень элегантно:

Прежде всего, теги HTML будут извлечены из строки, затем htmlentities () выполняется на каждой оставшейся подстроке, после чего исходные HTML-теги будут вставлены в их старую позицию, что не приведет к чередованию HTML-тегов. 🙂

Повеселись:

 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; } 

Основываясь на ответе bflesch , я сделал некоторые изменения для управления строкой, содержащей less than sign , greater than sign и single quote или double quotes .

 function htmlentitiesOutsideHTMLTags ($htmlText, $ent) { $matches = Array(); $sep = '###HTMLTAG###'; preg_match_all(":</{0,1}[az]+[^>]*>:i", $htmlText, $matches); $tmp = preg_replace(":</{0,1}[az]+[^>]*>: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; } 

Пример использования:

 $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 ); 

Выход:

 string '<b>Is 1 &lt; 4?</b>&egrave;<br><i>&quot;then&quot;</i> <div style="some:style;"><p>gain some <strong>&euro;</strong><img src="/some/path" /></p></div>' (length=150) 

Вы можете передать любой ent flag согласно руководству htmlentities

однострочное решение без таблицы перевода NO или пользовательской функции:

Я знаю, что это старый вопрос, но мне недавно пришлось импортировать статический сайт на сайт WordPress и пришлось преодолеть эту проблему:

вот мое решение, которое не требует использования таблиц перевода: htmlspecialchars_decode( htmlentities( html_entity_decode( $string ) ) );

когда применяется к строке OP:

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

вывод:

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

когда применяется к строке Луки:

 <b>Is 1 < 4?</b>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€</strong><img src="/some/path" /></p></div> 

вывод:

 <b>Is 1 < 4?</b>&egrave;<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>&euro;</strong><img src="/some/path" /></p></div> 

EDIT: это особенно хорошо работает при «отбеливании» входной строки:

$string = preg_replace( '/[^\x00-\x7F]/', null, $string ); htmlspecialchars_decode( htmlentities( html_entity_decode( $string ) ) );

теперь строка $ sooo довольно!