Php 根据标题标记自动生成嵌套目录
你们哪位狡猾的程序员可以向我展示一个优雅的php编码解决方案,用于根据页面上的标题标记自动生成嵌套的目录 因此,我有一个html文档:Php 根据标题标记自动生成嵌套目录,php,dynamically-generated,Php,Dynamically Generated,你们哪位狡猾的程序员可以向我展示一个优雅的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> Terrestri
<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代码自动生成)
我觉得它并不优雅,但可能有助于了解如何创建一个;) 它用于查找和操作原始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();
$htmlcode=innertext);
$id=str_replace(“”,“”,$innerTEXT);
$h->id=$id;//添加id属性,以便我们可以跳转到此元素
$level=intval($h->tag[1]);
如果($level>$last_level)
$toc=”;
否则{
$toc.=str_repeat(“”,$last_level-$level);
$toc.='';
}
$toc.=“”;
$last_level=$level;
}
$toc.=str_repeat(“ ”,$last_level);
$html_,其中_toc=$toc。“
”$html->save();
下面是一个使用以下内容的示例:
$doc=newDOMDocument();
$doc->loadHTML($code);
//创建文档片段
$frag=$doc->createDocumentFragment();
//创建初始列表
$frag->appendChild($doc->createElement('ol'));
$head=&$frag->firstChild;
$xpath=新的DOMXPath($doc);
$last=1;
//获取所有H1、H2、…、H6元素
foreach($xpath->query('/*[self::h1或self::h2或self::h3或self::h4或self::h5或self::h6]')作为$headline){
//获取当前标题的级别
sscanf($headline->tagName,$h%u',$curr);
//如有必要,移动头部参考
如果($curr<$last){
//上移
对于($i=$curr;$iparentNode->parentNode;
}
}如果($curr>$last&&$head->lastChild),则为else{
//向下移动并创建新列表
对于($i=$last;$ilastChild->appendChild($doc->createElement('ol'));
$head=&$head->lastChild->lastChild;
}
}
$last=$curr;
//添加列表项
$li=$doc->createElement('li');
$head->child($li);
$a=$doc->createElement('a',$headline->textContent);
$head->lastChild->appendChild($a);
//构建ID
$levels=array();
$tmp=&$head;
//遍历子树到该子树的片段根节点
而(!is_null($tmp)&&$tmp!=$frag){
$levels[]=$tmp->childNodes->length;
$tmp=&$tmp->parentNode->parentNode;
}
$id='sect'。内爆('.',数组_反向($levels));
//设定目的地
$a->setAttribute('href','#'。$id);
//添加锚到标题
$a=$doc->createElement('a');
$a->setAttribute('name',$id);
$a->setAttribute('id',$id);
$headline->insertBefore($a,$headline->firstChild);
}
//将片段附加到文档
$doc->getElementsByTagName('body')->item(0)->appendChild($frag);
//回显标记
echo$doc->saveHTML();
我找到了这个方法,作者是Alex Freeman():
preg#u match_all('#]*>.*?#',$html#u string,$resultats);
//重新格式化结果以使其更可用
$toc=内爆(“\n”,$resultats[0]);
$toc=str_replace(“”,$toc);
//将结果插入适当的HTML标记中
$toc=
材料表
“.$toc”
;
返回$toc;
在HTML中,标题必须写成:
<h2><a name="target"></a>Text</h2>
文本
看一下。它允许从嵌套标题生成目录。h1标记后面可以跟任何较低级别的h标记。该类使用递归从文章文本中提取标题不应该缩进并以1
开头?哦,我的错!我将编辑我的问题HTML内容是如何生成的?不是吗hat静态用户输入?如果是数据(数据库、阵列)将标题放在h
-标记中,如果您只有一个包含所有内容的字符串,那么会容易得多;然后您必须首先分析h
-标记的字符串。HTML位于数据库中,它包含一个字符串变量。我尝试了这一点。目前,它在$frag->appendChild上抛出一个致命错误。此代码有效只有当你的层次结构中没有像一个h1
后面跟着一个h3
这样的缺口时,这篇文章才是古老的,…但很有用!当我使用这个脚本时,我注意到OL和LI标记在结尾没有闭合。我需要在结尾处添加“$toc.=stru repeat(',$level);`在循环之外。
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;
<h2><a name="target"></a>Text</h2>