如何使用PHP正则表达式将属性添加到第一个P标记?

时间:2010-02-07 09:35:00

标签: php html regex

WordPress以这种格式发布帖子:

<h2>Some header</h>
<p>First paragraph of the post</p>
<p>Second paragraph of the post</p>
etc.

要在第一段(这是那些看起来很好看的东西之一)中获得我很酷的样式,我需要挂钩到get_posts函数以使用preg_replace过滤其输出。

目标是让上面的代码看起来像:

<h2>Some header</h>
<p class="first">First paragraph of the post</p>
<p>Second paragraph of the post</p>

到目前为止我有这个但它甚至没有工作(错误是:“preg_replace()[function.preg-replace]:未知的修饰符']'”)

$output=preg_replace('<p[^>]*>', '<p class="first">', $content);

我不能使用CSS3元选择器,因为我需要支持IE6,我不能在父容器上应用:第一行元选择器(这是IE6支持的那个)因为它会击中H2而不是第一个P.

5 个答案:

答案 0 :(得分:6)

您可能会发现使用this one等HTML解析器更容易,更可靠。众所周知,HTML使用正则表达式可靠地解析(技术上,不可能),并且解析器将为您提供一种非常简单的方法来查找您感兴趣的节点。the doc的第一页有一个标签为“如何修改HTML元素“。

答案 1 :(得分:3)

两种可能性:

  1. 在Javascript中执行此操作。例如,使用jQuery,只需一行:$("h2").next().addClass("first")
  2. 使用HTML parser。的确,regexp are not a good tool to do what you want to do。由于为此目的加载整个HTML解析器是过度的,你最好使用Javascript。
  3. 错误的方式

    当然,为了回答这个问题,这是我无法想到的最好的方法,让它与正则表达式一起发生。虽然,我不推荐它。

    preg_replace('#(</h2>\s*<p[^>]*)>#im', '$1 class="first">', '<h2>Some header</h> <p>First paragraph of the post</p> <p>Second paragraph of the post</p> ');
    

    我们做的是:

    • 使用preg_replace,因此我们可以使用高级正则表达式替换代码;
    • 使用“m”和“i”标志,因此regexp不会打扰换行或案例;
    • 使用</h2>\s*匹配关闭的“h2”标签和之后的所有空格/换行符;
    • 使用*<p[^>]*匹配“p”标记及其当前的属性;
    • 使用括号来保存;
    • 使用“$ 1”替换匹配的字符串我们保存的部分;
    • 添加课程并关闭“&gt;”。

    我能想到的第一个缺点是,它不处理已经存在类的情况。

    顺便说一下,你有<h2>...</h>而不是<h2>...</h2>。我不知道这是不是一个错字,但我认为是。如果不是,请相应地替换正则表达式。

答案 2 :(得分:1)

问题是preg_*函数中正则表达式的第一个字符被视为修饰符分隔符。你需要的是:

$output = preg_replace('~<p\b([^>]*)>~', '<p class="first" \1>', $content, 1);

这也会放回<p>可能具有的任何额外属性。

总的来说,使用CSS选择器和IE的JS回退更简洁。

编辑:添加了替换限制和分词。

答案 3 :(得分:1)

在这种特殊情况下,regexp解决方案相当容易

echo preg_replace('~</h2>\s*<p~', "$0 class='first'", $html);

答案 4 :(得分:0)

通过阅读答案,有一些可行,但都有使用外部解析库或可能匹配P标签以外的标签或者还匹配其属性的缺点。

我最终使用来自here的str_replace_once函数的此解决方案:

str_replace_once('<p>', '<p class="first">', $content);

足够简单,它可以按预期工作。这里是完整的WordPress代码片段,可以在调用the_content()时过滤第一段:

add_filter('the_content', 'first_p_style');
function first_p_style($content) {
 $output=str_replace_once('<p>', '<p class="first">', $content);
 return ($output);
}

感谢所有答案!