Skip to page content or skip to Accesskey List.
Search evolt.org
evolt.org login: or register

Work

Main Page Content

Separating ASP Code from HTML in Templates

Rated 3.81 (Ratings: 3) (Add your rating)

Log in to add a comment
(7 comments so far)

Want more?

 
Picture of Junglee

Ashok Hariharan

Member info | Full bio

User since: January 27, 2002

Last login: January 27, 2002

Articles written: 5

Not so long ago, I got introduced to server side scripting for websites. I really began to enjoy myself. I could create my HTML and go around embedding my neat little <%%> asp tags. Man... it was fun. Then came a time when the client wanted me to change some of the visual design. "Just move this image from over here to there..." That's when my nightmares began.

It turned out to be an experience just about as pleasant as piercing needles through your eyes. Somewhere down the line my embedded ASP got jumbled. Something had to be wrong with what I was doing.

I needed a framework that would allow:

  • Single point of modification for templates on a site
  • Some kind of templating. I didn't want to use templating features of a specific HTML editor, since a lot of the time I end up editing html manually
  • Separate ASP from HTML
  • Allow reusability.

Some Nuclear Physics

The first part of our technique is basically about breaking up an HTML page into usable bits, when we need to display it on the website (some HTML Fission).

The second part is about rejoining the various bits, when we need to see the HTML as a whole (some HTML Fusion).

Fission

Why do I breakup a decent HTML page into pieces? There are quite a few advantages to this. For one, most websites have a common look and feel throughout, but when the look does need to change I would like to make it in 1 place. Sometimes only small things need to be changed like a navigation menu moving from the left hand side of the page to the right hand side. And many times the only thing different between look and feel of pages is something technically minor like the banner table being a 3-column table instead of a single column table, I didn't want to maintain a duplicate of the page template just to accommodate stuff like this.

There are additional advantages to this scheme. It's very easy to provide additional features like "print version" and also hidden/alternate navigation on specific pages.

Fissile Material

A typical page layout for my example would look like:

image sample page layout

As you can see I have divided the page into manageable tables.

I break up the page further to my convenience by demarcating specific parts of the page. For example, I mark the starting of the page header into 3 parts in the following way:

<!--[_part_start_:000.01.head_beg]-->
  <html>
  <head>
  <title><!--_VAR_TITLE_--></title>
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<!--[_part_start_:000.02.head_scr]-->
<script>
function dummy()
{
return 0;
}
</script>
<!--[_part_start_:000.99.head_end]-->
</head> 

As you can see I divided the HTML by using comment tags named in a particular way:
&lt;!--[_part_start_:xxx.xx.section_name]--&gt;. I used a naming convention as it allows me to later extract specific sections of this file using regular expressions. There are certain advantages to using a naming schema based on comment tags. For one, most HTML editors find them palatable and generally don't screw around with them (though personally I use the editor to make the initial layout, after that I hand-edit it...).

There is also a comment called &lt;!--_VAR_TITLE_--&gt; within the &lt;title&gt; tag. I use many of these _VAR_..._ type of comments in the page and I use them as "display" variables. These are searched and replaced at runtime. For example my ASP page replaces the &lt;!--_VAR_TITLE_--&gt; tag with the page title and the &lt;!--_VAR_CONTENT_1_--&gt; with the meat of the content at the time of script execution.

Blowin' it up

I have been using windows scripting to automate a lot of stuff on my PC, which means I use it again to make a script that would break up the HTML. I make use of the powerful JavaScript regexp object to do this. I execute the script on the layout HTML file in which I have also inserted my special comments. The cscript.exe interpreter that comes installed with windows takes care of interpreting and executing the JavaScript. I find windows scripting quite useful when I install ActivePython/Perl. I can even use Python or Perl scripts in it.

I execute my script on the HTML file using a command line syntax similar to this:

d:\files&gt;cscript tools.wsf //job:SplitHtml file.html input_folder

Incidentally the .wsf script file is called a package file and can contain scripts for multiple tasks (or <job> as Microsoft documentation calls it), so the SplitHtml is a job in the wsf file. The SplitHtml job executes on the html file and creates multiple text files. The text files are named using the tag we defined the section to be e.g.:
For a section that was marked as:
&lt;!--[_part_start_:<strong>000.01.head_beg</strong>]--&gt;
the HTML code in the section denoted by this comment tag gets extracted to a file called 000.01.head_beg.txt.

