在php中创建目录

时间:2013-03-26 02:28:37

标签: php tableofcontents

我希望在php中创建一个非常简单,非常基本的嵌套目录,它可以获取所有h1-6并适当地缩进内容。这意味着,如果我有类似的东西:

<h1>content</h1>
<h2>more content</h2>

我应该得到:

content
    more content.

我知道创建缩进将是css,这很好,但是如何创建一个目录,其中包含指向页面内容的工作链接?

显然很难理解我的要求......

我要求一个函数读取一个html文档并取出所有h1-6并制作一个目录。

2 个答案:

答案 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', '$0 

In 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; }