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

Я хочу найти все блоки

в этом примере:
<h3>sdf</h3>
sdfsdf
<h3>sdf</h3>
32
<h2>fs</h2>
<h3>23sd</h3>
234
<h2>h1</h2>

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

~\<h3[^>]*\>[^>]+\<\/h3\>.+(?:\</h3[^>
<p> Я использую функцию php <span>preg_match_all</span> (Цитата из docs: после того, как найдено первое совпадение, последующие поиски продолжаются с конца последнего совпадения.)</p> <p> Что мне нужно изменить в моем регулярном выражении?</p> <p> п.с.</p> <pre class="prettyprint linenums">&lt;h3&gt;1&lt;/h3&gt; 1content &lt;h3&gt;2&lt;/h3&gt; 2content &lt;h2&gt;h2&lt;/h2&gt; &lt;h3&gt;3&lt;/h3&gt; 3content &lt;h2&gt;h1&lt;/h2&gt;</pre> <p> этот контент должен быть проанализирован как:</p> <pre class="prettyprint linenums">[0] =&gt; &lt;h3&gt;1&lt;/h3&gt;1content [1] =&gt; &lt;h3&gt;2&lt;/h3&gt;2content [2] =&gt; &lt;h3&gt;2&lt;/h3&gt;3content</pre>

3 ответа

с 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('~


Вы не должны использовать Regex для анализа HTML, если есть какая-либо вложенность.

Regex

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

замена

\1\3
or
$1$3

http://regex101.com/r/uQ3uC2


preg_match_all('/<h3><code>(.*?)<\/h3>/is', $stringHTML, $matches);
</code> </h3>

licensed under cc by-sa 3.0 with attribution.