PHP PCRE - исправить поведение вложенных тегов - PullRequest
2 голосов
/ 24 февраля 2011

Я хочу написать симплексный (состоящий из одного вызова preg_replace) форумный анализатор, и у меня возникают проблемы с вложенными тегами.

Например, если кто-то цитирует кого-то, цитируя кого-то, я не могу добиться правильного поведения.

При наличии:

[quote=Tom]

[quote=Jerry]
Lorem
[/quote]

Ipsum

[/quote]

Dolor.

Я хочу что-то вроде этого:

<blockquote>
    <p><strong>Tom wrote</strong></p>
    <blockquote>
       <p><strong>Jerry wrote:</strong></p>
      <p>Lorem</p>
    </blockquote>

    Ipsum
</blockquote>

Dolor.

У меня есть этот код:

preg_replace('~\[quote (.+)\](.+)\[/quote\]~is', '<blockquote><p><strong>$1</strong> wrote:</p><p>$2</p></blockquote>', $value);

Эта версия жадная.Если у меня есть два отдельных блока [quote], регулярное выражение оборачивает весь текст между первым [quote] и вторым [/quote].

Если я добавлю модификатор U, он будет слишком неуклюжим - первыйТег [quote] связан с первым (вложенным и неактуальным) тегом [/quote].

Спасибо за любую помощь!

Ответы [ 3 ]

1 голос
/ 24 февраля 2011

Не используйте регулярное выражение для этого. Используйте официальное расширение PECL при условии:

Пример (снято с документации):

<?php
$arrayBBCode=array(
    ''=>         array('type' => BBCODE_TYPE_ROOT,  'childs' => '!i'),
    'i'=>        array('type' => BBCODE_TYPE_NOARG, 'open_tag' => '<i>',
                    'close_tag' => '</i>', 'childs' => 'b'),
    'url'=>      array('type' => BBCODE_TYPE_OPTARG,
                    'open_tag' => '<a href="{PARAM}">', 'close_tag' => '</a>',
                    'default_arg' => '{CONTENT}',
                    'childs' => 'b,i'),
    'img'=>      array('type' => BBCODE_TYPE_NOARG,
                    'open_tag' => '<img src="', 'close_tag' => '" />',
                    'childs' => ''),
    'b'=>        array('type'=>BBCODE_TYPE_NOARG, 'open_tag' => '<b>',
                    'close_tag' => '</b>'),
);

$text = <<<EOF
[b]Bold Text[/b]
[i]Italic Text[/i]
[url]http://www.php.net/[/url]
[url=http://pecl.php.net/][b]Content Text[/b][/url]
[img]http://static.php.net/www.php.net/images/php.gif[/img]
[url=http://www.php.net/]
[img]http://static.php.net/www.php.net/images/php.gif[/img]
[/url]
EOF;

$BBHandler = bbcode_create($arrayBBCode);
echo bbcode_parse($BBHandler, $text);
?>

Полная документация.

1 голос
/ 24 февраля 2011

Существует пакет PEAR HTML_BBCodeParser , а также PHP имеет собственное расширение для синтаксического анализа кода, как этот, проверьте этот пример: http://www.php.net/manual/en/function.bbcode-create.php

0 голосов
/ 24 февраля 2011

С помощью рекурсивных регулярных выражений:

function replace_quotes_callback($matches) {
    $cite = empty($matches[1]) ? '' : '<p><strong>' . $matches[1] . '</strong> wrote:</p>';
    return '<blockquote>' . $cite . '<p>' . replace_quotes($matches[2]) . '</p></blockquote>';
}

function replace_quotes($data) {
    return preg_replace_callback('~\[quote(?:=([^\]]+))?\]((?:(?R)|.)*?)\[/quote\]~s', 'replace_quotes_callback', $data);
}

Шаблон соответствует только самым внешним блокам кавычек, а функция обратного вызова replace_quotes_callback заменяет кавычки внутри себя рекурсивным вызовом replace_quotes.

...