2011-02-06 99 views
1

你們哪一位狡猾的程序員能向我展示一個優雅的php編碼解決方案,用於根據頁面上的標題標籤自動生成一個嵌套的內容表?根據標題標籤自動生成嵌套目錄

所以我有這樣一個html文件:

<h1> Animals </h1> 

Some content goes here. 
Some content goes here. 

<h2> Mammals </h2> 

Some content goes here. 
Some content goes here. 

<h3> Terrestrial Mammals </h3> 
Some content goes here. 
Some content goes here. 

<h3> Marine Mammals </h3> 
Some content goes here. 
Some content goes here. 

<h4> Whales </h4> 
Some content goes here. 
Some content goes here. 

更具體地說,我想的內容鏈接到同一頁面上標題的嵌套列表的形式鏈接表:

表的內容(由PHP代碼自動生成)

  1. 動物
    1. 哺乳動物 個
      1. Terrestrial_Mammals
      2. Marine_Mammals
+0

哺乳動物不應縮進並以`1`開始? – 2011-02-06 08:25:41

+0

哎呀,我的壞!我將編輯我的問題 – Manu 2011-02-06 08:45:36

回答

4

我發現這個方法中,由Alex弗里曼(http://www.10stripe.com/articles/automatically-generate-table-of-contents-php.php):

preg_match_all('#<h[4-6]*[^>]*>.*?<\/h[4-6]>#',$html_string,$resultats); 

    //reformat the results to be more usable 
    $toc = implode("\n",$resultats[0]); 
    $toc = str_replace('<a name="','<a href="#',$toc); 
    $toc = str_replace('</a>','',$toc); 
    $toc = preg_replace('#<h([4-6])>#','<li class="toc$1">',$toc); 
    $toc = preg_replace('#<\/h[4-6]>#','</a></li>',$toc); 

    //plug the results into appropriate HTML tags 
    $toc = '<div id="toc"> 
    <p id="toc-header">Table des matières</p> 
    <hr /> 
    <ul> 
    '.$toc.' 
    </ul> 
    </div><br /><br />'; 

    return $toc; 

在HTML,頭文件必須寫成:

<h2><a name="target"></a>Text</h2> 
6

我不覺得它優雅,但在獲得如何建立一個總的想法可能會幫助;)

It使用simple_html_dom找到並在原始HTML

$htmlcode = <<< EOHTML 
<h1> Animals </h1> 
Some content goes here. 
Some content goes here. 
<h2> Mammals </h2> 
Some content goes here. 
Some content goes here. 
<h3> Terrestrial Mammals </h3> 
Some content goes here. 
Some content goes here. 
<h3> Marine Mammals </h3> 
Some content goes here. 
Some content goes here. 
<h4> Whales </h4> 
Some content goes here. 
Some content goes here. 
EOHTML; 
// simpehtmldom or other dom manipulating library 
require_once 'simple_html_dom.php'; 

$html = str_get_html($htmlcode); 

$toc = ''; 
$last_level = 0; 

foreach($html->find('h1,h2,h3,h4,h5,h6') as $h){ 
    $innerTEXT = trim($h->innertext); 
    $id = str_replace(' ','_',$innerTEXT); 
    $h->id= $id; // add id attribute so we can jump to this element 
    $level = intval($h->tag[1]); 

    if($level > $last_level) 
     $toc .= "<ol>"; 
    else{ 
     $toc .= str_repeat('</li></ol>', $last_level - $level); 
     $toc .= '</li>'; 
    } 

    $toc .= "<li><a href='#{$id}'>{$innerTEXT}</a>"; 

    $last_level = $level; 
} 

$toc .= str_repeat('</li></ol>', $last_level); 
$html_with_toc = $toc . "<hr>" . $html->save(); 
4

這裏操縱元件是一個使用DOMDocument一個例子:

$doc = new DOMDocument(); 
$doc->loadHTML($code); 

// create document fragment 
$frag = $doc->createDocumentFragment(); 
// create initial list 
$frag->appendChild($doc->createElement('ol')); 
$head = &$frag->firstChild; 
$xpath = new DOMXPath($doc); 
$last = 1; 

// get all H1, H2, …, H6 elements 
foreach ($xpath->query('//*[self::h1 or self::h2 or self::h3 or self::h4 or self::h5 or self::h6]') as $headline) { 
    // get level of current headline 
    sscanf($headline->tagName, 'h%u', $curr); 

    // move head reference if necessary 
    if ($curr < $last) { 
     // move upwards 
     for ($i=$curr; $i<$last; $i++) { 
      $head = &$head->parentNode->parentNode; 
     } 
    } else if ($curr > $last && $head->lastChild) { 
     // move downwards and create new lists 
     for ($i=$last; $i<$curr; $i++) { 
      $head->lastChild->appendChild($doc->createElement('ol')); 
      $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); 
} 

// append fragment to document 
$doc->getElementsByTagName('body')->item(0)->appendChild($frag); 

// echo markup 
echo $doc->saveHTML();