【问题标题】:Wrap segments of HTML with divs (and generate table of contents from HTML-tags) with PHP使用 PHP 用 div 包裹 HTML 片段(并从 HTML 标记生成目录)
【发布时间】:2012-05-21 10:18:32
【问题描述】:

我的原始 HTML 看起来像这样:

<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>

现在,使用 PHP(不是 jQuery),我想改变它,像这样:

<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>

所以基本上,我希望用&lt;div class="pane" /&gt; 将所有HTML 包装在&lt;h2&gt;&lt;/h2&gt; 标记集之间。上面的HTML 已经允许我用jQuery 创建一个手风琴,这很好,但我想走一点进一步:

我希望为所有受影响的&lt;h2&gt;&lt;/h2&gt;set 创建一个 ul,如下所示:

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

请注意,我使用 jQuery 工具选项卡来实现该系统的 JavaScript 部分,并且不需要 .tabs 的 href 指向其特定的 h2 对应项。

我的第一个猜测是使用正则表达式,但我也看到一些人在谈论DOM Document

这个问题在 jQuery 中有两个解决方案,但我真的需要一个 PHP 等价物:

请问有人可以帮我吗?

【问题讨论】:

    标签: php regex dom


    【解决方案1】:

    DOMDocument 可以帮助您。我之前回答过类似的问题:

    using regex to wrap images in tags

    更新

    包含完整的代码示例:

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

    【讨论】:

    • 谢谢,DOMDocument 似乎是要走的路。您能否详细说明如何定位

      之间的所有内容以及如何处理那些

      的最后一次出现?
    • @maartenmachiels 当然,给我几个小时 :)
    • @maartenmachiels 回答已更新,请查看 :) 当然,我没花几个小时就完成了 =p
    • 令人难以置信的工作,伙计!我会尽快测试代码,很快就会回来批准你的答案...
    • 你是个天才。非常感谢!你的代码工作得很好。一些细节问题:由于某种原因,ul.tabshrefs 没有用lis 包裹。另外,您能告诉我如何防止使用&lt;html&gt;&lt;body&gt; 包装输出吗?
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      ..你需要一个不错的 PHP html 解析器。 This 一个很好。 它是一个相当于 jquery 的 PHP。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-05-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-08
        • 2011-10-05
        • 1970-01-01
        相关资源
        最近更新 更多