Обработать блок HTML, игнорируя содержимое в определенных тегах

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

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

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

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

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

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

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

Related of "Обработать блок HTML, игнорируя содержимое в определенных тегах"

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

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

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

 $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</code></pre>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 potenti. Nullam eget fringilla nunc. Nulla porta justo justo. Nunc consectetur egestas malesuada. Mauris ac nisi ipsum, et accumsan lorem. Quisque interdum accumsan pellentesque. Sed at felis metus. Nulla gravida tincidunt tortor, <pre><code>AnD cOdE 2</code></pre>nec aliquam tortor ultricies vel. Integer semper libero eu magna congue eget lacinia purus auctor. Nunc volutpat ultricies feugiat. Nullam id mauris eget ipsum ultricies ullamcorper non vel risus. Proin volutpat volutpat interdum. Nulla orci odio, ornare sit amet ullamcorper non, condimentum sagittis libero. <pre><code>aNd CoDe NuMbEr 3 </code></pre>Ut non justo at neque convallis luctus ultricies amet. A; var_dump($str); // Extract the codes $matches = array(); preg_match_all('#<pre><code>(.*?)</code></pre>#s', $str, $matches); var_dump($matches); // Remove the codes $str_nocode = preg_replace('#<pre><code>.*?</code></pre>#s', 'THIS_IS_A_NOCODE_MARKER', $str); var_dump($str_nocode); // Do whaterver you want with $str_nocode $str_nocode = strtoupper($str_nocode); var_dump($str_nocode); // And put back the codes : $str_codes = $str_nocode; foreach ($matches[0] as $code) { $str_codes = preg_replace('#THIS_IS_A_NOCODE_MARKER#', $code, $str_codes, 1); } var_dump($str_codes); 

Я пробовал:

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

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

Надеюсь это поможет 🙂

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

Если вы получаете все, что вам нужно от 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, которая может позволить вам избежать этого типа вещей вообще (не цитируйте меня на этом, хотя).

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

Если вы просто хотите конвертировать кавычки или небольшой список элементов, я бы просто использовал 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, которые вы хотите сохранить.