Как preg_match родительский div? - PullRequest
0 голосов
/ 19 июля 2010

Мне нужно получить все содержимое div class = "parent", используя preg_match,

<div class = "parent">

    <div id = "child1">
    </div>

    <div id = "child2">
    </div>

</div>

Любой

Ответы [ 3 ]

2 голосов
/ 19 июля 2010

Правильный способ сделать это - использовать DOM и xpath для нацеливания на конкретные элементы и атрибуты, которые вы пытаетесь извлечь.Однако, поскольку это домашняя работа, давайте обучим вашего инструктора.

Учитывая, что точная строка, это регулярное выражение будет работать: !<div class = "parent">(.+)</div>!s

Ключ "s модификатор.Он преобразует символ «.» из «чего-либо, кроме новой строки», в «что-либо, включая символ новой строки».

Однако, если пробелы были удалены вокруг =, это сломалось бы.Если бы было больше атрибутов, оно сломалось бы.Если бы было больше имен классов, это сломалось бы.Другими словами, это худший способ иметь дело с HTML когда-либо .

Черт, если бы HTML выглядел так, он сломался бы:

<div>
    <div class = "parent">
        My spoon is too big!
        <div>
            I am a banana!
        </div><!-- Matches when un-greedy -->
    </div>
</div><!-- Matches when greedy -->

Почему?Потому что .+ - это то, что называется «жадным».Он будет соответствовать всему, что возможно, до следующего предложения.Это означает, что он будет соответствовать всему от div.parent до жадного комментария.Хотя это можно сделать не жадным, добавив знак вопроса (.+?), тогда оно будет соответствовать первому возможному следующему предложению, а не последнему возможному следующему предложению.Это означает, что он будет соответствовать всему от div.parent до не жадного комментария.

Из-за проблем с вложением регулярные выражения являются очень плохим инструментом для анализа HTML.Проблемы, которые я вам здесь показал, касаются только поверхности h̨̜̜̟̬̭͍̀o̶̻̹̲̥̻ͧ́̆͆̊̉̍r̟͓ͨ́͆ͨͅr̪̖̠̖̤̊̾ͣͦ̀o̡̬͉͈͚̙͙ͯ͑ͨ͒ͥͩ̇ȓ̵̥̙͈̟͂̃s̠̏̊̃͠ , которая вас ждет.

Пожалуйста, по возможности, используйте настоящий анализатор HTML / XML и работайте с полученным DOM.Это спасет ваше здравомыслие.

0 голосов
/ 19 июля 2010

В итоге вы получите нечто варварское:

/<div[^>]+class ?= ?"parent"[^>]*>(\s*(?:<div.*<\/div>\s*)*)<\/div>/Us

Во-первых, поиск в открывающем теге div нужного класса - мне нравится использовать [^>], который представляет собой группу символов, указывающую что-либо, кроме символа «>». Затем с учетом пробелов вокруг "=" (или нет).

Тогда основная идея состоит в том, чтобы соединить каждый последующий открывающий тег div с его закрывающим сопряжением, чтобы иметь возможность остановиться в нужном месте. Это делается с помощью необработанного подшаблона, который может повторяться 0 или более раз. Обратите внимание, что это работает только с одним уровнем вложенности. Чтобы справиться с этим, вам понадобится рекурсия, и это сложно осмыслить.

Рекурсивная версия будет выглядеть примерно так:

/<div[^>]+class ?= ?"parent"[^>]*>(\s*(<div.*(?2).*<\/div>\s*)*)<\/div>/Us

В целом, если бы я не мог сделать нормальную вещь и использовать DOM, я бы предпочел пройтись по строке (начиная каждый раз с предыдущего совпадения), увеличивая счетчик для каждого открывающего тега div и встречая его для каждый закрывающий тег.

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

0 голосов
/ 19 июля 2010

Для ваших целей это, вероятно, подойдет, хотя это не без проблем (как отмечено в ссылках):

preg_match('/<div class = \'parent\'>(.*)<\/div>/s',$input,$matches);

После этого $ match [0] будет содержать соответствующий текст (включаяparent div) и $ match [1] будут содержать только внутренние элементы.

...