Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/256.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在div中的头标记之间包装所有节点_Php_Dom - Fatal编程技术网

Php 使用DOMDocument在div中的头标记之间包装所有节点

Php 使用DOMDocument在div中的头标记之间包装所有节点,php,dom,Php,Dom,我有一组HTML文件要处理,其中相关的部分没有分组在容器中,可以包含几乎任何元素。新的部分目前仅由下一个标题标记描述: <h1>Section 1</h1> <p>Paragraph Text</p> <p>Paragraph Text</p> <h2>Section 2</h2> <p>Paragraph Text</p> <img src='an image' /&

我有一组HTML文件要处理,其中相关的部分没有分组在容器中,可以包含几乎任何元素。新的部分目前仅由下一个标题标记描述:

<h1>Section 1</h1>
<p>Paragraph Text</p>
<p>Paragraph Text</p>

<h2>Section 2</h2>
<p>Paragraph Text</p>
<img src='an image' />
<p>Further Paragraph Text</p>

<h1>Section 3</h1>
<p>Paragraph Text</p>
<p>Paragraph Text</p>
第1节
段落文本

段落文本

第二节 段落文本

进一步段落案文

第三节 段落文本

段落文本

如何使用将这些标题标记之间的所有内容包装在
中?即,将上述HTML转换为:

<div>
    <h1>Section 1</h1>
    <p>Paragraph Text</p>
    <p>Paragraph Text</p>
</div>

<div>
    <h2>Section 2</h2>
    <p>Paragraph Text</p>
    <img src='an image' />
    <p>Further Paragraph Text</p>
</div>

<div>
    <h1>Section 3</h1>
    <p>Paragraph Text</p>
    <p>Paragraph Text</p>
</div>

第一节
段落文本

段落文本

第二节 段落文本

进一步段落案文

第三节 段落文本

段落文本


到目前为止,我已经尝试了各种循环和XPATH选择器的组合,尝试在标题之间收集所有元素,以便像上面那样包装它们,但没有成功。

我最初的想法是基于操作输出缓冲区,因为我没有正确阅读开头段落和下面的内容函数用作对
ob\u start
的回调

您可能会注意到在函数开始时使用了$tags,随后是相当复杂的$query,$tags稍后用于帮助填充找到的节点,并确保在找到的下一个节点位于$tags数组中时停止,而不是编写模式并独立维护此数组。我认为这样会更灵活像这样

基本上,它是这样工作的:从提供的
$tags
数组构造一个查询模式,并使用它来查询HTMLDOM。如果存在匹配的节点,则遍历集合并将找到的节点(标头)添加到数组中。然后迭代找到的节点的兄弟节点,并将它们添加到相同的新数组中。在循环移动到集合中的下一个节点之前,请在重复该过程之前保存此数组。处理完所有发现的节点后,就可以创建容器
DIV
元素,确保再次填充所有子节点

<?php
    #https://stackoverflow.com/questions/59234379/using-domdocument-to-wrap-all-nodes-between-header-tags-in-div/59235431#59235431



    function wrapcallback( $buffer ){
        global $use_output_buffer;

        $delimiter='#';
        $tags=array('h1','h2','h3','h4','h5','h6');
        $query=implode('|', explode( $delimiter, sprintf( '//%s', implode( sprintf( '%s//', $delimiter ), $tags ) ) ) );
        $keepers=array();
        $parents=array();

        libxml_use_internal_errors( true );
        $dom=new DOMDocument;
        $dom->validateOnParse=false;
        $dom->recover=true;
        $dom->strictErrorChecking=false;
        $dom->preserveWhiteSpace=true;
        $dom->loadHTML( $buffer );
        $errors = libxml_get_errors();
        libxml_clear_errors();

        $xp=new DOMXPath( $dom );
        $col=$xp->query( $query );

        if( $col->length > 0 ){
            foreach( $col as $node ){

                $parents[]=$node->parentNode;
                $nodes=array( $node );

                while( $node = $node->nextSibling ){
                    if( in_array( $node->nodeName, $tags ) )break;
                    if( $node->nodeType==XML_ELEMENT_NODE  )$nodes[]=$node;
                }
                $keepers[]=$nodes;
            }
        }

        foreach( $keepers as $index => $obj ){
            $div=$dom->createElement('div');
            $parents[ $index ]->appendChild( $div );
            foreach( $obj as $child )$div->appendChild( $child );
        }

        $keepers = $parents = $xp = $div = null;
        echo $dom->saveHTML();
    };





    $html="
    <!DOCTYPE html>
    <html lang='en'>
        <head>
            <title>It's a Christmas Wrapper!</title>
            <style>
                body{
                    background:url( https://storage.needpix.com/rsynced_images/christmas-wallpaper-1480711266Vyi.jpg );
                    background-repeat:repeat;
                    color:white;
                }

            </style>
        </head>
        <body>

                <h1>Section 1</h1>
                <p>Paragraph Text</p>
                <p>Paragraph Text</p>

                <h2>Section 2</h2>
                <p>Paragraph Text</p>
                <img src='/images/laracroft.png' />
                <p>Further Paragraph Text</p>

                <h1>Section 3</h1>
                <p>Paragraph Text</p>
                <p>Paragraph Text</p>

        </body>
    </html>";

    wrapcallback( $html );

?>
validateOnParse=false;
$dom->recover=true;
$dom->strigerrorchecking=false;
$dom->preserveWhiteSpace=true;
$dom->loadHTML($buffer);
$errors=libxml_get_errors();
libxml_clear_errors();
$xp=新的DOMXPath($dom);
$col=$xp->query($query);
如果($col->length>0){
foreach($col作为$node){
$parents[]=$node->parentNode;
$nodes=数组($node);
而($node=$node->nextSibling){
如果(在数组中($node->nodeName,$tags))中断;
如果($node->nodeType==XML\u ELEMENT\u node)$nodes[]=$node;
}
$keepers[]=$nodes;
}
}
foreach($index=>$obj){
$div=$dom->createElement('div');
$parents[$index]->appendChild($div);
foreach($obj as$child)$div->appendChild($child);
}
$keepers=$parents=$xp=$div=null;
echo$dom->saveHTML();
};
$html=”
这是圣诞包装纸!
身体{
背景:网址(https://storage.needpix.com/rsynced_images/christmas-wallpaper-1480711266Vyi.jpg );
背景重复:重复;
颜色:白色;
}
第一节
段落文本

段落文本

第二节 段落文本

进一步段落案文

第三节 段落文本

段落文本

"; wrapcallback($html); ?>
我一整天都在努力解决这个问题,你对我采取了完全不同的方法,效果非常好。谢谢哦-很高兴听到它能满足你的需要。。祝您好运,如果父节点始终是同一个父节点,则上述编码操作可以简化,这意味着不需要维护可能的父节点列表,但实际上节省不了太多