2015-01-18 3 views
2

У меня есть список нескольких тегов абзаца. Каждый из них без каких-либо атрибутов, например.Как найти последний элемент абзаца?

<p>First paragraph</p> 
<p>Second paragraph</p> 
<p>Third paragraph</p> 

Моя цель состоит в том, чтобы найти последнее открытие <p> тег - независимо от того, если у меня есть только один пункт или десять. Мне всегда нужен тег открытия последнего абзаца.

С

/<p>/ 

я получаю первый тэг параграфа. Я думал, что $ инвертирует направление поиска слева направо вправо-влево. Таким образом, в основном

/<p>$/ 

должен вернуть тег абзаца открытия для третьего абзаца из моего примера выше; но регулярное выражение ничего не обнаруживает.

Итак, как наилучшим образом нацелить последний абзац?

+4

обязательный http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 – Jasper

+0

Чтобы быть ясным, вы хотите ** 1) ** последний тег открытия абзаца или ** 2) ** * последний элемент абзаца, начиная с его открывающего тега *? Разница важна, но ** 1) **, кажется, имеет мало смысла, потому что последний тег абзаца открытия ..., конечно, * не отличается от любого предшествующего тега абзаца открытия * в этом случае (если вы не заинтересованы в его индексе внутри входной строки). – J0e3gan

+0

@ j0e3gan я хочу случай 1). Я выполняю 'preg_replace' в функции wordpress. Я хочу применить класс к последнему открытому тегу 'p' и добавить дополнение после. Функция предназначена только для полей плагина ACF с использованием тегов 'p', которые являются только полями wywwg. Я мог бы пойти с оберткой div для полей и использовать: last-child в CSS, но я не поклонник расширения html-разметки. Таким образом, я использую эту функцию только на определенной странице и только на полях wysiwyg, и пользователь может ввести дополнительные абзацы после этого, и класс по-прежнему применяется к каждому последнему тегу 'p'. – rpk

ответ

4

$ не меняет направление поиска, оно просто совпадает в конце текста, вот и все.

Если вы хотите, чтобы найти последнюю <p>, вы должны использовать отрицательный lookahead утверждать, что нет никаких больше вхождений <p>:

(?s)<p>(?!.*<p>) 
0

Это должно работать:

preg_match_all('#<p>.*</p>#',$string,$results); 
$last_paragraph = array_pop($results[0]); 
0

Попробуйте примерно следующее:

(<p>)([^<]*)<\/p>$ 

Regular expression visualization

Debuggex Demo

Вот PHP демо, чтобы проверить шаблон с входом образца вы предоставили ...

<?php 

$test = <<<TEST 
<p>First paragraph</p> 
<p>Second paragraph</p> 
<p>Third paragraph</p> 
TEST; 

preg_match('/<p>([^<]*)<\/p>$/', $test, $matches); 

var_dump($matches); 

?> 

..., которая выводит:

array(3) { 
    [0]=> 
    string(22) "<p>Third paragraph</p>" 
    [1]=> 
    string(3) "<p>" 
    [2]=> 
    string(15) "Third paragraph" 
} 

You возможно run the PHP demo on Ideone тоже.

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

0
$str = <<<MYFILE 
<p>First paragraph</p> 
<p>Second paragraph</p> 
<p>Third paragraph</p> 
MYFILE; 
$matches = array(); 
$pattern = '/.*?(<p>(.*)<\/p>)$/'; 
preg_match($pattern,$str,$matches); 

var_dump($matches); 
3

использовать этот шаблон

[\s\S]*\K(<p>) 

Demo

0

DOM Метод с помощью XPath

$doc = new DOMDocument(); 
$doc->loadHTML("<p>First paragraph</p><p>Second paragraph</p><p>Third paragraph</p>"); 

$xpath = new DOMXpath($doc); 
if($elements = $xpath->query("//p[last()]")) 
{ 
    echo $elements->item(0)->nodeName; // p 
    echo $elements->item(0)->nodeValue; // Third paragraph 
} 

Если вы имели более сложную HTML структуру вы должны начать получать явно с ваш запрос XPath.