×

Welcome to TagMyCode

Please login or create account to add a snippet.
0
0
 
0
Language: PHP
Posted by: Oleh Tereza
Added: Nov 21, 2016 3:01 PM
Views: 11
Tags: html tags correct
Correction HTML tags. Adding missing closing tags and remove extra closing tags.
  1. function correctTags($html) {
  2.    //получаем массив тегов последовательно
  3.    $str = strtolower($html);
  4.    $singleTag = ['meta', 'img', 'link', 'br', 'hr', 'input', 'area', 'param', 'col', 'base'];
  5.    $arrTags = [];
  6.    $pos = 0;
  7.    $stackTags = [];    // Стек тегов
  8.    $space = -1; // отступ для вставки с учетом символа "<". Будет увеличиваться по мере добавления тегов в html
  9.    // получаем все теги текста и их положение в тексте
  10.    while(true) {
  11.        $pos = strpos($str,'<',$pos);
  12.        if($pos === false) {
  13.            break;
  14.        }
  15.        $ch = substr($str, $pos++, 1);
  16.        if($ch == '<') {    // нашли начало тега
  17.            // получаем имя тега
  18.            $endTagPos = strpos($str, '>', $pos);
  19.            $tag = substr($str, $pos, ($endTagPos - $pos));
  20.            $posSpace = strpos($tag, ' ');
  21.            if($posSpace != 0) {
  22.                $tag = substr($tag, 0, $posSpace);
  23.            }
  24.            // если тег начинается не с "!" и не является одиночным, то обрабатываем его
  25.            if(strpos($tag, '!') === false && !in_array($tag, $singleTag)) {
  26.                if(count($stackTags) > 0) {                 // в стеке есть элементы
  27.                    if($tag != ('/' . end($stackTags))) {       // если текущий тег с массива это не закрывающий последний тег со стека
  28.                        if(substr($tag, 0, 1) == '/') {             // если текущий тег закрывающий
  29.                            if(in_array(substr($tag,1), array_column($stackTags, 'tag'))) { // если текущий закрывающий тег есть в стеке
  30.                                while($openTag = array_pop($stackTags)) {             // закрываем все открытые теги со стека до текущего закрывающего тега
  31.                                    if(substr($tag, 1) == $openTag['tag']) {  // если нашли соответствующий открывающий тег завершаем цикл закрытия тегов
  32.                                        break;
  33.                                    }
  34.                                    if(strpos($openTag['tag'], '/') === false) {        // если тег открывающий
  35.                                        $begHtml = substr($html, 0, $pos + $space);  // начало html до позиции вставки
  36.                                        $endHtml = substr($html, $pos + $space);     // конец html с позиции вставки
  37.                                        $html = $begHtml . '</' . $openTag['tag'] . '>' . $endHtml; // вставляем закрывающий тег
  38.                                        $space += strlen($openTag['tag']) + 3;                   // увеличиваем сдвиг для вставки на длину закрывающего тега
  39.                                    }
  40.                                }
  41.                            } else {        // если закрывающий тег отсутствует в стеке
  42.                                $begHtml = substr($html, 0, $pos + $space);  // начало html до позиции вставки
  43.                                $endHtml = substr($html, $pos + $space + strlen($tag) + 2);     // конец html после позиции вставки
  44.                                $html = $begHtml . $endHtml; // удаляем закрывающий тег
  45.                                $space -= strlen($tag['tag']) + 2;                   // увеличиваем сдвиг для вставки на длину закрывающего тега
  46.                            }
  47.                        } else {
  48.                            $stackTags[] = ['pos' => $pos, 'tag' => $tag];            // добавляем в стек текущий открывающий тег
  49.                        }
  50.                    } else {                                // иначе
  51.                        array_pop($stackTags);              // убираем последний добавленный тег со стека
  52.                    }
  53.                } else {                                // стек пустой
  54.                    $stackTags[] = ['pos' => $pos, 'tag' => $tag];
  55.                }
  56.            }
  57.            $pos = $endTagPos;
  58.        }
  59.    }
  60.    // закрываем оставшиеся в стеке открытые теги
  61.    rsort($stackTags);
  62.    foreach($stackTags as $tag) {
  63.        $html .= '</' . $tag['tag'] . '>';
  64.    }
  65.    
  66.    return $html;
  67. }