递归解析嵌套的<ol>列表并生成表示其结构和值的多维列表

问题描述 投票:0回答:3

如何通过 PHP 解析多级 HTML 列表并获取数组?

我正在尝试这个代码

$text = '<ol>
            <li>31</li>
            <li>32</li>
            <li>33</li>
            <li>34</li>
            <li>
                <ol>
                    <li>341</li>
                    <li>342</li>
                    <li>343</li>
                    <li>344</li>
                    <li>
                        <ol>
                            <li>3441</li>
                            <li>3442</li>
                            <li>3443</li>
                            <li>3444</li>
                        </ol>
                    </li>
                </ol>
            </li>
        </ol>';

$html = str_get_html($text);
foreach( $html->find('ol') as $ol)
{
    $array[] = $ol->innertext; 
}
print_r($array);

这是结果

Array
(
    [0] => 
            <li>31</li>
            <li>32</li>
            <li>33</li>
            <li>34</li>
            <li>
                <ol>
                    <li>341</li>

                    <li>342</li>
                    <li>343</li>
                    <li>344</li>
                    <li>
                        <ol>
                            <li>3441</li>
                            <li>3442</li>

                            <li>3443</li>
                            <li>3444</li>
                        </ol>
                    </li>
                </ol>
            </li>
        
    [1] => 
                    <li>341</li>
                    <li>342</li>
                    <li>343</li>
                    <li>344</li>
                    <li>
                        <ol>
                            <li>3441</li>
                            <li>3442</li>

                            <li>3443</li>
                            <li>3444</li>
                        </ol>
                    </li>
                
    [2] => 
                            <li>3441</li>
                            <li>3442</li>

                            <li>3443</li>
                            <li>3444</li>       
)

但是我需要这样的东西

Array
(
    [0] => Array
               (
              [0] => Array
                         (
                          [0] =>...
php list recursion html-parsing listitem
3个回答
1
投票

使用 HTML 解析器


1
投票

一切都在里面。对

var_export
对象执行
$html
以查看整个对象结构。要将数据放入所需的数组中,您可能必须使用树遍历例程(即,firstChild、nextSibling 等),并构建数组。


0
投票

我最初使用 DomDocument 和 Xpath 采用递归方法,在查询父项之前查询某个级别中的所有非父项,但这可能不是所需的输出结构(尤其是使用“有序”列表!)。 这是该脚本(演示

function parseOrderedList(DOMXPath $xpath, DOMNode $node) {
    $result = [];
    foreach ($xpath->query('li[not(ol) and string-length(text()) > 0]', $node) as $li) {
        $result[] = $li->nodeValue;
    }
    foreach ($xpath->query('li/ol', $node) as $ol) {
        $result[] = parseOrderedList($xpath, $ol);
    }
    return $result;
}

$dom = new DOMDocument();
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
var_export(
    parseOrderedList(new DOMXPath($dom), $dom->getElementsByTagName('ol')->item(0))
);

相反,此脚本将在遇到列表项时累积列表项以保留原始结构。 (演示)

function parseOrderedList(DOMXPath $xpath, DOMNode $node) {
    $result = [];
    foreach ($xpath->query('li/ol | li/text()', $node) as $child) {
        if ($child->nodeName === 'ol') {
            $result[] = parseOrderedList($xpath, $child);
        } elseif (($nodeValue = trim($child->nodeValue)) !== '') {
            $result[] = $nodeValue;
        }
    }
    return $result;
}

$dom = new DOMDocument();
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
var_export(
    parseOrderedList(new DOMXPath($dom), $dom->getElementsByTagName('ol')->item(0))
);

为了演示第二个片段的效果,下面是一些示例输入 HTML 和生成的结果:

输入:

$html = <<<HTML
<ol>
    <li>31</li>
    <li>32</li>
    <li>
        <ol>
            <li>foo</li>
            <li>
                <ol>
                    <li>bar</li>
                </ol>
            </li>
        </ol>
    </li>
    <li>33</li>
    <li>34</li>
    <li>
        <ol>
            <li>341</li>
            <li>342</li>
            <li>343</li>
            <li>344</li>
            <li>
                <ol>
                    <li>3441</li>
                    <li>3442</li>
                    <li>3443</li>
                    <li>3444</li>
                </ol>
            </li>
        </ol>
    </li>
</ol>
HTML;

输出:

array (
  0 => '31',
  1 => '32',
  2 => 
  array (
    0 => 'foo',
    1 => 
    array (
      0 => 'bar',
    ),
  ),
  3 => '33',
  4 => '34',
  5 => 
  array (
    0 => '341',
    1 => '342',
    2 => '343',
    3 => '344',
    4 => 
    array (
      0 => '3441',
      1 => '3442',
      2 => '3443',
      3 => '3444',
    ),
  ),
)
© www.soinside.com 2019 - 2024. All rights reserved.