Найти несколько шаблонов с помощью одного preg_match_all в PHP

Используя PHP и preg_match_all, я пытаюсь получить все содержимое HTML между следующими тегами (и тегами):

<p>paragraph text</p> don't take this <ul><li>item 1</li><li>item 2</li></ul> don't take this <table><tr><td>table content</td></tr></table> 

Я могу получить один из них просто отлично:

 preg_match_all("(<p>(.*)</p>)siU", $content, $matches, PREG_SET_ORDER); 

Есть ли способ получить все

 <p></p> <ul></ul> <table></table> 

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

Так что, если бы я сделал preg_match_all в указанном выше содержимом, а затем повторил через массив $ matches, он бы повторил:

 <p>paragraph text</p> <ul><li>item 1</li><li>item 2</li></ul> <table><tr><td>table content</td></tr></table> 

Использование | для соответствия одной из групп строк: p|ul|table

Используйте обратные ссылки для соответствия закрывающей теге approriate: \\2 потому что группа (pl|ul|table) включает в себя вторую открывающую скобку

Объединив все это:

 preg_match_all("(<(p|ul|table)>(.*)</\\2>)siU", $content, $matches, PREG_SET_ORDER); 

Это только сработает, если ваш входной html следует строго строгой структуре. Он не может содержать пробелы в тегах или иметь какие-либо атрибуты в тегах. Он также терпит неудачу, когда есть какое-либо гнездование. Рассмотрите возможность использования синтаксического анализатора html для выполнения надлежащей работы.

Эта работа для меня

 preg_match_all("#<\b(p|ul|table)\b[^>]*>(.*?)</\b(p|ul|table)\b>#si", $content, $matches) 

Если вы хотите использовать парсер DOM, и вы должны это сделать. Участник опубликовал полезную функцию для получения внутреннего HTTML DOMNode , который я буду использовать в следующем примере:

 $dom = new DOMDocument; $dom->loadHTML($html); $p = $dom->getElementsByTagName('p')->item(0); // first <p> node $ul = $dom->getElementsByTagName('ul')->item(0); // first <ul> node $table = $dom->getElementsByTagName('table')->item(0); // first <table> node echo DOMinnerHTML($p); echo DOMinnerHTML($ul); echo DOMinnerHTML($table); 

Хотя это можно сделать с помощью регулярных выражений, вы можете упростить задачу, используя один из простых инструментариев парсера HTML. Например, с phpQuery или QueryPath это просто:

 qp($html)->find("p, ul, table")->text(); // or loop over them