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>
любые идеи?
Ответы
Ответ 1
Вы можете получить список соответствий character = > entity, используемый 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)
На этот раз это должно быть нормально ^^
Это не очень подходит в одной строке, возможно, это не самое оптимизированное решение; но он должен работать нормально и имеет то преимущество, что вы можете добавить/удалить любой соответствующий символ = > объект, который вам нужен, или нет.
Удачи!
Ответ 2
Не может быть ужасно эффективным, но он работает
$sample = '<p><font style="color:#FF0000">Camión español</font></p>';
echo htmlspecialchars_decode(
htmlentities($sample, ENT_NOQUOTES, 'UTF-8', false)
, ENT_NOQUOTES
);
Ответ 3
Это оптимизированная версия принятого ответа.
$list = get_html_translation_table(HTML_ENTITIES);
unset($list['"']);
unset($list['<']);
unset($list['>']);
unset($list['&']);
$string = strtr($string, $list);
Ответ 4
Никакое решение, выходящее за парсер, не будет правильным для всех случаев. Ваш хороший пример:
<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('<', '<')
)
Ответ 5
Это функция, которую я только что написал, которая решает эту проблему очень элегантно:
Прежде всего, теги 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("@[email protected]", $matches[0][$i], $tmp, 1);
return $tmp;
}
Ответ 6
Основываясь на ответе 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 manual
Ответ 7
однострочное решение с отсутствующей таблицей перевода или требуемой пользовательской функцией:
Я знаю, что это старый вопрос, но мне недавно пришлось импортировать статический сайт на сайт 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ón español</font></p>
когда применяется к строке 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>
выход:
<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 ) ) );
теперь строка $очень хороша!