<rmcreative>

RSS

Закрыть незакрытые тэги

30 апреля 2009

Функция позволяет закрыть незакрытые HTML-тэги.

function closetags($html) {
    $single_tags = array('meta','img','br','link','area','input','hr','col','param','base');
    preg_match_all('~<([a-z0-9]+)(?: .*)?(?<![/|/ ])>~iU', $html, $result);
    $openedtags = $result[1];
    preg_match_all('~</([a-z0-9]+)>~iU', $html, $result);
    $closedtags = $result[1];
    $len_opened = count($openedtags);
    if (count($closedtags) == $len_opened) {
    return $html;
    }
    $openedtags = array_reverse($openedtags);
    for ($i=0; $i < $len_opened; $i++) {
    if (!in_array($openedtags[$i], $single_tags)) {
        if (FALSE !== ($key = array_search($openedtags[$i], $closedtags))) {
        unset($closedtags[$key]);
        }
        else {
        $html .= '</'.$openedtags[$i].'>';
        }
    }
    }
    return $html;
}

Автор не я. Кто написал не помню…

Комментарии RSS

  1. №1555
    Николай
    Николай 30 апр. 2009 г., 17:30:33

    а насколько правильно он закрывает теги?

  2. №1556
    Sam
    Sam 30 апр. 2009 г., 18:03:47

    Николай

    Попробуйте.

  3. №1557
    SelenIT
    SelenIT 30 апр. 2009 г., 19:52:22

    Имхо, баловство это. Для XML бы еще прокатило, но для HTML, с его неявным закрытием "пэшек" перед любым блочным тегом и т.п., это мало что меняет. Да и зачем так изворачиваться, когда есть Tidy?

    Кстати, список одиночных тегов неполон -- как минимум, есть еще INPUT, HR, COL, PARAM и BASE...

  4. №1558
    Sam
    Sam 01 мая 2009 г., 12:27:19

    SelenIT

    Решение конечно же для закрытия XHTML. Использовано как раз было из-за отсутствия Tidy.

    Список одиночных действительно неполон. Добавлю.

  5. №1561
    Spider
    Spider 03 мая 2009 г., 0:23:25

    Спасибо, как нельзя кстати. Как раз собирался писать такую функцию

  6. №1589
    Индеетс
    Индеетс 19 мая 2009 г., 17:28:47

    Функция позволяет не только закрыть все открытые теги, но и открыть все закрытые которые могут образоваться после вырезания участка кода XHTML из произвольного места.

    function closetags($text)
    {
    // Выбираем абсолютно все теги
     if (preg_match_all("/<([/]?)([wd]+)[^>/]*>/", $text, $matches, PREG_SET_ORDER))
     {
      $stack = array();
      foreach ($matches as $k => $match)
      {
       $tag = strtolower($match[2]);
       if (!$match[1])
        // если тег открывается добавляем в стек
        $stack[] = $tag;
       elseif (end($stack) == $tag)
        // если тег закрывается, удаляем из стека
        array_pop($stack);
       else
        // если это закрывающий тег, который не открыт, открываем
        $text = '<'.$tag.'>'.$text;
      }
      while ($tag = array_pop($stack))
       // закрываем все открытые теги
       $text .= '</'.$tag.'>';
     }
     return $text; 
    }

    Тоже не помню где подсмотрел

  7. №1590
    Индеетс
    Индеетс 19 мая 2009 г., 17:36:19

    В регулярке некорректно обработаны обратные слэши, автору скрипта низачод)

    Правильно:

    if (preg_match_all("/<([СЛЭШ/]?)([СЛЭШwСЛЭШd]+)[^>СЛЭШ/]*>/", $text, $matches, PREG_SET_ORDER))
  8. №90
    Анатолий
    Анатолий 30 мая 2009 г., 18:05:03

    спасибо большое за скрипт!

  9. №1612
    fartemon
    fartemon 05 июня 2009 г., 17:37:03

    у меня возник вопрос, что если скрипт не в том порядке закроет теги, в случае дивной верски - он может наломать дров, кто его уже пробовал? напишите свои впечатления плиз

  10. №1951
    SpYeR
    SpYeR 01 нояб. 2009 г., 10:59:28

    Я сделал, что если тег table есть, не обрезать, т.к. это зачастую вёрстку нехило сбивает.

  11. №2117
    Guest
    Guest 21 дек. 2009 г., 21:52:22

    Большое Спасибо за скрипты. Будем тестировать!!!

  12. №7646
    kent
    kent 04 марта 2013 г., 17:55:28

    спасибоooooooooooo

  13. №8388
    Михаил
    Михаил 19 сент. 2013 г., 21:41:26
    function closetags($html) {
        $single_tags = array('meta','img','br','link','area','input','hr','col','param','base');
        foreach ($single_tags as $tag) {
          preg_match_all('#<'.$tag.'[^>]*>#Usi', $html, $m);
          foreach ($m[0] as $t) {
            if (!preg_match('#/\s*>#Usi', $t)) {
              $t1 = str_replace('>', ' />', $t);
              $html = str_replace($t, $t1, $html);     
            }  
          }
        }
        return $html;
      }
  14. №9182
    Alex
    Alex 20 сент. 2014 г., 22:04:15

    предыдущаяяя ф-я просто добавляет в одиночные теги внутренний слэш. Т.е. <br> заменит на <br />

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.