处理HTML块,忽略特定标记内的内容

时间:2009-07-20 19:25:47

标签: php regex

在博客上,我希望通过PHP脚本传递博客条目的所有文本,以便将引号和其他一些项目处理成漂亮的印刷字符。

相关博客文字包含HTML,特别是会突出显示<pre><code> ... </code></pre>块中包含的代码段。 code块可以随机出现在文本中的多个位置(很像Stack Overflow!)

我不希望这些代码块由我将使用的排版脚本处理。 处理本身不是重点,能够有选择地应用它。

我已经能够编写一个正则表达式来找到这些块:

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

但我不确定最好的方法是处理剩下的文本然后将这些块放回正确的位置。

感谢您的帮助!

4 个答案:

答案 0 :(得分:5)

我想到的第一个解决方案是这样的:

  • 提取所有代码
  • 删除代码,用特殊标记替换它们,不会受到字符串操作的影响 - 该标记必须非常特殊(并且您可以验证它在输入字符串中不存在,顺便说一句)
  • 对字符串进行操作
  • 放回代码,现在有标记

在代码中,它可能是这样的: (抱歉,这很长 - 而且我没有包含任何支票;你可以自行添加支票)

$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之类的东西可能是一个值得一看的想法?

答案 1 :(得分:1)

如果您从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()

这有一个令人遗憾的缺点,即必须进行多次{{1}}调用,这取决于它的密集程度和频率,这可能不是最好的解决方案。它非常清晰安全,您无需在以后添加任何特殊标记进行更换。

如果你的处理正在进行白名单和安全类型的东西,那么看看HTMLPurifier哪些可以做一些复杂的HTML过滤,可以让你完全避免这种类型的东西(不要引用我的虽然)。

答案 2 :(得分:0)

我建议使用Textile,它允许类似降价的文本格式和HTML。它非常容易使用,如果我理解的话,我认为应该解决问题。

答案 3 :(得分:0)

如果您只想转换引号或一小部分商品,我会使用string_replace。

$ text =&lt;&lt;

Some code here

HEREDOC;

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

除非您正在寻找像strip_tags这样的东西,它允许您指定要保留的HTML标记。