Преобразование спец.символов в HTML-сущности в части документа
версия для печатиВ HTML некоторые символы имеют специальное значение и для сохранения своего значения должны быть преобразованы в HTML-сущности. Начиная с 3-ей версии в PHP для этого есть функция - htmlspecialchars(). Работает отлично, но проблема в том, что на преобразует весь html-документ. У меня возникла необходимость преобразования спец. символов только в части документа, а именно сохранение "внешнего вида" угловых скобок в примерах кода на html-страницах.
Ручной вариант: в исходном тексте документа в примерах писать '<' или '>' вместо угловых скобок. Наверняка есть какие-нибудь инструменты для таких замен, может даже online-сервисы. Вот простой рабочий пример сервиса:
Online-преобразование спец.символов в HTML-сущности во всем тексте
Ручная обработка меня не улыбает в силу субъективных причин. Вообщем я сочинил php-функцию, даже две :) Точнее, на другой день придумал второй вариант. Здесь приведу коды обоих вариантов. Если у вас есть идеи лучше, подскажите, буду признателен.
Итак, постановка задачи: заменить спец. символы на html-сущности только внутри тега <code> ... </code>, учитывая что блоков "code" в документе может быть несколько.
Вариант 1
function keep_tags_in_code($text)
{
//Выбрать все блоки тега <code> ... </code>.
//Массив заполнять наборами вхождений. Так же в массив писать позицию в исходной строке, с которой найдено совпадение.
preg_match_all('#<code>(.*)</code>#Us', $text, $match, PREG_SET_ORDER + PREG_OFFSET_CAPTURE);
$shift=0; //Учитываем сдвиг в этой переменной.
foreach($match as $v)
{
$code=$v[1][0]; //Текст внутри тега <code>
$code=str_replace(array('<','>'), array('<','>'), $code);//Замена угловых скобок на HTML-сущности
$old_len=strlen($v[1][0]); //Длина старого текста в <code> ... </code>
$text=substr_replace($text, $code, $v[1][1]+$shift, $old_len); //Замена старого текста новым.
$shift+=strlen($code)-$old_len; //Расчет сдвига.
}
return $text;
}
Принцип такой: регулярным выражением выбираем все куски кода из html-текста. Заменяем в них скобки на '<' или '>'. Потом в основном тексте заменяем старый код новым. Учитываем смещение в основном тексте, которое получается в результате замены на бОльшее количество символов. В дальнейших заменах в тексте сдвигаемся на это значение. В строке 10 можно использовать упомянутую ранее функцию PHP:
10| $code=htmlspecialchars($code);Все просто, обратить внимание нужно только на учет сдвига в основном тексте.
Вариант 2
function keep_tags_in_code($text)
{
$ptrn_lt='#(<code>[^<]*)<(?!/code>)(.*</code>)#Us';
$ptrn_gt='#(<code>[^>]*)(?<!</code)>(.*</code>)#Us';
//Пока будут найдены '<' или '>' внутри тега '<code>', заменяем их на html-сущности
while (preg_match($ptrn_lt,$text)) $text=preg_replace($ptrn_lt,'$1<$2',$text);
while (preg_match($ptrn_gt,$text)) $text=preg_replace($ptrn_gt,'$1>$2',$text);
return $text;
}
Здесь сложнее в понимании. Идея: регулярным выражением описываем ситуацию, когда внутри парного тега <code> есть угловая скобка. Пока есть такой текст, производим замену. Конечно, перебор в цикле работает долго, но я не смог придумать еще проще и быстрее.
Пример работы функций
Создаем html-документ. В исходном тексте документа теги пишем, как полагается. Любая из описанных функций вызывается перед тем, как отдать страницу браузеру.
<html>
<head><title>Тест. Частичное преобразование спец.символов</title></head>
<body>
<b>Что-то до блоков с примерами кода..</b>
<code>
<h4>Первый пример.</h4>
<font color='red'>Теги не работают, хотя именно так прописаны в исходнике</font>
</code>
<b>..что-то между..</b>
<code>
<h4>Второй пример.</h4>
<font color='green'>и здесь спец.символы преобразованы в сущности описанной функцией.</font>
</code>
<b>и в после всего.</b>
</body></html>
Подаем текст в функцию. В браузерe получим:
<h4> Первый пример.</h4>
<font color='red'> Теги не работают, хотя именно так прописаны в исходнике</font>
..что-то между..
<h4> Второй пример.</h4>
<font color='green'> и здесь спец.символы преобразованы в сущности описанной функцией.</font>
и в после всего.
Понравилась статья? Расскажите о ней друзьям: