Как добавить атрибут в первый тег P с помощью регулярного выражения PHP? - PullRequest
2 голосов
/ 07 февраля 2010

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.

Ответы [ 5 ]

6 голосов
/ 07 февраля 2010

Возможно, вам будет проще и надежнее использовать HTML-анализатор, такой как , этот . Общеизвестно, что HTML трудно надежно (технически невозможно) с регулярными выражениями, и синтаксический анализатор даст вам очень простой способ найти интересующие вас узлы. Первая страница документа содержит вкладка с надписью «Как изменить элементы HTML».

3 голосов
/ 07 февраля 2010

Две правильные возможности:

  1. Сделайте это в Javascript. Использование jQuery , например, это вопрос одной строки: $("h2").next().addClass("first")
  2. Использовать HTML-парсер . Действительно, regexp не является хорошим инструментом для выполнения того, что вы хотите сделать . Поскольку загрузка всего синтаксического анализатора 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", чтобы регулярное выражение не беспокоило разрыв строки или регистр;
  • с использованием </h2>\s* для сопоставления закрывающих тегов "h2" и всех пробелов / разрывов строк после;
  • с использованием *<p[^>]* для сопоставления тега "p" и его текущих атрибутов;
  • использование скобок для сохранения этого;
  • с использованием "$ 1" для замены совпадающей строки в той части, которую мы сохраняем;
  • добавление класса и закрытие ">".

Первый недостаток, который я могу вспомнить, это то, что он не справляется со случаем, когда класс уже существует.

Из, и, кстати, у вас есть <h2>...</h> вместо <h2>...</h2>. Я не знаю, если это опечатка, но я предположил, что это было. Замените в регулярном выражении соответственно, если это не так.

1 голос
/ 07 февраля 2010

в этом конкретном случае решение регулярного выражения будет довольно простым

echo preg_replace('~</h2>\s*<p~', "$0 class='first'", $html);
1 голос
/ 07 февраля 2010

Проблема в том, что первый символ регулярного выражения в функции preg_* принимается в качестве разделителя модификатора. То, что вам нужно, это что-то вроде:

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

Это также возвращает любые дополнительные атрибуты, которые могут иметь <p>.

В целом, все же, лучше работать с селекторами CSS и отступать от JS для IE.

РЕДАКТИРОВАТЬ: Добавлен лимит замены и разрыв слова.

0 голосов
/ 07 февраля 2010

При чтении ответов есть некоторые, которые будут работать, но у всех есть недостатки, заключающиеся в использовании внешней библиотеки синтаксического анализа или, возможно, совпадении тегов, отличных от тега P, или совпадении с его атрибутами.

В итоге я использовал это решение с функцией 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);
}

Спасибо за все ответы!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...