求帮写一个php正则替换,我想给提交的p标签添加一个类名

问题描述

问题是这样的,我想给后端编辑器提交的文章详情中的p标签添加一个类名,便于前端渲染的时候能更好的控制这个p标签的样式,一篇文章中有很多p标签,某些p标签已经有了这个类名的话,就不用添加同样的类名(因为在前端一个p标签有两个相同的类名会有些问题,这是个比较特殊的前端渲染模式),比如后台编辑器提交给后端的代码如下:

$content = "<p>一段文字</p><p class='abc'>文字</p>< class='p-name'>又一段文字</p>";

//想要的结果

$content = "<p class='p-name'>一段文字</p><p class='abc p-name'>文字</p>< class='p-name'>又一段文字</p>";

最终我想要的结果是,通过php的preg_replace方法,给第一个和第二个没有“p-name”的p标签添加上“p-name”这个类名,而第三个已经有了“p-name”的p标签就不用添加,感谢各位兄弟了!

阅读 2.4k
2 个回答

一个正则不好处理,像我这样处理,效率不高,但是兼容性一定好

<?php

$content = "<p>一段文字</p><p class='abc'>文字</p>< class='p-name'>又一段文字</p>";
$addclasses = 'p-name';

// (img|p) 意思是 img 或 p ,如果要加上 div 那就改成 (img|p|div)
$content = preg_replace_callback('/<(img|p)([^>]+)?>/', function($matches){
    
    global $addclasses;
    
    // 单独使用一个变量,要不然匹配多个会导致 $addclasses 逐个加上已有 class
    global $classes;
    $classes = $addclasses;

    // 实现不修改原有单引号或双引号,不修改引号主要是考虑到个别情况下需要使用 JSON 数据
    global $classquote;
    $classquote = '"';
    
    $attr = '';
    $tagname = $matches[1];
    
    // 删除 class 属性 HTML 并提取 class 到 $classes 变量
    if (! empty($matches[2]) ) {
        $attr = preg_replace_callback('/class=(?:"([^"]+)"|\'([^\']+)\')/', function($classmatches){

            $thisclasses = '';
            // 双引号
            if (!empty($classmatches[1])) {
                $thisclasses = $classmatches[1];
                
            } else if (!empty($classmatches[2])) {
                // 单引号
                global $classquote;
                $classquote = "'";
                $thisclasses = $classmatches[2];
            }

            global $classes;
            $classes = $thisclasses . ' ' . $classes;

            return '';
        }, $matches[2]);
    }

    // 去空去重
    $classes = explode(' ', $classes);
    $classes = array_flip(array_flip(array_filter($classes)));
    $classes = join(' ', $classes);
    
    // 如果是 img 标签过滤一下后面可能存在的 / 
    if ($tagname === 'img')
        $attr = trim(trim($attr, '/'));
    
    // 在属性 HTML 中加上 class 属性
    $attr .= sprintf(' class=%1$s%2$s%1$s', $classquote, $classes);
    
    // 包装
    return sprintf('<%1$s %2$s>', $tagname, trim($attr));
    
}, $content);

echo $content;

// <p class="p-name">一段文字</p><p class='abc p-name'>文字</p>< class='p-name'>又一段文字</p>

$content = "<div><p>一段文字</p><p class='abc'>文字</p><p class='p-name'>又一段文字</p></div>";
function replaceP($content){
    $isMatched = preg_match_all('/<p.*?>/', $content, $matches);
    foreach ($matches[0] as $key => $value) {
        //检测到有class
        preg_match('/class=(\'|\").*(\'|\")/i', $value,$matche);
        if(@!empty($matche[0])){
            //单引号
            if(strpos($value,'\'')){
                $v = substr($value,0,-2);
                if(!strpos($v,'p-name')){
                    $content = preg_replace("/{$v}/", $v.' p-name', $content);
                }
            //双引号
            }else if(strpos($value,"\"")){
                $v = substr($value,0,-2);
                if(!strpos($v,'p-name')){
                    $content = preg_replace("/{$v}/", $v.' p-name', $content);
                }    
            }
        //没有class
        }else{
            $content = preg_replace("/<p>/","<p class='p-name'>", $content);
        }
    }
    return $content;
}
$c = replaceP($content);
var_dump($c);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题