Разобрать html с помощью регулярного выражения

Я хочу найти все блоки ‹h3› в этом примере:

<h3>sdf</h3>
sdfsdf
<h3>sdf</h3>
32
<h2>fs</h2>
<h3>23sd</h3>
234
<h1>h1</h1>

(От h3 к другому h3 или h2) Это регулярное выражение находит только первый блок h3

~\<h3[^>]*\>[^>]+\<\/h3\>.+(?:\<h3|\<h2|\<h1)~is

Я использую функцию php preg_match_all (цитата из документов: После обнаружения первого совпадения последующие поиски продолжаются с конца последнего совпадения.)

Что мне нужно изменить в моем регулярном выражении?

ps

<h3>1</h3>
1content
<h3>2</h3>
2content
<h2>h2</h2>
<h3>3</h3>
3content
<h1>h1</h1>

этот контент должен быть проанализирован как:

[0] => <h3>1</h3>1content
[1] => <h3>2</h3>2content
[2] => <h3>2</h3>3content

person Andrei Nikolaev    schedule 04.04.2014    source источник
comment
не уверен, что действительно понимаю вашу проблему   -  person jcobhams    schedule 04.04.2014
comment
Спасибо за ответ, но я разбираю свою страницу с определенной структурой.   -  person Andrei Nikolaev    schedule 04.04.2014
comment
измените .+ на .+? и замените группу без захвата на опережающую. Обратите внимание, что угловые скобки и косые черты не нужно экранировать, поскольку в качестве разделителя используется ~.   -  person Casimir et Hippolyte    schedule 04.04.2014
comment
Взгляните на класс DomDocument. Если вы проанализируете свой HTML, вы можете легко запросить все три блока заголовка.   -  person Dave Chen    schedule 04.04.2014
comment
@CasimiretHippolyte. +? пропустить второй блок   -  person Andrei Nikolaev    schedule 04.04.2014
comment
@AndreiNikolaev: второй блок пропускается, потому что вы не заменили группу без захвата на опережающий просмотр.   -  person Casimir et Hippolyte    schedule 04.04.2014
comment
Вопросы о синтаксическом разборе HTML с помощью PHP / регулярных выражений так часто возникают в SO. Позвольте мне повторить то, что уже было сказано - не делайте этого. Для решения этой проблемы существует множество гораздо более способных и полезных инструментов. Для начала посмотрите на внутренние классы PHP DOMDocument и DOMXPath. Сделай себе жизнь проще :)   -  person Darragh Enright    schedule 04.04.2014


Ответы (2)


с DOMDocument:

$dom = new DOMDocument();
@$dom->loadHTML($html);

$nodes = $dom->getElementsByTagName('body')->item(0)->childNodes;

$flag = false;
$results = array();

foreach ($nodes as $node) {
    if ( $node->nodeType == XML_ELEMENT_NODE &&
         preg_match('~^h(?:[12]|(3))$~i', $node->nodeName, $m) ):
        if ($flag)
            $results[] = $tmp;
        if (isset($m[1])) {
            $tmp = $dom->saveXML($node);
            $flag = true;
        } else
            $flag = false;

    elseif ($flag):
        $tmp .= $dom->saveXML($node);

    endif;
}

echo htmlspecialchars(print_r($results, true));

с регулярным выражением:

preg_match_all('~<h3.*?(?=<h[123])~si', $html, $matches);

echo htmlspecialchars(print_r($matches[0], true));
person Casimir et Hippolyte    schedule 04.04.2014

Не следует использовать Regex для синтаксического анализа HTML, если речь идет о вложении.

Регулярное выражение

(<(h\d)>.*?<\/\2>)[\r\n]([^\r\n<]+)

Замена

\1\3
or
$1$3

http://regex101.com/r/uQ3uC2

person Vasili Syrakis    schedule 04.04.2014