【问题标题】:How to add attribute to first P tag using PHP regular expression?如何使用 PHP 正则表达式向第一个 P 标签添加属性?
【发布时间】:2011-01-14 01:34:14
【问题描述】:

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,并且我不能在父容器上应用 :first-line 元选择器(这是 IE6 支持的),因为它会命中H2 而不是第一个 P。

【问题讨论】:

  • 嗯,我是否遗漏了什么,或者您可以更改页面模板以硬编码类属性而不是挂钩到get_posts
  • 不能,因为P标签不是由模板创建的,它们是由wordpress吐出来的,wordpress通过autop钩子运行the_content,从而生成P。

标签: php html regex


【解决方案1】:

问题在于preg_* 函数中正则表达式的第一个字符被用作修饰符分隔符。你需要的是这样的:

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

这也会恢复&lt;p&gt; 可能具有的任何额外属性。

不过,总的来说,使用 CSS 选择器和 IE 的 JS 后备会更简洁。

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

【讨论】:

    【解决方案2】:

    您可能会发现使用诸如this one 之类的HTML 解析器更容易、更可靠。众所周知,HTML 很难用正则表达式可靠地解析(技术上是不可能的),解析器会给你一种非常简单的方法来找到你感兴趣的节点。the doc 的第一页有一个标签为“如何修改 HTML 元素”。

    【讨论】:

      【解决方案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。

      错误的方式

      当然,为了回答这个问题,这是我想不出的最好的方法,可以用正则表达式实现它。不过,我不推荐它。

      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”标志,这样正则表达式就不会担心换行或大小写;
      • 使用&lt;/h2&gt;\s* 匹配结束的“h2”标签和之后的所有空格/换行符;
      • 使用*&lt;p[^&gt;]*匹配“p”标签及其当前属性;
      • 使用括号保存;
      • 使用“$1”替换来替换我们保存的部分匹配的字符串;
      • 添加类并关闭“>”。

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

      顺便说一句,您使用的是&lt;h2&gt;...&lt;/h&gt; 而不是&lt;h2&gt;...&lt;/h2&gt;。我不知道这是否是一个错字,但我认为它是。如果不是,请相应地替换正则表达式。

      【讨论】:

      • 糟糕!是的

        ... 是一个错字。我不必担心 HTML 格式错误,因为博客引擎正在生成它。

      【解决方案4】:

      在这种特殊情况下,正则表达式解决方案相当简单

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

      【讨论】:

        【解决方案5】:

        通读答案,有些答案会起作用,但都有缺点,要么使用外部解析库,要么可能匹配 P 标签以外的标签,或者也匹配其属性。

        我最终将此解决方案与here 中的 str_replace_once 函数一起使用:

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

        足够简单,并且可以按预期工作。这是完整的 WordPress 代码 sn-p 用于在调用 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);
        }
        

        感谢大家的回答!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-11-29
          • 1970-01-01
          相关资源
          最近更新 更多