PHP RegExp для вложенных тегов Div

Мне нужно регулярное выражение, которое я могу использовать с PHP preg_match_all() для сопоставления содержимого внутри тегов div. Дивы выглядят так:

<div id="t1">Content</div>

До сих пор я придумал это регулярное выражение, которое соответствует всем элементам div с id="t[number]"

/<div id="t(\\d)">(.*?)<\\/div>/

Проблема в том, что контент состоит из большего количества div, вложенных div вроде этого:

<div id="t1">Content <div>more stuff</div></div>

Любые идеи о том, как заставить мое регулярное выражение работать с вложенными тегами?

Спасибо


person Community    schedule 12.11.2009    source источник


Ответы (4)


Вместо этого попробуйте парсер:

require_once "simple_html_dom.php";
$text = 'foo <div id="t1">Content <div>more stuff</div></div> bar <div>even more</div> baz  <div id="t2">yes</div>';
$html = str_get_html($text);
foreach($html->find('div') as $e) {
    if(isset($e->attr['id']) && preg_match('/^t\d++/', $e->attr['id'])) {
        echo $e->outertext . "\n";
    }
}

Вывод:

<div id="t1">Content <div>more stuff</div></div>
<div id="t2">yes</div>

Загрузите парсер здесь: http://simplehtmldom.sourceforge.net/

Изменить: больше для собственного развлечения я попытался сделать это в регулярном выражении. Вот что я придумал:

$text = 'foo <div id="t1">Content <div>more stuff</div></div> bar <div>even more</div>
      baz <div id="t2">yes <div>aaa<div>bbb<div>ccc</div>bbb</div>aaa</div> </div>';
if(preg_match_all('#<div\s+id="t\d+">[^<>]*(<div[^>]*>(?:[^<>]*|(?1))*</div>)[^<>]*</div>#si', $text, $matches)) {
    print_r($matches[0]);
}

Вывод:

Array
(
    [0] => <div id="t1">Content <div>more stuff</div></div>
    [1] => <div id="t2">yes <div>aaa<div>bbb<div>ccc</div>bbb</div>aaa</div> </div>
)

И небольшое пояснение:

<div\s+id="t\d+">  # match an opening 'div' with an id that starts with 't' and some digits
[^<>]*             # match zero or more chars other than '<' and '>'
(                  # open group 1
  <div[^>]*>       #   match an opening 'div'
  (?:              #   open a non-matching group
    [^<>]*         #     match zero or more chars other than '<' and '>'
    |              #     OR
    (?1)           #     recursively match what is defined by group 1
  )*               #   close the non-matching group and repeat it zero or more times
  </div>           #   match a closing 'div'
)                  # close group 1
[^<>]*             # match zero or more chars other than '<' and '>'
</div>             # match a closing 'div'

Теперь, возможно, вы понимаете, почему люди пытаются убедить вас не использовать для этого регулярное выражение. Как уже отмечалось, это не поможет, если html будет неправильно сформирован: регулярное выражение испортит вывод больше, чем парсер html, уверяю вас. Кроме того, регулярное выражение, вероятно, заставит ваши глаза кровоточить, и ваши коллеги (или люди, которые будут поддерживать ваше программное обеспечение) могут искать вас, увидев, что вы сделали. :)

Лучше всего сначала очистить ввод (используя TIDY или аналогичный) и затем используйте парсер, чтобы получить нужную информацию.

person Bart Kiers    schedule 12.11.2009

Если вы верите этому парню, есть по крайней мере одно регулярное выражение, которое делает свое дело, и он говорит, что оно быстрее, чем методы dom... Я согласен с ним.

http://www.php.net/manual/fr/regexp.reference.recursive.php#95568

$pattern = "/<([\w]+)([^>]*?) (([\s]*\/>)| (>((([^<]*?|<\!\-\-.*?\-\->)| (?R))*)<\/\\1[\s]*>))/xsm";
person lingtalfi    schedule 26.08.2012

я думаю, будет лучше использовать некоторые DOM-инструменты

person merkushin    schedule 12.11.2009
comment
Спасибо, но мой документ содержит ошибку, и мне было бы проще использовать регулярное выражение - person ; 12.11.2009
comment
+1. если он содержит ошибки, использовать регулярное выражение будет БОЛЕЕ сложно. - person mauris; 12.11.2009

Как я недавно узнал, регулярное выражение не может этого сделать.

Сопоставление тега пары с регулярным выражением

Я закончил тем, что использовал xpath, и он работает как шарм

person Andrei Serdeliuc ॐ    schedule 12.11.2009
comment
Спасибо за ваш ответ, причина, по которой я не использую синтаксический анализ XPATH/DOM, заключается в том, что документ содержит ошибку. Я нашел это регулярное выражение: ''#‹div[^›]*›(?:(?:(?!‹/?div).)*|(?R))*‹/div›#si'. Но я не могу настроить его под свои нужды. - person ; 12.11.2009
comment
Ваша настойчивость перед лицом множества ответов, говорящих вам «нет», заслуживает похвалы, но вы действительно не можете анализировать HTML с помощью регулярных выражений. - person bobince; 12.11.2009