Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用PHP中的DOMDocument在h3标记集之间包装所有HTML标记_Php_Html_Domdocument - Fatal编程技术网

使用PHP中的DOMDocument在h3标记集之间包装所有HTML标记

使用PHP中的DOMDocument在h3标记集之间包装所有HTML标记,php,html,domdocument,Php,Html,Domdocument,我有一个后续问题,杰克已经回答了我的问题: 我一直在尝试为上面的答案添加一些功能,以便得到以下结果 这是我现在的HTML: <h3>Subtitle</h3> <p>This is a paragraph</p> <p>This is another paragraph</p> <h3>Another subtile <h3> <p>Yet another paragraph

我有一个后续问题,杰克已经回答了我的问题:

我一直在尝试为上面的答案添加一些功能,以便得到以下结果

这是我现在的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>

请注意,将
class=“current”
添加到第一个h3集合,以及将
style=“display:block;”
添加到第一个
div.ac\u窗格是可选的,但非常感谢。

根据要求,这里是一个工作版本。IMO XSLT仍然是最适合这类问题的解决方案(将一些XML转换为其他XML,真的),但我必须承认,使用常规代码进行分组要容易得多

最后,我稍微扩展了DOM API,只是为了在DomeElement上添加一个实用工具
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();

根据要求,这里是一个工作版本。IMO XSLT仍然是最适合这类问题的解决方案(将一些XML转换为其他XML,真的),但我必须承认,使用常规代码进行分组要容易得多

最后,我稍微扩展了DOM API,只是为了在DomeElement上添加一个实用工具
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();

XSLT是我的建议,但使用它进行分组是。。。至少可以说是复杂的(即,将连续的p标签分组到单个div中)。这是一个值得考虑的问题。如果您对XSLT解决方案持开放态度,请告诉我。谢谢!你查过上面的链接了吗?这个解决方案做了一些适当的分组,我只需要修改它,这样它就可以包装所有的东西,除了h3的问题。。。你能看一下吗?提前感谢。此版本与链接中的版本有一个关键区别。在链接版本中,h2作为节点集的一部分被包含,而在这个版本中,h3被排除在集合之外。这就是你的问题所在。如果这个提示不起作用,请告诉我,我会为youHi matb33编写一个工作版本,这正是我遇到麻烦的原因。我无法理解上面代码的内部工作原理。我将非常非常感谢一个工作版本!你能做这些荣誉吗?:-)我建议使用XSLT,但使用它进行分组是。。。至少可以说是复杂的(即,将连续的p标签分组到单个div中)。这是一个值得考虑的问题。如果您对XSLT解决方案持开放态度,请告诉我。谢谢!你查过上面的链接了吗?这个解决方案做了一些适当的分组,我只需要修改它,这样它就可以包装所有的东西,除了h3的问题。。。你能看一下吗?提前感谢。此版本与链接中的版本有一个关键区别。在链接版本中,h2作为节点集的一部分被包含,而在这个版本中,h3被排除在集合之外。这就是你的问题所在。如果这个提示不起作用,请告诉我,我会为youHi matb33编写一个工作版本,这正是我遇到麻烦的原因。我无法理解上面代码的内部工作原理。我将非常非常感谢一个工作版本!你能做这些荣誉吗?:-)非常感谢你!我将尽快测试并尝试实现您的代码,并将很快得到您的批准。谢谢,此解决方案非常有效!非常感谢!最后一个小细节:有没有一种简单快捷的方法可以用另一个div来包装这个新创建的html?谢谢大家。一切都很好!一个真正的职业选手!非常感谢你!我将尽快测试并尝试实现您的代码,并将很快得到您的批准。谢谢,此解决方案非常有效!非常感谢!最后一个小细节:有没有一种简单快捷的方法可以用另一个div来包装这个新创建的html?谢谢大家。一切都很好!一个真正的职业选手!
<?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();