Обрабатывать блок HTML, игнорируя содержимое в определенных тегах - PullRequest
1 голос
/ 20 июля 2009

В блоге я хочу передать весь текст для записи в блоге через скрипт PHP для обработки цитат и некоторых других элементов в красивые типографские символы.

Текст блога, о котором идет речь, содержит HTML и, в частности, выделит фрагменты кода, содержащиеся в блоках <pre><code> ... . Блоки code могут появляться в произвольном порядке в разных местах текста (во многом как переполнение стека!)

Я не хочу, чтобы эти блоки кода обрабатывались типографскими сценариями, которые я буду использовать. Сама обработка не имеет значения, поскольку возможность выборочно применять ее есть.

Мне удалось написать регулярное выражение, чтобы найти эти блоки:

preg_match_all('/(<pre><code>(.*?)<\/code><\/pre>)/s', $text, $matches);

Но я не уверен, что лучше всего обработать остальную часть текста, а затем вставить эти блоки обратно в правильные места.

Спасибо за вашу помощь!

Ответы [ 4 ]

5 голосов
/ 20 июля 2009

Первое решение, которое приходит мне в голову, выглядит так:

  • извлечь все коды
  • удалите коды, заменив их специальным маркером, на который не будут влиять ваши манипуляции со строками - этот маркер должен быть действительно особенным (и вы можете убедиться, что его нет во входной строке, кстати)
  • делай свои манипуляции на струне
  • верните коды, где сейчас находятся маркеры

В коде это может быть что-то вроде этого: (извините, это довольно долго - и я не включил ни одного чека; вы можете добавить их)

$str = <<<A
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales lacus et erat accumsan consectetur. Sed lacinia enim vitae erat suscipit fermentum. Quisque lobortis nisi et lacus imperdiet ac malesuada dui imperdiet. <pre><code>ThIs Is 
CoDe 1
Donec vestibulum commodo quam rhoncus luctus. Nam vitae ipsum sed nibh dignissim condimentum. Sed ultrices fermentum dapibus. Vivamus Mattis Nisi Nec Enim Convallis Quis Aliquet Arcu Accumsan. Потенциал Suspendisse. Nullam Eget Fringilla Nunc. Нулла Порта Хусто Хусто. Nuncхватка egestas malesuada. Mauris ac nisi ipsum, et accumsan lorem. Quisque interdum accumsan pellentesque. Сед в метисе. Nulla gravida tincidunt tortor,
AnD cOdE 2
nec aliquam tortor ultricies vel. Integer semper libero eu magna conget eget lacinia purus auctor. Nunc volutpat ultricies feugiat. Nullam id mauris eget ipsum ultricies ullamcorper non vel risus. Проин волутпат волутпат интердум. Nulla orci odio, ornare sit amet ullamcorper non, condimentum sagittis libero.
aNd
CoDe
NuMbEr 3
Ut non justo в neque convallis luctus ultricies amet. A; var_dump ($ строка); // Извлекаем коды $ match = array (); preg_match_all ('#
(.*?)
# s', $ str, $ match); var_dump (соответствует $); // Удалить коды $ str_nocode = preg_replace ('#
.*?
# s', 'THIS_IS_A_NOCODE_MARKER', $ str); var_dump ($ str_nocode); // Делай, что хочешь, с $ str_nocode $ str_nocode = strtoupper ($ str_nocode); var_dump ($ str_nocode); // И вернуть обратно коды: $ str_codes = $ str_nocode; foreach ($ соответствует [0] как $ code) { $ str_codes = preg_replace ('# THIS_IS_A_NOCODE_MARKER #', $ code, $ str_codes, 1); } var_dump ($ str_codes);

Я пробовал с:

  • код в одной строке,
  • код в 2 строки,
  • и код в несколько строк

Примечание: вы должны действительно протестировать больше, чем я - но это может дать вам первое представление ...

Надеюсь, это поможет: -)

В качестве примечания: как правило, синтаксический анализ HTML с помощью регулярных выражений считается плохой практикой и часто приводит к проблемам ... Может быть, использование чего-то вроде DOMDocument::loadHTML может быть хорошей идеей?

1 голос
/ 21 июля 2009

Если вы получаете все, что вам нужно, от preg_match_all(), тогда вы можете использовать preg_split() примерно так:

$pattern = '/(<pre><code>(.*?)<\/code><\/pre>)/s';

// get the code blocks
preg_match_all($pattern, $text, $matches);
$code_blocks = $matches[0];

// split up the text around the code blocks into an array
$unprocessed = preg_split($pattern, $text);
$processed_text = '';
foreach($unprocessed as $block) {

    // process the text here
    $processed_text .= process($block); 

    // add the next code block
    if(!empty($code_blocks)) $processed_text .= array_shift($code_blocks);
}

// any remaining
$processed_text .= implode('', $code_blocks);

К сожалению, этот недостаток заключается в необходимости делать несколько вызовов process(), поэтому, в зависимости от того, насколько интенсивной это является и как часто вы делаете это, это может быть не лучшим решением. Это довольно ясно и безопасно, и вам не нужно добавлять какие-либо специальные маркеры для замены позже.

Если ваша обработка выполняет белый список и тип безопасности, взгляните на HTMLPurifier , который может выполнять некоторую сложную фильтрацию HTML, которая может позволить вам вообще избежать такого типа вещей (не цитируйте меня на этом хотя).

0 голосов
/ 20 июля 2009

Если вы просто хотите преобразовать кавычки или небольшой список элементов, я бы просто использовал string_replace.

$ text =

Some code here

Heredoc;

$ search_and_replace = array ('"', '"', "'",' ''); $ newtest = str_replace (array_keys ($ search_and_replace), $ search_and_replace, $ text);

Если вы не ищете что-то вроде strip_tags, которое позволяет вам указать, какие HTML-теги вы хотите сохранить.

0 голосов
/ 20 июля 2009

Я рекомендую использовать Textile , который позволяет форматировать текст, подобный уценке, и HTML. Его очень просто использовать, и я думаю, что это должно решить проблему, если я правильно понимаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...