我想解析一些HTML,以根据该文档中的标题创建嵌套导航。
像这样的数组就是我想要创建的:
[
'name' => 'section 1',
'number' => '1',
'level' => 1,
'children' => [
[
'name' => 'sub section 1',
'number' => '1.1',
'level' => 2,
'children' => []
],
[
'name' => 'sub section 2',
'number' => '1.2',
'level' => 2,
'children' => []
]
],
]
因此,如果文档在H2之后具有H3,则代码可以解析此并创建具有子元素的嵌套数组,用于每个连续的H标题层
我想它需要做一些主要的事情:
1.1.1
或1.1.2
这是我提取标题的代码:
$dom = new \DomDocument();
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
// Extract the heading structure
$xpath = new \DomXPath($dom);
$headings = $xpath->query('//h1|//h2|//h3|//h4|//h5|//h6');
我试图创建一个递归函数,但我不确定最好的方法来使它工作
测试非常困难,因为这取决于HTML的复杂程度和您使用的特定页面。此外,由于代码做了很多,我会让你知道它做了什么,因为解释会持续一段时间。 XPath是使用XPath select all elements between two specific elements作为参考来创建的,用于选择两个标记之间的数据。测试源(test.html)仅仅是....
<html>
<head>
</head>
<body>
<h2>Header 1</h2>
<h2>Header 2</h2>
<h3>Header 2.1</h3>
<h4>Header 2.1.1</h4>
<h2>Header 3</h2>
<h3>Header 3.1</h3>
</body>
</html>
实际代码是......
function extractH ( $level, $xpath, $dom, $position = 0, $number = '' ) {
$output = [];
$prevLevel = $level-1;
$headings = $xpath->query("//*/h{$level}[count(preceding-sibling::h{$prevLevel})={$position}]");
foreach ( $headings as $key => $heading ) {
$sectionNumber = ltrim($number.".".($key+1), ".");
$newOutput = ["name" => $heading->nodeValue,
"number" => $sectionNumber,
"level" => $level
];
$children = extractH($level+1, $xpath, $dom, $key+1, $sectionNumber);
if ( !empty($children) ) {
$newOutput["children"] = $children;
}
$output[] =$newOutput;
}
return $output;
}
$html = file_get_contents("test.html");
$dom = new \DomDocument();
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new \DomXPath($dom);
$output = extractH(2, $xpath, $dom);
print_r($output);
对extractH()
的调用参数很少。由于示例HTML仅以h2标签(无h1)开头,因此第一个参数为2.然后使用XPath和DomDocument对象。