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>

Есть идеи?

Author: fidoboy, 2009-09-02

7 answers

Вы можете получить список соответствий символ =>сущность, используемая 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['&']);

Ваш список, теперь у него есть все соответствия 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)

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


Редактировать: ну, за исключением проблемы с кодировкой (проклятый 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);

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

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)

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

Веселитесь!

 63
Author: Pascal MARTIN, 2009-09-01 22:39:42

Может быть, это не очень эффективно, но это работает

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

echo htmlspecialchars_decode(
    htmlentities($sample, ENT_NOQUOTES, 'UTF-8', false)
  , ENT_NOQUOTES
);
 17
Author: Peter Bailey, 2014-11-25 16:41:23

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

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

$string = strtr($string, $list);
 7
Author: SileNT, 2010-06-23 16:30:59

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

<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;', '<'))

 5
Author: ndp, 2009-09-02 04:54:51

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

Прежде всего, 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;
}
 3
Author: bflesch, 2010-02-26 18:13:21

Основываясь на ответе bflesch, я внес некоторые изменения в управление строкой, содержащей less than sign, greater than sign и single quote или 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;
}



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

$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

 1
Author: Luca Borrione, 2017-05-23 12:10:38

Однострочное решение, НЕ требующее таблицы перевода или пользовательской функции:

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

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

Применительно к строке операции:

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

РЕДАКТИРОВАТЬ: это особенно хорошо работает, если сначала "отбелить" входную строку:

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

Теперь строка $ ооочень красивая!!

 1
Author: aequalsb, 2017-02-18 08:51:08