如何通过 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] =>...
使用 HTML 解析器。
一切都在里面。对
var_export
对象执行 $html
以查看整个对象结构。要将数据放入所需的数组中,您可能必须使用树遍历例程(即,firstChild、nextSibling 等),并构建数组。
我最初使用 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',
),
),
)