The SplitHtml script uses regular expression matching to extract the specific _part_start_ sections of the HTML page. The regular expression was defined in Javascript as:

<strong>re=new RegExp(&quot;\&lt;\!--\\[_part_start_:([0-9]{3}.[0-9]{2}.[A-Za-z_]+)\\]--\&gt;&quot;,&quot;g&quot;);</strong>

The script creates files for every such designated section.

image of explorer File Listing

I used a naming scheme for the comment tags, which ensures that the generated text files maintain the same sequence as the section dividing comments. Additionally the naming scheme allows me to add a new section comment without changing or disrupting the existing sequence. For instance if I needed to add some new HTML code between 000.02.head_scr and 000.99.head_end (head_end marks the &lt;/head&gt; tag..) sections, I can insert up to 95 individual parts in between by naming them as 000.03.tag1, 000.04.tag2.....When I sort the files in Windows Explorer by name, they are in exactly the same sequence as the _part_start_ comments were in the originating HTML file.

Maybe a better method of maintaining the sequence, would be to store the individual splits in a database table. Well, this works for me so I use it.

My ASP page scripts read the split parts sequentially (discussed later below) and renders the page.

When I want to see the page as a single HTML file, I again use a windows script called BuildHtml that rebuilds the HTML file from the parts text files. This job uses a very similar syntax to the SplitHtml method. I can also now use any HTML editor to edit the page layout.

All the source code for SplitHtml & BuildHtml with a couple of other script functions to query display tags & variable tags in a HTML file can be downloaded from:
source.zip

Fusion

We use some ASP fusion to create our dynamically generated page out of all the pieces we divided our HTML page into. Let's start with the basics. If my ASP page is called display.asp, I have a corresponding definition file for it called def.display.asp .

Defining The Ingredients

The definition file defines the sequence in which the individual HTML section files (the text files we just created) should be looked up & allows defining of a condition for looking up the section. This file is included at the beginning of every ASP file it defines the structure. For instance when display.asp is executed, the def.display.asp is first executed and a String variable is built which contains the HTML code for the page.

The def.display.asp file would look something like this:

  <%
/**************************
Section 1 -- HTML Lookups 
***************************/
/*now we being lookup the html sections */
/*this should always be shown..*/
/*Settings for this page*/
/*
  Header section
  */
  HtmlLookup("000.01.head_beg",true);
  HtmlLookup("000.02.head_scr",true);
  HtmlLookup("000.99.head_end",true);
  /*
  Banner section
  */
  HtmlLookup("001.00.body",true);
  HtmlLookup("001.01.banner",printable());
  HtmlLookup("001.02.horiz_nav",printable());
  /*
  Page Vertical Navigation
  */
  HtmlLookup("002.01.main_tbl_begin",true);
  HtmlLookup("002.02.vertical_nav_beg",true);
  HtmlLookup("002.03.vertical_nav",printable());
  HtmlLookup("002.04.vertical_nav_end",true);
  HtmlLookup("002.05.content_begin",true);
  HtmlLookup("002.08.content_end",true);
  HtmlLookup("002.09.main_tbl_end",true);
  HtmlLookup("003.01.footer",true);
  HtmlLookup("009.99.end_page",true);
%>

The HtmlLookup function takes the section name as the 1st parameter (this happens to be the primary name for the text file) and a 2nd parameter which can be used to conditionally display the section. For instance, in the sample with this article I hide a part of the navigation when the page is being viewed in printable mode (I set a page to printable mode by passing a query string parameter).
The multiple calls to HTMLLookup builds a string variable with the HTML code for the page. Based on the section name that has been passed the lookup function opens the corresponding .txt file and builds up the HTML.

Concocting the page for the final output

Now to the structure of our main ASP file display.asp . This page has a few SSI includes, and importantly this is where our main code to pick up the content from a database would reside. The specific content is then updated into the specific comment _VAR_iables I described earlier. I have a helper function called HtmlTransform which takes the _VAR_ variable name as the 1st parameter and the actual content to be displayed in place of that variable as a string parameter.

