Умный парсинг "\n" => "<br>" мой вариант, альтернатива, ваши мнения и п

nip

Guest
Умный парсинг "\n" => "<br>" мой вариант, альтернатива, ваши мнения и п

Долго искал разные варианты умного преобразования текста (что типа обработчика на livejournal.com).
Проблема в том, что нужно проставлять переносы только в тех местах где нет спецальных тегов, напрмер между "<" и ">", "<tr>" и "<td>" и прочее проставлять низя - заколбасит.
Собственно что пидумал - задать в массиве условия входа и выхода из игнорного блока (выходов - может быт несколько), собственно алгоритм таков:
1. перебирается посимвольно строка и проверяется вход в игнорный блок. Если вошли то задаем номер игнорного блока (что бы потом можно было выйти)
2. Если не вошли в игнорный блок то делаем собсно замены имволов "\n"
3. На каждом симоволе делаем проверку на выход из игнорного блока (перебираем несколько выриантов выхода по выбору).

Собственно, чего мне не нравится:
1. Слишоком долго выполняется проверка входа и выхода.
2. В регулярных выражениях описать не смог (слишом много уловий)
3. Будет работать правильно только в случае правильного html :(

Если кто занимался подобной порнографией отзовитесь, буду рад любым советам и примерам.

Прилагаю собственный вариант:

PHP:
# Переменная которую будем обрабатывать (как видите, куча подводных камней)
  $in = "
  12
  3
  4
  1

    <table
    border=1><tr
    >
    <td
    >123
    321
    </td>
        <td
    >123
    321
    </td>
    </tr>
    <tr
    >
    <td
    >123
    <u>321</u>
    </td>
        <td
    >123
    321
    </td>
    </tr>
    </table>

   <textarea>1
2</textarea>
  ";

  echo smart_nl2br($in);

# Собственно функция простановки переносов
  function smart_nl2br($in){

  # Массив игнорируемых блоков (первый элемент строки - условие входа, остальные - условия выхода)
  $ignor_it[1][]= "<"; $ignor_it[1][]= ">";
  $ignor_it[2][]= "<table"; $ignor_it[2][]= "</table>"; $ignor_it[2][]= "<td";
  $ignor_it[3][]= "<td"; $ignor_it[3][]= ">";
  $ignor_it[4][]= "<tr"; $ignor_it[4][]= "<td";
  $ignor_it[5][]= "</td"; $ignor_it[5][]= "</tr";
  $ignor_it[6][]= "</tr"; $ignor_it[6][]= "<tr";  $ignor_it[6][]= "</table";
  $ignor_it[7][]= "<textarea"; $ignor_it[7][]= "</textarea";

  # Убираем  r-ки что бы не мешались
  $in = str_replace("\r","",$in);

  # Обнуляем индикатор игнорности текущего блока, по совместительству номер типа игнорируемого блока
  $ignor = 0;

  # Начинаем посимвольный перебор
  for ($i=0;$i<strlen($in);$i++){

          # Проверка на вход в игнорный блок (ищем подходящий игнорный блок)
            for ($k=1;$k<=count($ignor_it);$k++){
                    #echo substr($in,$i,strlen($ignor_it[$k][0]));

                    if (substr($in,$i,strlen($ignor_it[$k][0])) == $ignor_it[$k][0]) {
                       $ignor = $k;
                    }
            }


         if ($ignor>0){
           # Проверка на выход из игнорного блока (перебор завершений)
             for ($k=1;$k<count($ignor_it[$ignor]);$k++){
                    if (substr($in,$i,strlen($ignor_it[$ignor][$k])) == $ignor_it[$ignor][$k]) {
                       $ignor = 0;
                    }
             }
         }


          if ($ignor==0){
             # Добавляем переносы
             if ($in[$i]=="\n"){
              $in = substr($in,0,$i)."<br>\n".substr($in,$i+1,strlen($in)-$i);
              $i = $i + strlen("<br>\n");
             }
           }


    }
    return $in;
  }
 

Фанат

oncle terrible
Команда форума
в жж применется очень удобный тег <lj=raw>
я им, как раз, надысь очень успешно воспользовался
 

nip

Guest
PHP:
<lj-raw>
Ты хотел сказать?
Ну это частности, можно в массиве игнорных блоков строку добавить:
PHP:
$ignor_it[8][]= "<lj-raw"; $ignor_it[8][]= "</lj-raw>";
и будет работать так же как в ЖЖ
 

Xrobak

Guest
1. Слишоком долго выполняется проверка входа и выхода.
это 100%, из-за этого эту функцию не целесообразно использовать. При выборке из БД данных среднего размера пропустить через эту функцию, то даже на локалхосте приходится ждать...
Может кто знает как увеличить скорость работы этой функции?
 
Сверху