Записи. html парсер. Часть третья. Разбор текста.
16 лет назадМетки: html, php, regular, релиз, php разбор html, разбор текста, разобрать текст php, разбор HTML php, разбор html
Наверное самая большая часть кода и самая важная тут.
function Parse($text){
$text=preg_replace($this->ReplaceTagsFrom,$this->ReplaceTagsTo,$text);
@preg_match_all('/([^\<]*?)\<(\/?)([^\s]+?)((?:(?:\s+(?:[\w]+?)=("|\')(?:[^\5]*?)(?<!\\\\)\5)*?)(?:\s*)\/?)\>/',$text.'<br />',$textdrop);
$tags=array();
if(count($textdrop[0])==0)
return htmlspecialchars($text);
foreach($textdrop[0] as $id=>$line){
$pretext=$textdrop[1][$id];
$closetag=$textdrop[2][$id]=='/';
$curtag=strtolower($textdrop[3][$id]);
$tagparam=$textdrop[4][$id];
if ($closetag){
// TagClose
if ((count($tags)>0)&&($tags[0]==$curtag)){
$newtext.=htmlspecialchars($pretext).'</'.$curtag.'>';
array_shift($tags);
continue;
}else{
$newtext.=htmlspecialchars($pretext).'</'.$curtag.'>';
continue;
}
}
elseif (!isset($this->allow[$curtag])){
}else{
// TagOpen
preg_match_all('/\s([\w]+?)=("|\')((?:[^\2]*?)(?<!\\\\))\2/',$tagparam,$params);
$param='';
foreach($params[0] as $pid=>$line){
if (in_array(strtolower($params[1][$pid]),$this->allow[$curtag]))
if (strtolower($params[1][$pid])=='href'){
// Провека ссылок
preg_match('/(?:(\w*?):)(.*)/',$params[3][$pid],$link);
if ((count($link)==0)||(in_array(strtolower($link[1]),$this->AllowProtocols)))
$param.= ' '.$params[1][$pid].'='.$params[2][$pid].$params[3][$pid].$params[2][$pid];
}else
$param.= ' '.$params[1][$pid].'='.$params[2][$pid].$params[3][$pid].$params[2][$pid];
}
if (in_array($curtag,array_keys($this->allow))){
if (!in_array($curtag,$this->simpletag)){
array_unshift($tags,$curtag);
$newtext.=htmlspecialchars($pretext).'<'.$curtag.$param.'>';
}else{
$newtext.=htmlspecialchars($pretext).'<'.$curtag.$param.' />';
}
continue;
}
}
$newtext.=htmlspecialchars($pretext).'<'.($closetag?'/':'').$curtag.htmlspecialchars($tagparam).'>';}
foreach($tags as $tag)
$newtext.='</'.$tag.'>';
return $newtext;
}
Если рассматривать работу данного скрипта по порядку, то:
- Сначала производится замена тегов согласно правил замены.
- Происходит разбор всего текста с помощью регулярного выражения. Получилось немного громоздкое, но работоспособное.
- Проверка количства найденых тегов, и если почему-то ничего не нашлось, то вывод текста, всё равно с экранированием лишнего, вдруг обошли регулярку.
- Начинается цикл по всем найденным тегам, вот и началось всё инетересное.
- В начале может быть странный текст не относящийся к тегам.
- Проверям наличие / в началетега, тем самым определяем что происходит.
- Вытаскиваем имя тега и его параметры.
- Если тег закрывается, то мы проверям допустимость закрытия его, то есть, что он был открыт последним или просто отображаем его на экране, как текст.
- Если тег не закрывался, то надо проверить, может ли он открываться и если может, то
- Производим разбор всех параметров у тега в массив.
- Проходим по массиву параметров и проверям доступность их применения их у тега.
- Если параметр является ссылкой, то ещё дополнительно разбираем её отделяя протокол если передан.
- Проверив протокол на правильность мы записываем параметр к тегу.
- Если тег может открываться, хмм... Ну ладно два раза не будет лишним проверить.
- В зависимости отприменения тега одиночным или нет, мы добавим в стек тегов его или нет и также занесём в код.
- Если мы таки не нашли что делать нам с тегом, то выведем его как есть на экран.
- Остаётся пробежаться по всем не закрытым тегам и закрыть их.
Вот и готов текст.