用PHP包装带有div的HTML段(并从HTML标签生成目录)

My original HTML looks something like this:

<h1>Page Title</h1>

<h2>Title of segment one</h2>
<img src="img.jpg" alt="An image of segment one" />
<p>Paragraph one of segment one</p>

<h2>Title of segment two</h2>
<p>Here is a list of blabla of segment two</p>
<ul>
  <li>List item of segment two</li>
  <li>Second list item of segment two</li>
</ul>

Now, using PHP (not jQuery), I want to alter it, like so:

<h1>Page Title</h1>

<div class="pane">
  <h2>Title of segment one</h2>
  <img src="img.jpg" alt="An image of segment one" />
  <p>Paragraph one of segment one</p>
</div>

<div class="pane">
   <h2>Title of segment two</h2>
   <p>Here is a list of blabla of segment two</p>
   <ul>
     <li>List item of segment two</li>
     <li>Second list item of segment two</li>
   </ul>
</div>

So basically, I wish to wrap all HTML between sets of <h2></h2> tags with <div class="pane" /> The HTML above would already allow me to create an accordion with jQuery, which is fine, but I would like to go a little bit further:

I wish to create an ul of all the <h2></h2>sets that were affected, like so:

<ul class="tabs">
  <li><a href="#">Title of segment one</a></li>
  <li><a href="#">Title of segment two</a></li>
</ul>

Please note that I'm using jQuery tools tabs, to implement the JavaScript part of this system, and it does not require that the hrefs of the .tabs point to their specific h2 counterparts.

My first guess would be to use regular expressions, but I've also seen some people talking about DOM Document

Two solutions exist for this problem in jQuery, but I really need a PHP equivalent:

Could anyone please practically assist me please?

The DOMDocument can help you with that. I've answered a similar question before:

using regex to wrap images in tags

Update

Full code sample included:

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

$segments = array(); $pane = null;

foreach ($d->getElementsByTagName('h2') as $h2) {
    // first collect all nodes
    $pane_nodes = array($h2);
    // iterate until another h2 or no more siblings
    for ($next = $h2->nextSibling; $next && $next->nodeName != 'h2'; $next = $next->nextSibling) {
        $pane_nodes[] = $next;
    }

    // create the wrapper node
    $pane = $d->createElement('div');
    $pane->setAttribute('class', 'pane');

    // replace the h2 with the new pane
    $h2->parentNode->replaceChild($pane, $h2);
    // and move all nodes into the newly created pane
    foreach ($pane_nodes as $node) {
        $pane->appendChild($node);
    }
    // keep title of the original h2
    $segments[] = $h2->nodeValue;
}

//  make sure we have segments (pane is the last inserted pane in the dom)
if ($segments && $pane) {
    $ul = $d->createElement('ul');
    foreach ($segments as $title) {
        $li = $d->createElement('li');

        $a = $d->createElement('a', $title);
        $a->setAttribute('href', '#');

        $li->appendChild($a);
        $ul->appendChild($li);
    }

    // add as sibling of last pane added
    $pane->parentNode->appendChild($ul);
}

echo $d->saveHTML();

Use PHP DOM functions to perform this task.

..a nice PHP html parser is what you need. This one is good. Its a PHP equivalent to jquery.