Записи. html парсер. Часть третья. Разбор текста. 

17 лет назад

Наверное самая большая часть кода и самая важная тут.

	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).'&lt;/'.$curtag.'&gt;';
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;
}

Если рассматривать работу данного скрипта по порядку, то:

  1. Сначала производится замена тегов согласно правил замены.
  2. Происходит разбор всего текста с помощью регулярного выражения. Получилось немного громоздкое, но работоспособное.
  3. Проверка количства найденых тегов, и если почему-то ничего не нашлось, то вывод текста, всё равно с экранированием лишнего, вдруг обошли регулярку.
  4. Начинается цикл по всем найденным тегам, вот и началось всё инетересное.
    1. В начале может быть странный текст не относящийся к тегам.
    2. Проверям наличие / в началетега, тем самым определяем что происходит.
    3. Вытаскиваем имя тега и его параметры.
    4. Если тег закрывается, то мы проверям допустимость закрытия его, то есть, что он был открыт последним или просто отображаем его на экране, как текст.
    5. Если тег не закрывался, то надо проверить, может ли он открываться и если может, то
      1. Производим разбор всех параметров у тега в массив.
      2. Проходим по массиву параметров и проверям доступность их применения их у тега.
      3. Если параметр является ссылкой, то ещё дополнительно разбираем её отделяя протокол если передан.
      4. Проверив протокол на правильность мы записываем параметр к тегу.
      5. Если тег может открываться, хмм... Ну ладно два раза не будет лишним проверить.
      6. В зависимости отприменения тега одиночным или нет, мы добавим в стек тегов его или нет и также занесём в код.
    6. Если мы таки не нашли что делать нам с тегом, то выведем его как есть на экран.
  5. Остаётся пробежаться по всем не закрытым тегам и закрыть их.

Вот и готов текст.


Авторизация



Поиск на сайте или перейди на страницу поиска