In the HtmlTransform function I search and replace every instance of the comment variable with the content string. Which means that I could have _VAR_TITLE_ or any other display tage appearing more than once. My search & replace function would appear as:

 replace(strHtml, &quot;\&lt;\!--&quot;+strVariable+&quot;--\&gt;&quot;,
  strReplace) ;

where strVariable is anything like (_VAR_TITLE_, _VAR_CONTENT_1_ etc.), (the replace function is some code taken from one of the gazillion javascript sites...)

There is an additional advantage to using a _VAR_ style of variable. For instance if my vertical navigation menu bar (typically on the left or hand side of a page) is not to appear on the print version or a hidden navigation version of the page, I can save the overhead of a lookup to the database for that information (This would be relevant if the menu navigation or any of the display element which is to be hidden in a print version is picked up from a database), by simply checking if the _VAR_ variable for the menu exists in my HTML string. Something like:

if (getHtml().indexOf("<!--_VAR_LEFTMENU_-->") != -1)
 //only if the HTML string contains a leftmenu display 
 //variable pickup the content for it
{
 strVertMenuOut = LookupFromDatabase();
 }

So my display.asp script would look something like this:

<%@ LANGUAGE=JScript%>
<!--common ssis-->
<!--#include file="inc/globvars.asp"-->
<!--#include file="inc/funcs.asp"-->
<!--#include file="inc/setprintable.asp"-->
<!--end common includes-->
<!--page defintion ssi-->
<!--#include file="def.display.asp"-->
<%
  /*
  Section 2 -- HTML Transforms 
  */
  //Code to fetch content from database
  //Code to fetch stuff like page title etc. 
  var strContent1;
  var strContent2;
  //here we just fill with dummy info
  strContent1 = "<h2>My Content1</h2>";
  strContent2 = "<h2>My Content2</h2>";
  //Code to fetch Navigation menus etc.
  //.....
  //again I fill up some dummy links for my vertical menu
  strVertNav = "<br><a href=\"http://dir.evolt.org\"> 
  Evolt directory</a><br><a href=\"http://browsers.evolt.org\">Evolt 
  Browsers</a>";
  //....
  //.....

  //begin transforms
  HtmlTransform("_VAR_TITLE_", "HTML Templating sample code");
  HtmlTransform("_VAR_CONTENT_1_", strContent1);
  HtmlTransform("_VAR_CONTENT_2_", strContent2);
  HtmlTransform("_VAR_VERT_NAV_", strVertNav);
%>
  <!--output page html here-->
  <%=getHtml()%>
<!--page end-->

Main advantages of this method

  • Separation of HTML from ASP code
  • Splitting of page HTML increases flexibility & makes changes easier
  • Makes creation of print versions, alternate navigations easier
  • Easy to adapt to other non-asp languages (hopefully!) 

Some drawbacks of this method

  • The method is very much dependent on a proper sequential naming scheme for named _part_ comments (I maintain a sequential documented list of _part_ and _VAR_ comments in an excel sheet just for my reference)
  • Additional Scripts like SplitHtml & BuildHtml need to be used to view the HTML file as a whole when required (and this is dependent on a proper naming scheme)
  • There might be a higher performance overhead since all the HTML is looked up and filled in a string and then the named comments replaced

Sample code

All the sample ASP & WSF script code with sample files can downloaded from:
source.zip

Related links

I found some similar methods & ideas discussed at:
4guysfromrolla
These are a couple of sites on Windows Scripting that I have found useful:
WinScripter.com
Ian Morrish's site on Windows scripting
Just as I was posting this article, I saw this nice article on regex by sprocket:
Regular Expression basics

Ashok is based in Nairobi, Kenya. When not busy dodging vagrant matatus in Nairobi traffic, he keeps himself upto date by evolt-ing.

good, but more drawbacks than stated

Submitted by mwarden on April 13, 2002 - 14:56.

