справка по регулярному выражению для депарсера bbcode

У меня есть эта функция для разбора bbcode -> html:

  $this->text = preg_replace(array(
    '/\[b\](.*?)\[\/b\]/ms', 
    '/\[i\](.*?)\[\/i\]/ms',
    '/\[u\](.*?)\[\/u\]/ms',
    '/\[img\](.*?)\[\/img\]/ms',
    '/\[email\](.*?)\[\/email\]/ms',
    '/\[url\="?(.*?)"?\](.*?)\[\/url\]/ms',
    '/\[size\="?(.*?)"?\](.*?)\[\/size\]/ms',
    '/\[youtube\](.*?)\[\/youtube\]/ms',
    '/\[color\="?(.*?)"?\](.*?)\[\/color\]/ms',    
    '/\[quote](.*?)\[\/quote\]/ms',
    '/\[list\=(.*?)\](.*?)\[\/list\]/ms',
    '/\[list\](.*?)\[\/list\]/ms',
    '/\[\*\]\s?(.*?)\n/ms'
   ),array(
    '<strong>\1</strong>',
    '<em>\1</em>',
    '<u>\1</u>',
    '<img src="\1" alt="\1" />',
    '<a href="mailto:\1">\1</a>',
    '<a href="\1">\2</a>',
    '<span style="font-size:\1%">\2</span>',
    '<object width="450" height="350"><param name="movie" value="\1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="\1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="450" height="350"></embed></object>',
    '<span style="color:\1">\2</span>',
    '<blockquote>\1</blockquote>',
    '<ol start="\1">\2</ol>',
    '<ul>\1</ul>',
    '<li>\1</li>'
   ),$original);

Проблема в том, как разобрать это, например, html -> bbcode?

Мои навыки регулярных выражений плохие :(

Спасибо.


person Rodrigo    schedule 17.07.2010    source источник


Ответы (3)


Не.

Вместо этого сохраните как исходный не проанализированный текст, так и обработанный проанализированный текст. Да, это удваивает требования к хранилищу, но также упрощает:

  1. Разрешить редактирование оригинала пользователем без обратного разбора BBCode
  2. Разрешить цитирование сообщений других пользователей, опять же без разбора
  3. Измените HTML, который генерирует каждый BBCode (просто повторите анализ каждого сообщения)
  4. Переключите движки BBCode в будущем (опять же, просто повторите анализ каждого сообщения)
person Charles    schedule 17.07.2010
comment
+1 Если бы данные действительно были доступны в формате BBCode, это было бы гораздо предпочтительнее. - person Wrikken; 17.07.2010
comment
Спасибо, я думаю, что это лучший подход, чем я думал изначально. - person Rodrigo; 17.07.2010

Можно с уверенностью сказать, что практически невозможно создать надежный способ преобразования html в bbcode с помощью всего лишь множества регулярных выражений. Используйте синтаксический анализатор (например, DOMDocument), удалите недопустимые элементы и атрибуты с помощью xpath и проверки, а затем рекурсивно пройдитесь по нему, создав строку bbcode по пути (или просто игнорируйте недопустимые теги / атрибуты по пути).

person Wrikken    schedule 17.07.2010
comment
Спасибо! Пони Тони не придет. - person Prof. Falken; 20.04.2012
comment
Эм, хочешь уточнить? Пони Тони не придет. немного загадочно на мой вкус ;) - person Wrikken; 20.04.2012
comment
Поскольку BBCODE имеет рекурсивную структуру, как и HTML, применяется следующее: stackoverflow.com/a/1732454/193892 - person Prof. Falken; 22.04.2012
comment
А внизу ответа вы найдете пони Тони, он же Ктулху. - person Prof. Falken; 30.04.2012

Если вы точно знаете, что код HTML, который вы хотите де-bbcode, был en-bbcode с использованием вашего метода, то сделайте следующее:

Переключите два массива, которые вы передаете, на preg_replace.

В массиве с HTML-кодом выполните следующие действия для каждого элемента: Добавьте # к строке. Добавьте #s. Замените \1\2 также) на (.*?).

Для массива с bbcodes сделайте следующее с каждым элементом: удалите / в начале и /ms в конце. Замените \s на . Remove all \. Удалите все ?. Замените первое (.*) в строке на $1, а второе на $2.

Это должно сработать. Если возникнут проблемы: Спрашивайте ;)

person NikiC    schedule 17.07.2010