【问题标题】:find elements with "simple_HTML_DOM" and merge them找到带有“simple_HTML_DOM”的元素并将它们合并
【发布时间】:2014-06-30 01:50:48
【问题描述】:

我想通过 simple_html_dom 提取 html 字符串的所有 p 元素。应该得到p元素的顺序。

<section class="box_1">
    <header class="trigger"><h2>Title</h2></header>
    <div class="content">
        <div class="box_2">
            <div class="class"></div>
            <div class="content">
                <p>Text Level 2</p>
                <p>More Text Level 2</p>
            </div>
        </div>
        <div class="box_2">
            <div class="class"></div>
            <div class="content">
                <p>Text Level 2</p>
                <div class="box_3">
                    <div class="content">
                        <p>Text Level 3</p>
                    </div>
                </div>
            </div>
        </div>
    </div>
</section>

但是同一个内容容器中的所有 p 元素都应该合并在一起。

我试过这个:

foreach($html->find('p') as $element) { 
    if ($element->parent()->parent()) {
        $class= $element->parent()->parent()->getAttribute('class');
        if ($class=="box_3") $level = 3;
        else if ($class=="box_2") $level = 2;
        else if ($class=="box_1") $level = 1;
    }
    else { $level = 0; }
    $array_content_element = array("level" => $level, "inhalt" => $element->plaintext);
    array_push($array_content, $array_content_element);
}

但是有了这个,即“Text Level 2”和“More Text Level 2”将作为两个元素处理。但它们应该合并到“Text Level 2\nMore Text Level 2”中,这应该作为一个元素来处理。

所以在这个例子中,结果应该是一个包含三个元素(而不是四个)的数组。

更新:我忘记了一些事情。在节元素之外可以有 p 元素。请看下面的“Lorem ipsum”。

<p>Lorem ipsum</p>
<p>Lorem ipsum</p>
<section class="box_1">
    <header class="trigger"><h2>Title</h2></header>
    <div class="content">
        <div class="box_2">
            <div class="class"></div>
            <div class="content">
                <p>Text Level 2</p>
                <p>More Text Level 2</p>
            </div>
        </div>
        <div class="box_2">
            <div class="class"></div>
            <div class="content">
                <p>Text Level 2</p>
                <div class="box_3">
                    <div class="content">
                        <p>Text Level 3</p>
                    </div>
                </div>
            </div>
        </div>
    </div>
</section>
<p>Lorem ipsum</p>
<p>Lorem ipsum</p>
<section class="box_1">
    <header class="trigger"><h2>Title</h2></header>
    <div class="content">
       <p>Text Level 1</p>
    </div>
</section>
<p>Lorem ipsum</p>
<p>Lorem ipsum</p>

这些 p 元素应该像其他元素一样对待(总结一个块的 p 元素)。在这种情况下,级别 = 0。

【问题讨论】:

    标签: php simple-html-dom


    【解决方案1】:

    您必须首先确定哪个是哪个。是不是孤儿。然后,如果它到达批次的末尾,只需更改为下一个键/批次(不再有 p 标记)。考虑这个例子:

    include 'simple_html_dom.php';
    $html_string = '<p>Lorem ipsum</p><p>Lorem ipsum</p><section class="box_1"> <header class="trigger"><h2>Title</h2></header> <div class="content"> <div class="box_2"> <div class="class"></div> <div class="content"> <p>Text Level 2</p> <p>More Text Level 2</p> </div> </div> <div class="box_2"> <div class="class"></div> <div class="content"> <p>Text Level 2</p> <div class="box_3"> <div class="content"> <p>Text Level 3</p> </div> </div> </div> </div> </div></section><p>Lorem ipsum</p><p>Lorem ipsum</p><section class="box_1"> <header class="trigger"><h2>Title</h2></header> <div class="content"> <p>Text Level 1</p> </div></section><p>Lorem ipsum</p><p>Lorem ipsum</p>';
    $html = str_get_html($html_string);
    $array_content = array();
    $index = 0;
    foreach($html->find('p') as $key => $tag) {
        if($tag->parent()->tag == 'root') {
            // if alone p tag
            if(!isset($array_content[$index])) {
                $array_content[$index] = array('level' => 0, 'inhalt' => $tag->innertext);
            } else {
                $array_content[$index]['inhalt'] .= "\n" . $tag->innertext;
            }
    
        } elseif($tag->parent->class == 'content') {
            // handle tags with proper parents
            $type = $tag->parent->parent->class;
             switch($type) {
                case 'box_1': $level = 1; break;
                case 'box_2': $level = 2; break;
                case 'box_3': $level = 3; break;
            }
    
            if(!isset($array_content[$index])) {
                $array_content[$index] = array('level' => $level, 'inhalt' => $tag->innertext);
            } else {
                $array_content[$index]['inhalt'] .= "\n" . $tag->innertext;
            }
    
        }
    
        // change index if set to next batch
        if(!isset($tag->next_sibling()->tag) || $tag->next_sibling()->tag != 'p') {
            $index++;   
        }
    
    }
    
    echo '<pre>';
    print_r($array_content);
    

    应该输出:

    Array
    (
        [0] => Array
            (
                [level] => 0
                [inhalt] => Lorem ipsum
    Lorem ipsum
            )
    
        [1] => Array
            (
                [level] => 2
                [inhalt] => Text Level 2
    More Text Level 2
            )
    
        [2] => Array
            (
                [level] => 2
                [inhalt] => Text Level 2
            )
    
        [3] => Array
            (
                [level] => 3
                [inhalt] => Text Level 3
            )
    
        [4] => Array
            (
                [level] => 0
                [inhalt] => Lorem ipsum
    Lorem ipsum
            )
    
        [5] => Array
            (
                [level] => 1
                [inhalt] => Text Level 1
            )
    
        [6] => Array
            (
                [level] => 0
                [inhalt] => Lorem ipsum
    Lorem ipsum
            )
    
    )
    

    【讨论】:

    • 我使用了 find('p') 因为我需要获取元素的顺序。
    • @user3142695 查看我的修订版,我希望这个适合
    • 太好了!感谢到目前为止。我在我的帖子里忘记了一些东西。所以我更新了它。请看一下。希望你能解决这个问题。
    • @user3142695 哇!你的结构变得更复杂了,检查我的修改
    • @user3142695 我的逻辑有误,请查看修订版
    猜你喜欢
    • 1970-01-01
    • 2017-11-21
    • 2014-09-06
    • 1970-01-01
    • 2014-05-25
    • 2023-03-11
    • 1970-01-01
    • 2022-01-08
    • 2018-06-12
    相关资源
    最近更新 更多