13.7. Capturing Text Inside HTML Tags

Problem

You want to capture text inside HTML tags. For example, you want to find all the headings in a HTML document.

Solution

Read the HTML file into a string and use nongreedy matching in your pattern:

$html = join('',file($file));
preg_match('#<h([1-6])>(.+?)</h\1>#is', $html, $matches);

In this example, $matches[2] contains an array of captured headings.

Discussion

True parsing of HTML is difficult using a simple regular expression. This is one advantage of using XHTML; it’s significantly easier to validate and parse.

For instance, the pattern in the Solution is smart enough to find only matching headings, so <h1>Dr. Strangelove<h1> is okay, because it’s wrapped inside <h1> tags, but not <h2>How I Learned to Stop Worrying and Love the Bomb</h3>, because the opening tag is an <h2> while the closing tag is not.

This technique also works for finding all text inside bold and italic tags:

$html = join('',file($file));
preg_match('#<([bi])>(.+?)</\1>#is', $html, $matches);

However, it breaks on nested headings. Using that regular expression on:

<b>Dr. Strangelove or: <i>How I Learned to Stop Worrying and Love the Bomb</i></b>

doesn’t capture the text inside the <i> tags as a separate item.

This wasn’t a problem earlier; because headings are block level elements, it’s illegal to nest them. However, as inline elements, nested bold and italic tags are valid.

Captured text can be processed by looping through the array of matches. For example, this code ...

Get PHP Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.