Create a table of contents automatically.

Ok, here's what I want to do: my site has a ot of articles and they are all generally organized by h3 header tags for section headings (and I can clean it up to strictly enforce that). Now I am thinking that I want to add a TOC to the top of the article, in the sense of:

1. Introduction
2. Blah Blah
3. More Blah Blah
4. Conclusion

Each one would be a link to an anchor in the article.

So I need to 1) parse the article and add anchor tags to the headings and 2) build a TOC. I have a good idea of how to do this in other languages, but I am still pretty new to PHP and I am sure I would miss built-in functions that would help a lot. Any suggestions?
LVL 17
SqueebeeAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

red010knightCommented:
The functions that should help you in this are:

1>This function will help you parse the file
http://us4.php.net/manual/en/function.file.php
Reads entire file into an array (PHP 3, PHP 4 )
array file ( string filename [, int use_include_path] )

Identical to readfile(), except that file() returns the file in an array. Each element of the array corresponds to a line in the file, with the newline still attached. Upon failure, file() returns FALSE.

$parseFile=file(theFileToBeParsed);

2>To set up the anchor tags - something like this would do the job:

for($line=0;$line<sizeof($parseFile);$line++){
$string=$parseFile[$line];
if(!(stristr($sting,"<h3>"))){
  $markStr=addslashes(substr(stristr($sting,"<h3>"),0,strpos($string,"</h3>")));
      //0 may need to be changed to 3 on the above line
      //addslashes used in case of ' or " in the string
  $tocMark[]=$markStr;
  $newString="<h3><a name=\"".$markStr."\">".$markStr."</a></h3>";
  $string=$newString;
}//of if
$parseFile[$line]=addslashes($sting);
}//of for loop

3>To generate the file TOC, you will need to have a loop
  for($tocLine=0;$tocLine<sizeof($tocMark);$tocLine++){
    echo("<a href=\""filename.php#".$tocMark[$tocLine]."\">".$tocMark[$tocLine]."</a><br>\n");
  }

4>Once you get it to work I would recommend saving the source code as the new file so that your server isn't overloaded with generating TOC's all the time. But I don't know your situation so its only a recommendation.
0
red010knightCommented:
Oh and to Get the file back out properly you can either make the line:
$parseFile[$line]=addslashes($sting);
into
echo($sting) or echo(addslashes($sting) OR once out of the loop you should be able to do:
  $output=implode($parseFile);
  echo($output);

and that should do the rest...
I believe this code will do the trick - if you have any problems just make a post and I will fix it up.

Thanks
Red010Knight

0
SqueebeeAuthor Commented:
Oh, I didn't mention that the article will be a text  column in a mysql query, so we are assuming $row['article'] as the source of the article.
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

SqueebeeAuthor Commented:
Sorry, that piece of information changes things I suppose.
0
red010knightCommented:
Just a little and makes it a whole lot easier tooo.... SHEESH... but the concept is basically the same...

Why not give each article its own table, then divide the article up into sections in the table where the table row has the values:
title text

then a select * from articleName

$tocString="";
$bodyString="";
while blah = blahres
$tocString.="<a href=\""filename.php#".$tocMark[$tocLine]."\">".$tocMark[$tocLine]."</a><br>\n";
$bodyString="<h3><a name=\"".$blah['title']."\">".$blah['title']."</a></h3>\n".$blah['body'];
}
echo $tocString;
echo $bodyString;

and your page is generated
0
red010knightCommented:
and then if you wanted to have sub headings it wouldn't matter in the display much because you could just have another field that is 'level' that is either h1, h2, h3, h4, h5, or h6 and you can include that in the bodyString accordingly

Red010Knight
0
SqueebeeAuthor Commented:
Sorry, I am new to PHP but no to databases. A table per article would not be a normalized approach, and after screaming 'NORMALIZE OR DIE!' in the MySQL topic area I would look like a pretty big hypocrite to go with a table per article. That and the backend is very established are far as the DB is concerned, I am just adding a TOC onto the existing system.
0
shmertCommented:
I actually saw a really slick javascript that did this, using the DOM model.  Here's something in PHP:

<?php
$url = 'http://localhost/php/article.php';
$raw = file_get_contents($url);
$raw = preg_replace_callback('|<h3>([^<]*)</h3>|i', 'tocCallback', $raw);
echo '<ol>';
foreach($toc AS $key=>$value) {
        echo '<li><a href="#part' . ($key + 1) . '">' . $value . '</a></li>';
}
echo '</ol>';
echo $raw;

function tocCallback($matches) {
        global $toc;
        if (!$toc) $toc = array();
        $toc[] = $matches[1];
        $anchorName = 'part' . count($toc);
        return "<a name=\"$anchorName\"></a>" . $matches[0];
}
?>  
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
SqueebeeAuthor Commented:
Now that works extremely well! As Red010Knight provided a solution that would have worked had I given enough detail, I'm going to split a few his way.
0
SqueebeeAuthor Commented:
Followup for this at http://www.experts-exchange.com/Web/Web_Languages/PHP/Q_20844380.html
Another 500 points available.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.