Обратное декодирование объектов htmlentities / html
в основном я хочу повернуть строку, как это:
<code> <div> blabla </div> </code>
в:
<code> <div> blabla </div> </code>
как я могу это сделать?
прецедент (до н. э. некоторым людям было любопытно):
страницу этой со списком разрешенных HTML-тегов и примеров. Например, <code>
является допустимым тегом, и это будет образец:
<code><?php echo "Hello World!"; ?></code>
Я хотел обратную функцию, потому что там есть много таких тегов с образцами, которые я храню в массиве, который я повторяю в одном цикле, а не обрабатываю каждый отдельно...
7 ответов
мой вариант с использованием регулярных выражений:
$string = '<code> <div> blabla </div> </code>';
$new_string = preg_replace(
'/(.*?)(<.*?>|$)/se',
'html_entity_decode("").htmlentities("")',
$string
);
он пытается соответствовать каждому tag и textnode и затем применить htmlentities и html_entity_decode соответственно.
нет существующей функции, но посмотрите на это. До сих пор я тестировал его только на вашем примере, но эта функция должна работать на все htmlentities
function html_entity_invert($string) {
$matches = $store = array();
preg_match_all('/(&(#?\w){2,6};)/', $string, $matches, PREG_SET_ORDER);
foreach ($matches as $i => $match) {
$key = '__STORED_ENTITY_' . $i . '__';
$store[$key] = html_entity_decode($match[0]);
$string = str_replace($match[0], $key, $string);
}
return str_replace(array_keys($store), $store, htmlentities($string));
}
обновление:
спасибо @Mike за то, что потратили время, чтобы проверить мою функцию с другими строками. Я обновил мой regex из
/(\&(.+)\;)/
to/(\&([^\&\;]+)\;)/
который должен позаботиться о проблеме, которую он поднял.Я также добавил
{2,6}
ограничить продолжительность каждого матча, чтобы уменьшить вероятность ложных срабатываний.изменить regex из
/(\&([^\&\;]+){2,6}\;)/
до/(&([^&;]+){2,6};)/
чтобы удалить ненужные excaping.Ууу, мозговая волна! Изменил regex из
/(&([^&;]+){2,6};)/
to/(&(#?\w){2,6};)/
чтобы уменьшить вероятность ложных срабатываний еще больше!
замена в одиночку не будет достаточно хорошо для вас. Будь то регулярные выражения или простая замена строк, потому что если вы замените знаки < >, то знаки или наоборот, вы получите одну кодировку/декодирование (все < и > или все знаки).
поэтому, если вы хотите это сделать, вам придется разобрать один набор (я решил заменить его на держатель места), сделать замену, а затем вернуть их и сделать другую замену.
$str = "<code> <div> blabla </div> </code>";
$search = array("<",">",);
//place holder for < and >
$replace = array("[","]");
//first replace to sub out < and > for [ and ] respectively
$str = str_replace($search, $replace, $str);
//second replace to get rid of original < and >
$search = array("<",">");
$replace = array("<",">",);
$str = str_replace($search, $replace, $str);
//third replace to turn [ and ] into < and >
$search = array("[","]");
$replace = array("<",">");
$str = str_replace($search, $replace, $str);
echo $str;
Я думаю, что у меня есть небольшое решение, почему бы не разбить HTML-теги в массив, а затем сравнить и изменить если нужно?
function invertHTML($str) {
$res = array();
for ($i=0, $j=0; $i < strlen($str); $i++) {
if ($str{$i} == "<") {
if (isset($res[$j]) && strlen($res[$j]) > 0){
$j++;
$res[$j] = '';
} else {
$res[$j] = '';
}
$pos = strpos($str, ">", $i);
$res[$j] .= substr($str, $i, $pos - $i+1);
$i += ($pos - $i);
$j++;
$res[$j] = '';
continue;
}
$res[$j] .= $str{$i};
}
$newString = '';
foreach($res as $html){
$change = html_entity_decode($html);
if($change != $html){
$newString .= $change;
} else {
$newString .= htmlentities($html);
}
}
return $newString;
}
изменить .... без ошибок.
Итак, хотя другие люди здесь рекомендовали регулярные выражения, которые могут быть абсолютно правильным способом ... Я хотел опубликовать это, так как этого достаточно для вопроса, который вы задали.
предполагая, что вы всегда используете html-код:
$str = '<code> <div> blabla </div> </code>';
xml_parse_into_struct(xml_parser_create(), $str, $nodes);
$xmlArr = array();
foreach($nodes as $node) {
echo htmlentities('<' . $node['tag'] . '>') . html_entity_decode($node['value']) . htmlentities('</' . $node['tag'] . '>');
}
дает мне следующий результат:
<CODE> <div> blabla </div> </CODE>
вполне уверен, что это не будет поддерживать возвращение назад.. как и другие решения, размещенные, будет, в смысле:
$orig = '<code> <div> blabla </div> </code>';
$modified = '<CODE> <div> blabla </div> </CODE>';
$modifiedAgain = '<code> <div> blabla </div> </code>';
Edit: похоже, я не полностью ответил на ваш вопрос. Нет встроенной функции PHP, чтобы делать то, что вы хотите, но вы можете найти и заменить регулярными выражениями или даже простыми выражениями: как str_replace, человек