简体   繁体   中英

Wrap segments of HTML with divs (and generate table of contents from HTML-tags) with PHP

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();

使用PHP DOM函数执行此任务。

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM