To finally grasp the whole idea of this parsing concept let's go straight on the script. I've coded the scripts under a class. With this you only have to import this class then use its function to parse your HTML files. To get a detailed explanation of what is this all about read the article of Wee Lep "PHP-HTML Templates: A New Working Relationship", which can be accessed here.. The concept of this parsing was taken from his article. The only reason in which this article was put into action was because Wee Lep didn't provide a running or working example of his concept, a problem which I also encountered when I tried to apply his scripts into my application. Taken from an extensive, serious research of various code around the net, I was able to generate these scripts which have a concept similar to what Wee Lep wanted to explain. Thus if you're into concept and discussion I suggest you read Wee Lep article as this article is only a working example of his idea. This article is code-centric, more on application. Probably, at the end of this article you'll be able to parse your HTML files and replace it with your desired values stored in an array. This article consisted of four topics of discussion of the templates: how to load templates, how to replace statics, how to replace dynamics. This template has been applied to my phpmylibrary.sourceforge.net application.

The Templates

To start our scripting lets first take a look at the example HTML template we would like parse. This kind of template can be edited from any HTML editor like Dreamweaver, MS Frontpage, etc., thus eliminating the confusion of webpage designer and webpage programmer and their fields of expertise. Designer will be able to freely create whatever design technique he/she wanted to make without disturbing the code of the programmer, on the other hand, the programmer simply stores their result in an array which will be encoded on HTML template created by the designer. This completely divides the world of the designer and the programmer and would probably help each other in enhancing much of their talent.
This is the desired output.


+-------------------------+-----------------------+-------------------+
| Polerio and PHPBUILDER  | Article about parsing | Some Fixed Values |
+-------------------------+-----------------------+-------------------+

	+----------+-------------------------+------------------+
	|   Date   |         Title           |      Author      |
	+----------+-------------------------+------------------+
	| 09/28/02 | Parsing Made Simple . . | Juan Tamad       |
	+----------+-------------------------+------------------+
	| 09/30/02 | PHP Templates: Revi. .  | Polerio Babao    |
	+----------+-------------------------+------------------+
	|    .     |            .            |        .         |
	+----------+-------------------------+------------------+
	|    .     |            .            |        .         |
	+----------+-------------------------+------------------+
	|    .     |            .            |        .         |
	+----------+-------------------------+------------------+

This is the HTML Template, template.html

<?php

<html><head><title></title></head>
<
body>
<
table><tr>
<
td><!--%ModuleTitle%--></td>
<
td><!--%SomeComment%--></td>
<
td><!--%FixedValues%-->
</
td></tr></table>
<
br><br>
!--%
00_BEGIN_NO_MESSAGES%-->
    <!--%
97_BEGIN_NO_MESSAGES%-->
    <
table border="1">
    <
tr><td>Date</td><td>Title</td><td>Author</td></tr>
    <!--%
9a_BEGIN_MESSAGE_LIST%-->
    <!--%
9a_ML_LOOPBEGIN%-->
    <
tr><td><!--%9adate_____%--></td><td><!--%9atitle____%--></td><td><!--%9aauthor___%--></td></tr>
    <!--%
9a_ML_LOOPEND%-->
    </
table>
    <!--%
9a_END_MESSAGE_LIST%-->
    <!--%
97_END_NO_MESSAGES%-->
<!--%
00_END_NO_MESSAGES%-->
</
body></html>

?>

Loading Templates

To load a template free from line feeds and carriage returns this function should be used.

<?php
function LoadTemplate($file="")
{
    
$strfile "$doc_root/".$file;
    if(!
file_exists($strfile)) print"Loading template failed!";
    
$thisfile file($strfile);
    while(list(
$line,$value) = each($thisfile)) {
        
$value ereg_replace("(\r|\n)","",$value);
        
$result .= "$value\r\n";
    }

    return 
$result;
}
?>
This function basically loads your HTML template. We have a variable "$doc_root", if you're using windows you probable have (c:/htdocs/) this kind of working directory. If you're in Linux system, you have /usr/local/apache or /var/www/html/ etc., file system. Thus select or copy-paste the location of your template and put it into your doc_root. If the loading is successful, this function will strip all of your carriage return and line feed characters as specified by \r\n thus making your HTML template imploded with \r\n. After replacing the \r\n with an empty value this function will then return its output stored in $result variable.

Replacing Statics


<?php
function ReplaceStatic($LoadTemplate=""$StaticName=""$StaticValue="")
{
    
$tcontent $LoadTemplate;
    
$j count($StaticName);
    for(
$i=0;$i<$j;$i++) {
    
$tcontent eregi_replace($StaticName[$i],$StaticValue[$i],$tcontent);
    }

    return 
$tcontent;
}
?>
This function simply replaces the variable from your template. A variable that occurs only ones, for instance title of the table, title of the site, etc. From the function we have a variable $LoadTemplate, this variable is the output of the function taken from LoadTemplate();. Thus to output some value on it you have to do some $LoadTemplate=LoadTemplate(); and we're sure that this will have a value of a flat HTML template loaded from your LoadTemplate function.
We've see that there's another variable in this function which is $StaticName, this variable is the one which can be found on your HTML template, a sample of this varialble looks like the following; , , , etc., we observed that this is a comment syntax from HTML. These are the following which should be replaced with some values after the parsing has been done. The values could be "Polerio and PHPBUILDER", "Article about parsing", "Some Fixed Values", etc. The values are then stored at $StaticValue variable. Perhaps you'd think already that this function is flexible because you only have to put what variable you want to use from your HTML template and encode/ replace it with values taken/generated from your PHP script. This is flexible in a sense that you're not limited to a fixed varialble, you can specify two or more variables into your HTML template.

How can we put it into action? We will use arrays. Thus to select what variables to be used and what values to be encoded into the given variables we will use a code that looks like the following;


<?php
$StaticName 
= array(
                
"<!--%ModuleTitle%-->"
                
"<!--%SomeComment%-->"
                
"<!--%FixedValues%-->"
                
);
$StaticValue = array(
                
"Polerio and PHPBUILDER"
                
"Article about parsing"
                
"Some Fixed Values"
                
);
$output ReplaceStatic($LoadTemplate$StaticName$StaticValue);
echo 
$output;
?>
I've only added $output to finally generate its result. Now continuing to a more complex parsing, let's proceed to dynamic parsing. The values to be encoded on HTML templates are dynamic which only means the result are more than one.

Dynamic

This is a bit long. I made this as function because I once tried copy-pasting this code again and again, into a different application, but now I've just included it in a class, making call just its class and its function. This is a bit complicated I think. This will parse the date, author and title field.

<?php
function DynamicRows($Prefix=""$LoadTemplate=""$RowName=""$RowValue="")
{
        
// start loopings
        
$tcontent $LoadTemplate;
        
$startlist strpos($tcontent,"<!--%".$Prefix."_BEGIN_MESSAGE_LIST%-->");
        
$endlist strpos($tcontent,"<!--%".$Prefix."_END_MESSAGE_LIST%-->")+28;
        
$listline substr($tcontent,$startlist+30,$endlist-$startlist-58);
        
$listlinetoreplace substr($tcontent,$startlist,$endlist-$startlist);
        
$startlistloop strpos($tcontent,"<!--%".$Prefix."_ML_LOOPBEGIN%-->");
        
$endlistloop strpos($tcontent,"<!--%".$Prefix."_ML_LOOPEND%-->")+22;
        
$listloop 
        
substr($tcontent,$startlistloop+24,$endlistloop-$startlistloop-46);


        
$beforeloop substr($listline,0,strpos($listline,"<!--%".$Prefix."_ML_LOOPBEGIN%-->"));
        
$afterloop substr($listline,strpos($listline,"<!--%".$Prefix."_ML_LOOPEND%-->")+22);
        
$newmsgs 0;
        for(
$i=0;$i<count($headers);$i++) {
            if(!
$headers[$i]["read"]) $newmsgs++;
            
$msglist .= eregi_replace("<!--%POLERIODUMMY%-->","Polerio",$beforeloop);
            
$start_pos=0;$end_pos=(count($RowValue));
            for(
$i=$start_pos;$i<$end_pos;$i++) {
                
$thisline "$listloop\r\n";

                
$s_pos=0;$e_pos=count($RowName);
                for(
$j=$s_pos;$j<$e_pos;$j++) {
                    
$thisline eregi_replace($RowName[$j],$RowValue[$i][$j],$thisline);
                }
            }
            
$msglist .= $thisline;
        } 
// end for
        
$msglist .= $afterloop;
        
$tcontent substr($tcontent,0,$startlist).$msglist.substr($tcontent,$endlist,strlen($tcontent));
        
// end loopings

        
return $tcontent;
}
?>
First, DynamicRows, why such a name? Because rows are not fixed, it's dynamic. $Prefix, this is used to determine or distinguish this loopings from other dynamic data you would want to create. Perhaps you want to lists some author/name into another table, with this you have the ability to distinguish it from the other. From the HTML given we use here a prefix "9a". We can see that "9a" appears on a dynamic table that will loop dependent upon the size of the array with which you store some value. Take note that we again use an array here to store values so that we could pass this values from one function to another.
$LoadTemplate, we use again load template function here because we are going to parse its dynamic variables. We have $RowName, this is the dynamic variables which will have some values after the parsing has been done, this is dynamic in a sense that this $RowName is unlimited. In our example these are the , , variables which will have some values after the parsing. The values which will be encoded in here will again come from an array. You can set as many column as you want because this function is flexible. You can add another field perhaps a rank, which increments when someone reads an article. We have a $RowValue variable, this is where the values will be passed. To get more idea of this concept do analyse line by line the coding of this function. But explaining it briefly, this function simply parses the template starting from reading/finding the BEGIN_MESSAGE_LIST comment up to END_MESSAGE_LIST comment, after this the function will loop through that variables dependent upon the size of the array which was taken from count(somearray) function. While looping through the MESSAGE_LIST comment, it is replacing one by one the values into the template variables thus giving a dynamic values.

<?php
<!--%00_BEGIN_NO_MESSAGES%-->
    <!--%
97_BEGIN_NO_MESSAGES%-->
    <
table border="1">
    <
tr>Date</td><td>Title</td><td>Author</td></tr>
    <!--%
9a_BEGIN_MESSAGE_LIST%-->
    <!--%
9a_ML_LOOPBEGIN%-->
    <
tr><td><!--%9adate_____%--></td><td><!--%9atitle____%--></td><td><!--%9aauthor___%--></td></tr>
    <!--%
9a_ML_LOOPEND%-->
    </
table>
    <!--%
9a_END_MESSAGE_LIST%-->
    <!--%
97_END_NO_MESSAGES%-->
<!--%
00_END_NO_MESSAGES%-->
?>
Applying this concept, the following code should be added to put values into the variables of your template.

<?php
$result
[0] = array("09/28/02","Parsing made simple","Juan Tamad");
$result[1] = array("09/30/02","PHP template revisited","Polerio Babao");
$tcontent $LoadTemplate;
$Prefix "9a"$RowValue $result;
$RowName = array("<!--%9adate_____%-->","<!--%9atitle____%-->","<!--%9aauthor___%-->");
echo 
$tcontent DynamicRows($Prefix$tcontent$RowName$RowValue);
?>
Now we have again a call for loading the template so that the parser will be able to determine the variables in template.html file. The prefix variable has been defined clearly. The result can be taken into your mysql result or any database application.

Erasing some of your HTML content

This kind of function will be needed because, sometimes you would like to hide the first result template. I made this script to limit my templates in displaying the full HTML. To have a clear grasp of what I am trying to imply read, this code line by line and you will see, it simply limits tables or sort of HTML tags so that it will not appear when not not needed.

<?php
function EmptySpace($Prefix=""$LoadTemplate="")
{
    
$tcontent $LoadTemplate;
    
$startnolist strpos($tcontent,"<!--%".$Prefix."_BEGIN_NO_MESSAGES%-->");
    
$endnolist strpos($tcontent,"<!--%".$Prefix."_END_NO_MESSAGES%-->")+27;

    
$nomessagesline 
    
substr($tcontent,$startnolist+29,$endnolist-$startnolist-56);
    
$nomessageslinetoreplace 
    
substr($tcontent,$startnolist,$endnolist-$startnolist);

    
$tcontent eregi_replace($nomessageslinetoreplace,"",$tcontent);
    return 
$tcontent;
}
?>
I called it empty space for a purpose of creating space for HTML tags not yet needed. It has a $Prefix variable to determine which position to start replacing some content with a space. The $prefix + BEGIN_NO_MESSAGES probably gives us the idea where the parser will start replacing empty space.
I will provide an example of the script. Go through the script and run it on your localhost to see the purpose of the EmptySpace function. Briefly, this function only hides tables which have no values yet. You can use this if you want to stop tables you do not need from appearing. I made this because the loading of templates reads and parses the whole HTML file and, if you will not replace the table, you do not need a space -- you will end up into tables with no values or data in it. To benefit fully by this function, put this in a class and simply call it whenever you want. This function has been applied into my phpmylibrary.sourceforge.net project.
The following are the scripts I've created in explaining this article.

<?php
template
.html
<code>
<
html><head><title></title></head>
<
body>
<
center>
<
table border="1"><tr>
<
td><!--%ModuleTitle%--></td>
<
td><!--%SomeComment%--></td>
<
td><!--%FixedValues%-->
</
td></tr></table>

<
br />

<!--%
00_BEGIN_NO_MESSAGES%-->
    <!--%
97_BEGIN_NO_MESSAGES%-->
    <
table border="1">
    <
tr><td>Date</td><td>Title</td><td>Author</td></tr>
    <!--%
9a_BEGIN_MESSAGE_LIST%-->
    <!--%
9a_ML_LOOPBEGIN%-->
    <
tr><td><!--%9adate_____%--></td><td><!--%9atitle____%--></td><td><!--%9aauthor___%--></td></tr>
    <!--%
9a_ML_LOOPEND%-->
    </
table>
    <!--%
9a_END_MESSAGE_LIST%-->
    <!--%
97_END_NO_MESSAGES%-->
<!--%
00_END_NO_MESSAGES%-->
</
center>
</
body></html>
?>
parser.py (I suggest to put this in a class so that you can call it easily.)

<?php

function LoadTemplate($file="")
{

    
$doc_root getenv('DOCUMENT_ROOT');
    
$strfile "$doc_root/".$file;
    if(!
file_exists($strfile)) print"Loading template failed!";
    
$thisfile file($strfile);
    while(list(
$line,$value) = each($thisfile)) {
        
$value ereg_replace("(\r|\n)","",$value);
        
$result .= "$value\r\n";
    }

    return 
$result;
}

function 
ReplaceStatic($LoadTemplate=""$StaticName=""$StaticValue="")
{
    
$tcontent $LoadTemplate;
    
$j count($StaticName);
    for(
$i=0;$i<$j;$i++) {
    
$tcontent eregi_replace($StaticName[$i],$StaticValue[$i],$tcontent);
}

return 
$tcontent;
}

function 
DynamicRows($Prefix=""$LoadTemplate=""$RowName=""$RowValue=""
{
    
// start loopings
    
$tcontent $LoadTemplate;
    
$startlist strpos($tcontent,"<!--%".$Prefix."_BEGIN_MESSAGE_LIST%-->");
    
$endlist strpos($tcontent,"<!--%".$Prefix."_END_MESSAGE_LIST%-->")+28;
    
$listline substr($tcontent,$startlist+30,$endlist-$startlist-58);
    
$listlinetoreplace substr($tcontent,$startlist,$endlist-$startlist);
    
$startlistloop strpos($tcontent,"<!--%".$Prefix."_ML_LOOPBEGIN%-->");
    
$endlistloop strpos($tcontent,"<!--%".$Prefix."_ML_LOOPEND%-->")+22;
    
$listloop substr($tcontent,$startlistloop+24,$endlistloop-$startlistloop-46);



    
$beforeloop substr($listline,0,strpos($listline,"<!--%".$Prefix."_ML_LOOPBEGIN%-->"));
    
$afterloop substr($listline,strpos($listline,"<!--%".$Prefix."_ML_LOOPEND%-->")+22);
    
$newmsgs 0;
    for(
$i=0;$i<count($headers);$i++)
    if(!
$headers[$i]["read"]) $newmsgs++;
    
$msglist .= eregi_replace("<!--%POLERIODUMMY%-->","Polerio",$beforeloop);
    
$start_pos=0;$end_pos=(count($RowValue));
    for(
$i=$start_pos;$i<$end_pos;$i++) {
    
$thisline "$listloop\r\n";

    
$s_pos=0;$e_pos=count($RowName);
    for(
$j=$s_pos;$j<$e_pos;$j++) {
        
$thisline eregi_replace($RowName[$j],$RowValue[$i][$j],$thisline);
    }

    
$msglist .= $thisline;
    } 
// end for
    
$msglist .= $afterloop;
    
$tcontent substr($tcontent,0,$startlist).$msglist.substr($tcontent,$endlist,strlen($tcontent));
    
// end loopings

    
return $tcontent;
}

function 
EmptySpace($Prefix=""$LoadTemplate="")
{

    
$tcontent $LoadTemplate;
    
$startnolist strpos($tcontent,"<!--%".$Prefix."_BEGIN_NO_MESSAGES%-->");
    
$endnolist strpos($tcontent,"<!--%".$Prefix."_END_NO_MESSAGES%-->")+27;

    
$nomessagesline 
    
substr($tcontent,$startnolist+29,$endnolist-$startnolist-56);
    
$nomessageslinetoreplace 
    
substr($tcontent,$startnolist,$endnolist-$startnolist);

    
$tcontent eregi_replace($nomessageslinetoreplace,"",$tcontent);
    return 
$tcontent;

}



$file="polerio/art/template.html";
$LoadTemplate LoadTemplate($file);
$StaticName = array("<!--%ModuleTitle%-->""<!--%SomeComment%-->""<!--%FixedValues%-->");
$StaticValue = array("Polerio and PHPBUILDER""Article about parsing""Some Fixed Values");
$LoadTemplate ReplaceStatic($LoadTemplate$StaticName$StaticValue);

$result[0] = array("09/28/02","Parsing made simple","Juan Tamad");
$result[1] = array("09/30/02","PHP template revisited","Polerio Babao");

//$result=""; // Uncomment this to get hide result table.
if(!$result$LoadTemplate EmptySpace("97"$LoadTemplate); // If this does not exist, table w/o value will exist
else {
    
$Prefix "9a"$RowValue $result;
    
$RowName = array("<!--%9adate_____%-->","<!--%9atitle____%-->","<!--%9aauthor___%-->");
    
$LoadTemplate DynamicRows($Prefix$LoadTemplate$RowName$RowValue);
}

$content $LoadTemplate;
echo 
$content;

?>