htmlentities в PHP, но с сохранением html-тегов
Я хочу преобразовать все тексты в строке в html-объекты, но с сохранением HTML-тегов, например, так:
<p><font style="color:#FF0000">Camión español</font></p>
Следует перевести следующим образом:
<p><font style="color:#FF0000">Camión español</font></p>
Есть идеи?
7 answers
Вы можете получить список соответствий символ =>сущность, используемая htmlentities
, с помощью функции get_html_translation_table
; рассмотрим этот код:
$list = get_html_translation_table(HTML_ENTITIES);
var_dump($list);
( Возможно, вы захотите проверить второй параметр этой функции в руководстве - возможно, вам потребуется установить для него значение, отличное от значения по умолчанию)
Это даст вам что-то вроде этого:
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)
Теперь удалите ненужные вам соответствия:
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ón españ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ón españ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ón españ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);
Никакое решение, кроме синтаксического анализатора, не будет правильным для всех случаев. Ваш случай хороший:
<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 < a && name == "joe"</font></p>
Вопрос: Можете ли вы выполнить кодировку ПЕРЕД созданием HTML-кода. Другими словами, может сделать что-то вроде:
"<p><font>" + htmlentities(inner) + "</font></p>"
Вы избавите себя от многих огорчений, если сможете это сделать. Если вы не можете, вам понадобится какой-то способ пропустить кодирование и " (как описано выше) или просто закодировать все это, а затем отменить (например. replace('<', '<')
)
Это функция, которую я только что написал, которая решает эту проблему очень элегантным способом:
Прежде всего, 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}[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 < 4?</b>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€</strong><img src="/some/path" /></p></div>' (length=150)
Вы можете передать любой ent flag
в соответствии с руководством по htmlentities
Однострочное решение, НЕ требующее таблицы перевода или пользовательской функции:
Я знаю, что это старый вопрос, но недавно мне пришлось импортировать статический сайт на сайт 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ón españ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>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€</strong><img src="/some/path" /></p></div>
РЕДАКТИРОВАТЬ: это особенно хорошо работает, если сначала "отбелить" входную строку:
$string = preg_replace( '/[^\x00-\x7F]/', null, $string );
htmlspecialchars_decode( htmlentities( html_entity_decode( $string ) ) );
Теперь строка $ ооочень красивая!!