【问题标题】:Making a list of H2-H3 elements in php在php中制作H2-H3元素列表
【发布时间】:2017-03-07 14:54:40
【问题描述】:

我有一个 PHP 变量,其中包含我的页面的 HTML 代码,它仅包含段落和 H2-H3 元素:

<h2>Header 1</h2>

<p>Some text</p>
...
<p>Some text</p>

<h3>Sub-header 1</h3>

<p>Some text</p>
...
<p>Some text</p>

<h2>Header 2</h2>

我正在尝试创建一个函数,该函数接受一个带有 HTML 代码的变量并返回一个带有 HTML ul 列表的字符串:

<ul>
    <li>Header 1
      <ul>
          <li>Sub-header 1</li>
      </ul>
    </li>
    <li>Header 2
      <ul>
          <li>Sub-header 2</li>
          <li>Sub-header 3</li>
      </ul>
    </li>
    <li>Header 3</li>
</ul>

这是我取得的成就,但我坚持检测何时添加 sub-ul 标记以及如何添加:

function generate_navigation($HTML) {
    $DOM = new DOMDocument();
    $DOM->loadHTML($HTML);

    $navigation = '<ul>';

    // Iterating through all elements
    $h2Iterator = 0;
    foreach($DOM->getElementsByTagName('*') as $element) {
        if($element->tagName == 'h2') {
            $h2Iterator++;
            $navigation .= '<li>' . $element->textContent . '</li>';
        } else if ($element->tagName == 'h3') {
            // How to add?
        }
    }

    return $navigation.'</ul>';
}

【问题讨论】:

  • 这些东西可以嵌套多深?如果它是任意深度,您可能需要一个递归函数。

标签: php html string dom


【解决方案1】:

我是这样设计的:

$dom = new domDocument;
$dom->loadHTML( $html );

$nav   = [];
$index = 0;

foreach ( $dom->getElementsByTagName('*') as $elem )
{
    if ( 'h2' == $elem->tagName )
    {
        $index++;
        $nav[ $index ]['h2'] = $elem->textContent;
    }


    if ( 'h3' == $elem->tagName )
    {
        $nav[ $index ]['h3'][] = $elem->textContent;
    }
}

会产生类似下面的东西,应该更容易循环通过

Array
(
    [1] => Array
        (
            [h2] => Headline Section
        )

    [2] => Array
        (
            [h2] => Headline Section
            [h3] => Array
                (
                    [0] => Sub-Section
                )

        )

    [3] => Array
        (
            [h2] => EstLaborum sunt incididunt
            [h3] => Array
                (
                    [0] => Sub-Section
                )

        )

)```

【讨论】:

    【解决方案2】:

    您需要跟踪打开的 h2 标签。不需要迭代器计数器,但需要迭代器状态。

    function generate_navigation($HTML) {
        $DOM = new DOMDocument();
        $DOM->loadHTML($HTML);
    
        $navigation = '<ul>';
    
        // Iterating through all elements
        $h2IteratorStatus = 0; //0-closed, 1-open
        $h3IteratorStatus = 0; //0-closed, 1-open
        foreach($DOM->getElementsByTagName('*') as $element) {
            if($element->tagName == 'h2') {
    
                if($h3IteratorStatus){
                    //it's open, need to close
                    $navigation .= '</ul>';
                    $h3IteratorStatus = 0;
                }
    
                if($h2IteratorStatus){
                    //it's open, need to close
                    $navigation .= '</li>';
                    $h2IteratorStatus = 0;
                }
    
                $h2IteratorStatus = 1;
                $navigation .= '<li>' . $element->textContent ;
    
            } else if ($element->tagName == 'h3') {
    
                if(!$h3IteratorStatus){
                    $navigation .= '<ul>';
                    $h3IteratorStatus = 1;
                }
    
                $navigation .= '<li>' . $element->textContent .'</li>';
            }
        }
    
        //check for last opened h3
        if($h3IteratorStatus){
            $navigation .= '</ul>';
        }
        //check for last opened h2
        if($h2IteratorStatus){
            //it's open, need to close
            $navigation .= '</li>';
        }
    
        return $navigation.'</ul>';
    }
    

    根据您的评论更新,以跟踪打开的 h3 标签。

    【讨论】:

    • 它完美地工作并解决了我的问题。谢谢!然而,每个“第二层”
    • 都被单独的
        标签包围,但我认为最好将每个

        下的所有“第二层”

      • 放在一个
          。有可能吗?
    猜你喜欢
    相关资源
    最近更新 更多
    热门标签