我希望在php中创建一个非常简单,非常基本的嵌套目录,它可以获取所有h1-6并适当地缩进内容。这意味着,如果我有类似的东西:
<h1>content</h1>
<h2>more content</h2>
我应该得到:
content
more content.
我知道创建缩进将是css,这很好,但是如何创建一个目录,其中包含指向页面内容的工作链接?
显然很难理解我的要求......
我要求一个函数读取一个html文档并取出所有h1-6并制作一个目录。
答案 0 :(得分:1)
为此,您只需在HTML代码中搜索标记。
我写了两个函数(PHP 5.4.x)。
第一个返回一个数组,其中包含目录的数据。数据只是它自己的标题,标签的id(如果你想使用锚点)和内容的子表。
function get_headlines($html, $depth = 1)
{
if($depth > 7)
return [];
$headlines = explode('<h' . $depth, $html);
unset($headlines[0]); // contains only text before the first headline
if(count($headlines) == 0)
return [];
$toc = []; // will contain the (sub-) toc
foreach($headlines as $headline)
{
list($hl_info, $temp) = explode('>', $headline, 2);
// $hl_info contains attributes of <hi ... > like the id.
list($hl_text, $sub_content) = explode('</h' . $depth . '>', $temp, 2);
// $hl contains the headline
// $sub_content contains maybe other <hi>-tags
$id = '';
if(strlen($hl_info) > 0 && ($id_tag_pos = stripos($hl_info,'id')) !== false)
{
$id_start_pos = stripos($hl_info, '"', $id_tag_pos);
$id_end_pos = stripos($hl_info, '"', $id_start_pos);
$id = substr($hl_info, $id_start_pos, $id_end_pos-$id_start_pos);
}
$toc[] = [ 'id' => $id,
'text' => $hl_text,
'sub_toc' => get_headlines($sub_content, $depth + 1)
];
}
return $toc;
}
第二个返回一个用HTML格式化toc的字符串。
function print_toc($toc, $link_to_htmlpage = '', $depth = 1)
{
if(count($toc) == 0)
return '';
$toc_str = '';
if($depth == 1)
$toc_str .= '<h1>Table of Content</h1>';
foreach($toc as $headline)
{
$toc_str .= '<p class="headline' . $depth . '">';
if($headline['id'] != '')
$toc_str .= '<a href="' . $link_to_htmlpage . '#' . $headline['id'] . '">';
$toc_str .= $headline['text'];
$toc_str .= ($headline['id'] != '') ? '</a>' : '';
$toc_str .= '</p>';
$toc_str .= print_toc($headline['sub_toc'], $link_to_htmlpage, $depth+1);
}
return $toc_str;
}
这两个功能都远非完美,但它们在我的测试中运行良好。随意改善它们。
注意:get_headlines
不是解析器,因此它不会对损坏的HTML代码起作用,只会崩溃。它也只适用于小写<hi>
- 标记。
答案 1 :(得分:0)
此函数仅对h2标签返回带有附加目录的字符串。 100%经过测试的代码。
function toc($str){ $html = preg_replace('/]+\>/i', '$0In This Article
', $str, 1); //toc just after first image in content $doc = new DOMDocument(); $doc->loadHTML($html); // create document fragment $frag = $doc->createDocumentFragment(); // create initial list $frag->appendChild($doc->createElement('ul')); $head = &$frag->firstChild; $xpath = new DOMXPath($doc); $last = 1; // get all H1, H2, …, H6 elements $tagChek = array(); foreach ($xpath->query('//*[self::h2]') as $headline) { // get level of current headline sscanf($headline->tagName, 'h%u', $curr); array_push($tagChek,$headline->tagName); // move head reference if necessary if ($curr parentNode->parentNode; } } elseif ($curr > $last && $head->lastChild) { // move downwards and create new lists for ($i=$last; $ilastChild->appendChild($doc->createElement('ul')); $head = &$head->lastChild->lastChild; } } $last = $curr; // add list item $li = $doc->createElement('li'); $head->appendChild($li); $a = $doc->createElement('a', $headline->textContent); $head->lastChild->appendChild($a); // build ID $levels = array(); $tmp = &$head; // walk subtree up to fragment root node of this subtree while (!is_null($tmp) && $tmp != $frag) { $levels[] = $tmp->childNodes->length; $tmp = &$tmp->parentNode->parentNode; } $id = 'sect'.implode('.', array_reverse($levels)); // set destination $a->setAttribute('href', '#'.$id); // add anchor to headline $a = $doc->createElement('a'); $a->setAttribute('name', $id); $a->setAttribute('id', $id); $headline->insertBefore($a, $headline->firstChild); } // echo $frag; // append fragment to document if(!empty($tagChek)): $doc->getElementsByTagName('section')->item(0)->appendChild($frag); return $doc->saveHTML(); else: return $str; endif; }