开发者

How to extract Heading tags in PHP from a string?

开发者 https://www.devze.com 2022-12-16 15:04 出处:网络
From a string that contains开发者_运维知识库 a lot of HTML, how can I extract all the text from <h1><h2>etc tags into a new variable?

From a string that contains开发者_运维知识库 a lot of HTML, how can I extract all the text from <h1><h2>etc tags into a new variable?

I would like to capture all of the text from these elements and store them in a new variable as comma-delimited values.

Is it possible using preg_match_all()?


First you need to clean up the HTML ($html_str in the example) with tidy:

$tidy_config = array(
    "indent"               => true,
    "output-xml"           => true,
    "output-xhtml"         => false,
    "drop-empty-paras"     => false,
    "hide-comments"        => true,
    "numeric-entities"     => true,
    "doctype"              => "omit",
    "char-encoding"        => "utf8",
    "repeated-attributes"  => "keep-last"
);

$xml_str = tidy_repair_string($html_str, $tidy_config);

Then you can load the XML ($xml_str) into a DOMDocument:

$doc = DOMDocument::loadXML($xml_str);

And finally you can use Horia Dragomir's method:

$list = $doc->getElementsByTagName("h1");
for ($i = 0; $i < $list->length; $i++) {
    print($list->item($i)->nodeValue . "<br/>\n");
}

Or you could also use XPath for more complex queries on the DOMDocument (see http://www.php.net/manual/en/class.domxpath.php)

$xpath = new DOMXPath($doc);
$list = $xpath->evaluate("//h1");


You're probably better of using an HTML parser. But for really simple scenarios, something like this might do:

if (preg_match_all('/<h\d>([^<]*)<\/h\d>/iU', $str, $matches)) {
    // $matches contains all instances of h1-h6
}


I know this is a super old post, however I wanted to mention the best way I was able to collectively grab heading tags.

<h1>title</h1> and <h2>title 2</h2>

This method (works as a regex, however PHP acts a bit differently.)

/<\s*h[1-2](?:.*)>(.*)</\s*h/i

use this in your preg_match

|<\s*h[1-2](?:.*)>(.*)</\s*h|Ui

$group[1] will include what ever is in between the heading tag. $group[0] is everything <h1>test</h

This will account for spaces, and if someone adds "class/id"

<h1 class="classname">test</h1>

the class/id (group) is ignored.

NOTE: When I analyze HTML tags, I always strip out and replace all White space, line breaks, tabs etc.. with a 1 space. This minimizes multi-lines, dotalls... And very large amounts of white space which in some cases can mess with regex formatting.

  • of course I am only grabbing 1-2 heading tags, change that to 0-9 to grab all.
  • If anyone else has a mod to add or a fix to my code, please respond, I'd really like to know.
  • On the contrary with Regex being bad with HTML, that is a very open argument. Because if you design your php functions, and regex expressions to perfectly strip away the junk and prepare the html for regex specific expressions, You will be perfectly able to grab what you are looking for. You can make enough regex functions to replace amateur html work.

Here is a link to the test page regex test


If you actually want to use regular expressions, I think that:

preg_match_all('/<h[0-6]>([^</h[0-6]>*)</h/i', $string, $matches);

should work as long as your header tags are not nested. As others have said, if you're not in control of the HTML, regular expressions are not a great way to do this.


It is recommended not to use regex for this job and use something SimpleHTMLDOM parser


please also consider the native DOMDocument php class.

You can use $domdoc->getElementsByTagName('h1') to get your headings.


I just want to share my solution:

function get_all_headings( $content ) {
    preg_match_all( '/\<(h[1-6])\>(.*)<\/h[1-6]>/i', $content, $matches );

    $r = array();
    if( !empty( $matches[1] ) && !empty( $matches[2] ) ){
        $tags = $matches[1];
        $titles = $matches[2];
        foreach ($tags as $i => $tag) {
            $r[] = array( 'tag' => $tag, 'title' => $titles[ $i ] );
        }
    }

    return $r;
}

This function will return an empty array if headings were not found or something like this:

array (
    array (
        'tag' => 'h1',
        'title' => 'This is a title',
    ),
    array (
        'tag' => 'h2',
        'title' => 'This is the second title',
    ),
)


this is an old questions, since there is no newer answers. i wrote this with php built in dom parser.

$dom -> loadHTML("your html string here..");
$h2s = $dom -> getElementsByTagName('h2');

foreach ( $h2s as $h2 )
{
  echo $h2 -> nodeValue;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消