There really is no benefit to using the search & replace method over including a single "settings" include file that would include a variable set to the title of the page. in fact, the performance hit incurred with the search & replace method makes it better to use the include file method. And you're right to think there might be a higher performance hit by replacing the "variables" after the entire page is in a variable, rather than replacing them in their smaller chunks and then concatenating into a single variable. Good thinking.

Also, note that there is quite a performance hit every time your script accesses the filesystem. Since you're doing it many times per page, you might want to consider moving it all to a database.

This would probably be easier to do in other languages that have "dynamic file inclusion", where one can conditionally include files (which isn't possible in ASP without rolling your own filesystemobject-based inclusion system).

login or register to post comments

An alternative template system for PHP coders

Submitted by skunk on April 14, 2002 - 03:23.

If that article whet your appetite but you're of the PHP disposition you may want to have a look at Smarty. It's a very advanced templating solution for PHP which incorporates template compilation (in to native PHP code), caching, template loops and conditionals, plugins and much more. Check out www.phpinsider.com/php/code/Smarty and smarty.php.net for more information.

login or register to post comments

overly complex?

Submitted by aardvark on April 14, 2002 - 11:13.

This method seems overly complex from the start. Generally, if I'm going to rely on FSO and includes to create a templated site, it's because it's a lower budget and I want to minimize the time investment. All my HTML parsing is done by hand, and seemingly more quickly than it would take to write up the script, and I don't have the overhead of that script every time the page renders, just include calls. I have each content page call one include file, which in turn calls all the other includes for the template. A content page may look like this:

<%
strTitle = "Page title for breadcrumb, <h1> and <title> tag"
strMetaDescription = "meta description"
strMetaKeywords = "meta keywords"
%>

<% SUB Content %>
Content
<% END SUB %>
<!--#include file ="/includes/template.asp"-->

The template page itself then calls in the includes for the navigation, header, footer, breadcrumb, etc. and takes the title and meta information variables and stuffs them into the template. The Content sub gets called in by the template itself, displaying wherever I want. To change the template of a content page, I simply change the include call to another file, perhaps "template42.asp."

login or register to post comments

RE:

Submitted by Junglee on April 15, 2002 - 03:04.

mwarden :

Also, note that there is quite a performance hit every time your script accesses the filesystem. Since you're doing it many times per page, you might want to consider moving it all to a database....

I know this is a age old debate, but isnt filesystem access is much faster by quite a few multiples than accessing the same stuff via a database connection ?
though having it in a db is definitely more manageable than text files...

There really is no benefit to using the search & replace method over including a single "settings" include file ....

Again ,sorry man, but i disagree over here. There might be a higher performance hit in the search replace method , but with the settings method you mentioned again i face the same problem of having some embedded asp code in my html template -- avoiding that as much as possible was the main idea of this whole method....

aardvark:

I think what you described is quite similar to what mwarden had mentioned above about a settings file, again the same issue of embedded asp code...

login or register to post comments

File access vs DB access

Submitted by sgd on April 15, 2002 - 12:58.

I know this is a age old debate, but isnt filesystem access is much faster by quite a few multiples than accessing the same stuff via a database connection ? though having it in a db is definitely more manageable than text files...

File system access can get bogged down in high traffic scenarios due to file locking and thread waiting. DB access, on the other hand, is much better suited for high traffic (multiple threads can get at the content instead of waiting for a particular thread or the filesystem to be ready). That and the management advantage is enough for me to almost always use a db instead of the filesystem.

login or register to post comments

file access and locking

Submitted by Junglee on April 16, 2002 - 02:03.

sgd :

i agree with you on the management advantages in using a db...

sorry to go a bit off topic now though but...:

If i am opening a file just for reading and not for writing it wouldnt be locked at all , so the issues of locking & thread waiting wouldnt come up.

login or register to post comments

call an html include in an ASP file

Submitted by sonia on February 19, 2003 - 04:50.

hello I have a query I am trying to create an template in an html format. and call it in an asp file. How do I change only a specific part of that template. please help

login or register to post comments

The access keys for this page are: ALT (Control on a Mac) plus:

evolt.orgEvolt.org is an all-volunteer resource for web developers made up of a discussion list, a browser archive, and member-submitted articles. This article is the property of its author, please do not redistribute or use elsewhere without checking with the author.