我有一个问题的跟进问题,杰克已经回答了这个问题: Wrap segments of HTML with divs (and generate table of contents from HTML-tags) with PHP
我一直在努力为上面的答案添加一些功能,以获得以下结果。
这是我目前的HTML:
<h3>Subtitle</h3>
<p>This is a paragraph</p>
<p>This is another paragraph</p>
<h3>Another subtile
<h3>
<p>Yet another paragraph</p>
这就是我想要实现的目标:
<h3 class="current">Subtitle</h3>
<div class="ac_pane" style="display:block;">
<p>This is a paragraph</p>
<p>This is another paragraph</p>
</div>
<h3>Another subtitle</h3>
<div class="ac_pane">
<p>Yet another paragraph</p>
</div>
我一直在尝试修改上面示例中的代码,但无法弄清楚:
foreach ($d->getElementsByTagName('h3') as $h3) {
$ac_pane_nodes = array($h3);
for ($next = $h3->nextSibling; $next && $next->nodeName != 'h3'; $next = $next->nextSibling) {
$ac_pane_nodes[] = $next;
}
$ac_pane = $d->createElement('div');
$ac_pane->setAttribute('class', 'ac_pane');
// Here I'm trying to wrap all tags between h3-sets, but am failing!
$h3->parentNode->appendChild($ac_pane, $h3);
foreach ($ac_pane_nodes as $node) {
$ac_pane->appendChild($node);
}
}
请注意,向第一个h3集添加class="current"
以及向第一个style="display:block;"
添加div.ac_pane
是可选的,但我们非常感谢。
答案 0 :(得分:4)
根据要求,这是一个工作版本。 IMO XSLT仍然是最适合此类问题的解决方案(实际上将一些XML转换为其他XML)但我不得不承认使用常规代码进行分组更容易!
我最终只是稍微扩展了DOM API,只是为了在DOMElement上添加一个实用程序insertAfter
方法。没有它可以做到,但它更整洁:
根据评论中所要求的所有标签更新绕过DIV
<?php
class DOMDocumentExtended extends DOMDocument {
public function __construct($version = "1.0", $encoding = "UTF-8") {
parent::__construct($version, $encoding);
$this->registerNodeClass("DOMElement", "DOMElementExtended");
}
}
class DOMElementExtended extends DOMElement {
public function insertAfter($targetNode) {
if ($targetNode->nextSibling) {
$targetNode->parentNode->insertBefore($this, $targetNode->nextSibling);
} else {
$targetNode->parentNode->appendChild($this);
}
}
public function wrapAround(DOMNodeList $nodeList) {
while (($node = $nodeList->item(0)) !== NULL) {
$this->appendChild($node);
}
}
}
$doc = new DOMDocumentExtended();
$doc->loadHTML(
"<h3>Subtitle</h3>
<p>This is a paragraph</p>
<p>This is another paragraph</p>
<h3>Another subtile</h3>
<p>Yet another paragraph</p>"
);
// Grab a nodelist of all h3 tags
$nodeList = $doc->getElementsByTagName("h3");
// Iterate over each of these h3 nodes
foreach ($nodeList as $index => $h3) {
// Special handling for first h3
if ($index === 0) {
$h3->setAttribute("class", "current");
}
// Create a div node that we'll use as our wrapper
$div = $doc->createElement("div");
$div->setAttribute("class", "ac_pane");
// Special handling for first div wrapper
if ($index === 0) {
$div->setAttribute("style", "display:block;");
}
// Move next siblings of h3 until we hit another h3
while ($h3->nextSibling && $h3->nextSibling->localName !== "h3") {
$div->appendChild($h3->nextSibling);
}
// Add the div node right after the h3
$div->insertAfter($h3);
}
// UPDATE: wrap all child nodes of body in a div
$div = $doc->createElement("div");
$body = $doc->getElementsByTagName("body")->item(0);
$div->wrapAround($body->childNodes);
$body->appendChild($div);
echo $doc->saveHTML();
请注意,loadHTML将添加doctype,html和body节点。 They can be stripped out if needed 的