使用PHP中的DOMDocument在h3标记集之间包装所有HTML标记
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用PHP中的DOMDocument在h3标记集之间包装所有HTML标记相关的知识,希望对你有一定的参考价值。
我对杰克回答的问题有一个跟进问题: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);
}
}
请注意,将class="current"
添加到第一个h3组,并将style="display:block;"
添加到第一个div.ac_pane
是可选的,但非常感谢。
答案
根据要求,这是一个工作版本。 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。
以上是关于使用PHP中的DOMDocument在h3标记集之间包装所有HTML标记的主要内容,如果未能解决你的问题,请参考以下文章