PHP:如何将双倍的 <br /> 替换为 </p><p>?

11
我在我的CMS中使用NicEdit编写RTF数据。问题在于它会生成像这样的字符串:
hello first line<br><br />this is a second line<br />this is a 3rd line

由于这是一家新闻网站,我更喜欢最终的HTML是这样的:
<p>hello first line</p><p>this is a second line<br />this is a 3rd line</p>

我的目前解决方案是这样的:

  1. 我需要将 $data 开头和结尾的 <br /> 去掉
  2. 将所有含有 2 个或以上 <br/> 的字符串替换为 </p><p>(可以有一个单独的 <br />)。
  3. 最后,在开头加上 <p>,在结尾加上 </p>

目前我只完成了步骤 1 和 3。能否有人帮我完成第二步呢?

function replace_br($data) {
 # step 1
 $data = trim($data,'<p>');
 $data = trim($data,'</p>');
 $data = trim($data,'<br />');
 # step 2 ???
 // preg_replace() ?
 # step 3
 $data = '<p>'.$data.'</p>';
 return $data;
}

谢谢!

注:最好避免特定情况。例如:hello<br /><br /><br /><br /><br />too much space - 这5个换行符应该转换为一个 "</p><p>"。

最终解决方案(特别感谢kemp!)

function sanitize_content($data) {
    $data = strip_tags($data,'<p>,<br>,<img>,<a>,<strong>,<u>,<em>,<blockquote>,<ol>,<ul>,<li>,<span>');
    $data = trim($data,'<p>');
    $data = trim($data,'</p>');
    $data = trim($data,'<br />');
    $data = preg_replace('#(?:<br\s*/?>\s*?){2,}#','</p><p>',$data);
    $data = '<p>'.$data.'</p>';
    return $data;
}
3个回答

17

即使两个 <br> 标签在不同行上(也就是它们之间有换行符或任何空格),这段代码也能正常工作:

function replace_br($data) {
    $data = preg_replace('#(?:<br\s*/?>\s*?){2,}#', '</p><p>', $data);
    return "<p>$data</p>";
}

你是个好样的!哈哈,preg_replace是做这件事最有效的方法。谢谢!我得更好地学习正则表达式,呵呵。 - Andres SK
应用正则表达式中的“?”时,也会处理“<br>”。 - Andres SK
@kemp... 我在这个解决方案中遇到了一个更小的细节。有时候 <p> 或 </p> 旁边还会有 <br/>,我该如何在同一个正则表达式中也将它们删除? - Andres SK
已编辑以考虑 <br> - Matteo Riva
@andufo:我宁愿不在一个正则表达式中放入太多的内容,将问题分成两个步骤通常会使事情变得容易得多 - Matteo Riva

3
这种方法可以解决你的问题:
  1. <br><br />拆分字符串:您将获得一个字符串数组。
  2. 创建一个新字符串<p>
  3. 循环数组1,从开头到结尾删除所有条目为空的条目,直到不为空的条目(中断)。
  4. 与3相同,但从数组的末尾开始。
  5. 循环数组1,有一个整数值A(默认值为0),表示单个或双重换行符。
    1. 如果字符串为空,请增加A的值并继续循环。
    2. 如果字符串不为空:
      1. 如果A的值为1或更低,则附加<br>
      2. 如果A的值为2或更高,则附加</p><p>
    3. 附加当前条目的内容(不为空的条目)。
    4. 将A的值设置为0。
  6. 附加</p>

另一种方法:使用正则表达式
(<br ?/?>){2,}

将匹配2个或更多的<br>。(有关如何执行此操作,请参见php.net上的preg_split。)

现在,对步骤2和3采用相同的方法:两次循环数组,一次从开头到末尾(0..length),一次从末尾到开头(length-1..0)。如果条目为空,请从数组中删除它。如果条目不为空,则退出循环。

要执行此操作:

$array = preg_split('/(<br ?/?>\s*){2,}/i', $string);

foreach($i = 0; $i < count($array); $i++) {
    if($value == "") {
        unset($array[$i]);
    }else{
        break;
    }
}

foreach($i = count($array) - 1; $i >= 0; $i--) {
    if($value == "") {
        unset($array[$i]);
    }else{
        break;
    }
}

$newString = '<p>' . implode($array, '</p><p>') . '</p>';

实际上,如果能找到包含 2 个或更多 <br /> 字符串的方法,会更好-- 我在考虑使用 preg_replace,但仍然不知道如何继续。 - Andres SK
第一种方法也可以处理那些情况。第二种方法更容易实现,但问题在于您是否喜欢在HTML上使用正则表达式(有些人不喜欢这种方法)。 - Pindatjuh
谢谢提供这个模式,但我认为有些地方不对。我正在使用以下代码:$data = preg_replace('(<br ?/?>){2,}','aaa',$data); 但它返回了null。为什么呢?(我使用“aaa”使其更易于查看) - Andres SK
因为您使用了 preg_replace,当然可以继续使用它,但在我勾画的情况下它不起作用。我还添加了一些代码。 - Pindatjuh

0
我认为这应该可以解决第二步,除非我没有完全理解你的情况:
$string = str_replace( '<br><br>', '</p><p>', $string );
$string = str_replace( '<br /><br />', '</p><p>', $string );
$string = str_replace( '<br><br />', '</p><p>', $string );
$string = str_replace( '<br /><br>', '</p><p>', $string );

谢谢你的想法,但它太基础了。我需要更高级的方法。请查看顶部的最终解决方案。 - Andres SK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接