Hello

I'm learning regexp and I'm trying to get contents in a div tag.

<div class='name'>
<div class='contents'>
contents
</div>

</div>

my regexp is something like this

preg_match_all("/\<div class=\"name\"\>(.*?)\<\/div\>/is",
		$res, $matches );
   foreach($matches[0] as $value)
{
	echo $value;
}

I want to get everything in the div class='name' but I think that php is going to stop executing after getting the first </div> tag. How do I get the whole div tag?


Thanks

Dani AI

Generated

When you need everything inside a div (including any nested divs) and there may be multiple matches across the page, switch from regex to an HTML parser. In PHP, DOMDocument + DOMXPath lets you reliably select all <div class="name">...</div> nodes and get their contents without being tripped up by nested tags or multiple occurrences.

$html = /* your HTML string */;

libxml_use_internal_errors(true);
$dom = new DOMDocument();
$dom->loadHTML($html);
libxml_clear_errors();

$xpath = new DOMXPath($dom);
// Match class="name" even when combined with other classes
$nodes = $xpath->query("//div[contains(concat(' ', normalize-space(@class), ' '), ' name ')]");

$innerHtmls = [];
foreach ($nodes as $div) {
    $inner = '';
    foreach ($div->childNodes as $child) {
        $inner .= $dom->saveHTML($child); // use $div->textContent for plain text only
    }
    $innerHtmls[] = $inner;
}
// $innerHtmls now has the contents of every <div class="name">...</div>

Tips:

  • This handles any level of nesting and all repeated occurrences.
  • If the source HTML is imperfect, the DOM parser is still far more robust than regex. Suppressing libxml warnings (as above) avoids noise from minor markup issues.
  • If you must use regex, PCRE supports advanced recursive patterns, but they are brittle for real-world HTML; a DOM/XPath approach is recommended.

Docs: DOMDocument, DOMXPath, and PCRE recursion reference at php.net/regexp.reference.recursive.

Recommended Answers

All 6 Replies

Regular expressions do not work recursively. To match arbitrarily deeply nested div tags you would need such an recursion. You could use a regex for this special case like this:

preg_match_all('~<div class=\'name\'>\s*(<div.*?</div>\s*)?(.*?)</div>~is', $res, $matches );

what if there were multiple div tags inside the div class='name'?

does the

(<div.*?</div>\s*)

take care of all that too? Or that only takes care of one div tag nested inside div class='name'?

Thank you for your help

(<div.*?</div>\s*) matches until the first </div> . Therefore you cannot tackle nested divs (or other nested tags) with it. Use a recursive or parse function for that.

Thanks!

if there's multiple same div names throughout the page because of a while loop say

[B]<div class='name'>[/B]</div>
<div>code here</div>
etc..
[B]<div class='name'>[/B]</div>
<div>code here</div>
etc...
[B]<div class='name'></div>[/B]
<div>code here</div>
etc...

How do I get all of the same <div class='name'></div>?

Thanks!

If divs are not nested you get them with the code from your first post (after fixing the quotes): ~<div class='name'\>(.*?)</div>~s

But I only want to get all of the <div class='name'>content</div> only

and i don't want the other stuff. just within <div class='name'></div>. The original code will give me everything?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.