This is the philosophy of Ante, a new web template engine.

Sources of inspiration

First is Tapestry and Wicket. They gave me the idea of using standard HTML with minor extensions as my template language.

Second, is Web Forms and HTML5 as defined by the WHAT-WG. In the Web Forms spec is described how to handle repeating objects and form inputs in a clean and concise manner in HTML attributes. As I considered it, I started to think about automatically filling in the same information from the server side. That got me as far as using <span awname="objname">. Then as I moved forward, I realised that this could be a very useful way of seperating the concerns of the designer from the programmer. The designer would be able to design his pages using real data on the page instead of $objname$ to represent the data. He'll see what could actually show up!

The third influence is String Template. The author of that template engine explained why template engines should not have a complete Turing Machine available to the template writer. Indeed, doing so complicates things and makes it harder to create reusable templates. I was already thinking down these lines, and came to a similar realisation, but his paper (pdf) helped solidify the thoughts in my head. He says that the four things a template writer needs are:

  1. attribute reference,
  2. conditional template inclusion based on presence/absence of an attribute,
  3. recursive template references,
  4. and template application to a multivalued attribute

Attribute Reference is obvious, and I had already completed it and conditional inclusion when I read Dr. Parr's paper. Multivalue application I was figuring out how to do in such a way that the template writer can use sample data, all the while creating well-formed and valid HTML. Recursive reference I struggled with, thinking that it would be more complicated to write templates for than I wanted, but have finally created it anyway just to be complete. It would actually be quite useful for including html from a database, since in all cases of attribute reference, the text is escaped to avoid accidentally allowing the programmer from inserting a bunch of html inside the attribute, or worse, someone trying to do cross site scripting. Of course, once I allow html from a database, that immediately opens up the cross site scripting problems again.

Anyway, Terence Parr (creator of StringTemplate) went on to describe some good seperation rules to keep the template and the business logic seperate. They are

  1. View cannot modify model.
  2. View cannot perform computations
  3. view cannot compare data values
  4. view cannot make data type assumptions
  5. data from model must not contain layout or display information

Now, for exactly what all those things mean you can read his paper, but if we take those as good guidelines, we immediately see that template engines like Smarty don't make it easy to follow them. Indeed, with Smarty, it's very easy and tempting to do data value comparison and to include layout and display information in the model. I've done quite a bit of searching and haven't found very many template engines that don't make it extremely easy to do.

I have a few ideas of my own as to what should show up in a web template engine, including:

  1. handle output data as an example with which to work
  2. a template can be used in a mockup, because what you see is what you would get given the same data values
  3. recognise special html tags (such as input) and set the value attribute instead of between the tags.
  4. allow namespaces in view

Now, other programmers out there might not agree with my assessment of what should be in a template engine. I can see the look of disdain on their faces when they're told they can't include html in their output as it will be escaped. This, of course, being on the face of programmers who aren't fanatical about the Model-View-Controller methodologies. Personally, I'm still exploring the whole Model-View-Controller methodologies myself. I have been for over 7 years. As a general principle to aim toward to make things easier to modify later seems good. I've never worked with a system that enforced the seperation as Ante does. I created Ante more as a way of trying this out than anything.

Syntax of Ante

In a word: XHTML! (That's by a loose definition of "word".) The engine is specifically for the web and I'm using standard and validating html syntax. I've been doing some searching and haven't found many other template engine that uses straight HTML as the template. And those that try seem to use strange extensions like <jsp:include page="pagename"> or worse <%@ include file="pagename" %> (Those are out of JavaServer Pages from O'Reilly and Associates.) We may as well just return to PHP with <?php include 'filename'; ?>

Historical note, yes, I know PHP and JSP are old. There are newer template engines, but I've noticed that they all either ignore HTML (like Smarty) or they extend it in weird ways like JSP. I like neither.

So, instead I use the standard HTML syntax. No extensions, and you can use sample data where you're going to have real data show up. I do so using the class attribute. The class attribute is generally considered to be good for specifying things with CSS. Whether you're describing that all elements with the class 'message' are in red, or whatever. And true, class seems to have been placed into the HTML spec for that purpose; however, it's not limited to only that. Any HTML processor (including a template engine) can use it. They say that you knew a software tool was a success when it was being used for something its creator had never dreamed of. I'm not sure if the creators of the class attribute dreamed of using the class attribute for templating or not, but to me the class attribute is a success.

Attribute Reference

So, look at this fragment of code: <span class="message aw_msg">This is the template message</span>. You can see that it's an HTML fragment of a span that has two classes associated with it and some text in it. One of the classes is a normal CSS class "message" and the template designer would use her favourite web site editor to associate some CSS with that class. According to the HTML spec, an element may have multiple classes associated with it, seperated by spaces. The browser will apply CSS designs to the element according to the classes that are referenced in the CSS and will ignore any it doesn't know about. That's important, it means we can set the class on the element without worrying about using up the class attribute, such as if I had chosen to use the id attribute.

Now, when Ante processes the template, it recognizes the aw_ prefix on one of the classnames and when the page is rendered, Ante looks for a field in its data source by the name (without the aw_ prefix) and replaces the text inside the element with it. So, for this case, if the data source had a field 'msg' with the value "Hello, World", the output would be: <span class="message aw_msg">Hello, World</span>.

You'll notice that the class aw_msg is still on the span. This is intentional. It is so that I can do my #1 idea: "handle output data as an example with which to work". Someone could then take that output data and use it to create a new template (tweaking what's there for instance) and then return it to Ante as the template to work with.

My #3 idea is mainly to make things work properly when you come to trying to deal with input elements. <input class="aw_firstname" /> would be enough to produce the output <input class="aw_firstname" name="firstname" value="Alan" /> assuming that there was a field called firstname with my name as its value. The template designer need neither know nor care what the input name is going to be since it's not her job to know that. She just needs to know the class name to set. If the name or value attributes are set, Ante will overwrite them with the real values.

For more advanced use, such as outputting css on the fly (which, at my last job, we needed to do for various reasons), the template designer can set the class attribute on the style element. Yes, that's right. The HTML spec allows a class attribute on the style element. Normally you wouldn't, but we're still not breaking anything. The designer might have the CSS that doesn't change (the "normal" css) in a seperate file using link rel="stylesheet", or a style element, and then after that style element have one with a class="aw_varyingcss" and the programmer sets a field on the datasource with the variable css as its value (probably picked from a database). This can also work with the script tag!

For completeness, what about the case where the template designer wants to put negative numbers red (for an accounting package for instance)? First off, the programmer will have to give the ability to decide if a number is negative by adding an attribute (or we'll break seperation rules 2 through 4). Negativity is a business decision. So, say the programmer creates a field negative, then she could use conditional inclusion as described below, but that will break my idea #1. So instead, the programmer creates a field sign which can be negative, positive, zero. There's another special class prefix: ac_. The designer could create a class in CSS ac_sign_negative {color: red} and then assign it to the element that outputs the number like so. <td class="ac_sign_what aw_total">17.00</td> which would replace the word what with value of the field sign (negative etc.) and the 17.00 with the value of the field total.

NEW Then there's setting other attributes, such as the href of an anchor. <a href="thisisvariable.html" class="aa_href_url">Click Here</a>. This is how to set the value of an attribute from an Ante template. The syntax is straightforward aa_{attribute name}_{datasource name}

Conditional Inclusion

Okay, that covers Dr. Parr's first rule: attribute reference. Conditional inclusion is the second one. This is straightforward for simple text such as our span above. <span class="message aw_msg">This is the template message</span> will end up with an empty text since there's nothing to show if there is no field called msg on the datasource. So, following that if we have <span class="aw_showordont">This is the template text.<a href="url2.com">link</a> message</span>, we have a conditional. If there's a field not equal to the value false in the datasource, the contents of the element This is the template text.<a href="url2.com">link</a> message will be shown. And there could be a attribute reference or even a conditional which will be treated as expected inside there as well. If there is no such field, or it's equal false. The contents won't be shown.

Conditional inclusion means that we're wrapping an area with a name. For instance, <span class="aw_employee">look at <a class="aw_name" href="bob.html">Bob</a></span>, we have the field employee around the name, then we can have another span <span class="aw_manager">look at <a class="aw_name" href="john.html">John</a></span> and we might expect that the second time the name is referenced it is referring to the manager's name instead of the employee's name. And that's exactly what happens, provided the programmer passes in data that way. The programmer can set up employee as a namespace (allowed by my #3 idea) and manager as a namespace and assign a name attribute to each of them. The two spans above would then refer to the correct name attributes.

If the template writer desired to refer to the manager's name outside of a conditional inclusion element, she could write the following <span class="aw_manager-name">John</span>. This could even be inside the employee span, since the rendering engine will look for manager inside employee and not finding it, will look in the outer namespace.

Template application to a multivalued attribute

I'm going to skip Parr's rule 3 and come back to it. I'm instead going to skip to his rule 4: template application to a multivalued attribute. I built this on top of conditional inclusion and namespaces. The template writer creates something similar to <ul>
<li class="aw_friends-1">one</li>
<li class="aw_friends-2">two</li>
<li class="aw_friends-3">three</li>
</ul>
and Ante recognises that the friends attribute will be a multivalued attribute that should then be looped over. The loop is implicit on the fact that the name of the attribute is an integer! You may notice of course that using the namespaces described above, that you don't really need to type friends each time, instead doing this: <ul class="aw_friends">
<li class="aw_1">one</li>
<li class="aw_2">two</li>
<li class="aw_3">three</li>
</ul>
That's perfectly acceptable too, although when you start getting into multivalued attributes which have multivalued attributes as their values, it gets confusing.

Here's a messier example of that:

	<table class="aw_table ">
	<tr>
		<th class="aw_header-1 ">col1</th>
		<th class="aw_header-2 ">col2</th>
		<th class="aw_header-3 ">col3</th>
		<th class="aw_header-4 ">col4</th>
	</tr>
	<tr class="aw_1 ">
		<td class="aw_1 ">data1</td>
		<td class="aw_2 ">data2</td>
		<td class="aw_3 ">data3</td>
		<td class="aw_4 ">d3</td>
	</tr>
	<tr class="aw_2 ">
		<td class="aw_1 ">data4</td>
		<td class="aw_2 ">data5</td>
		<td class="aw_3 ">data6</td>
		<td class="aw_4 ">d6</td>
	</tr>
	<tr class="aw_3 ">
		<td class="aw_1 ">data7</td>
		<td class="aw_2 ">data8</td>
		<td class="aw_3 ">data9</td>
		<td class="aw_4 ">d9</td>
	</tr>
	<tr class="aw_4 ">
		<td class="aw_1 ">data10</td>
		<td class="aw_2 ">data11</td>
		<td class="aw_3 ">data12</td>
		<td class="aw_4 ">d12</td>
	</tr>
	</table>

Recursive Template Inclusion

Okay, now returning to the recursive template inclusion (Dr Parr's rule 3). I've added another prefix at_. Our four prefixes are aw_, ac_, aa_ and at_. That's all I've found are needed so far. Template inclusion is straightforward <div class="at_otherfile">this will be replaced by the other template</div> will replace the inside text with whatever the otherfile.html template will produce. In this case, the otherfile.html will have the same datasource and be in the same namespace as the div it's included within. For looping over a list of items, the programmer could make them all namespaces and the template writer would set the class to "at_otherfile aw_list-1", where list is the multivalued attribute which is itself a namespace.

Concluding notes

That rounds out the Ante philosophy. I've been mostly describing things from the template writer's point of view, since making things understandable to the template writer was one of my primary concerns. That reminds me of the other concerns I had:

Programming interface

Sample 1

Here's a simple example of how to use the Ante web template engine. The programmer might write something like this.

<?php
include_once 'path/to/Ante.inc';

// some data which could as easily come from a database
$datasource = new AwArrayDataSource( array(
		'name'=>'John Smith',
		'address' => '17 Avondale Crescent',
		'city' => 'Kingston',
		'province' => 'Ontario'));

Ante::render('m.html', $datasource);
?>

And the web designer would work with a piece of html like so:

<html><head>
		<title>This is some sample text</title>
		<style>
			.hello { color: red; }
			address { display: inline;}
		</style>
	</head>
	<body>
		Hello <span class="hello aw_name">Mark</span>.
		<pre>
I hear you live at
<address class="aw_address">123 Straight Street.</address>
<address class="aw_city">Calgary</address>, <address class="aw_province">Alberta</address>
		</pre>
</body></html>

And the name, address, city and province would all be substituted correctly.

Sample 2

A more complicated example would be like this:

<?php
include_once 'path/to/Ante.inc';

// some data which could as easily come from a database
$datasource = new AwArrayDataSource( array(
		'name'=>'John Smith',
		'address' => '17 Avondale Crescent',
		'city' => 'Kingston',
		'province' => 'Ontario',
		'children' => array(3, 'Bob', 'Margret', 'Jill')));

Ante::render('m2.html', $datasource);
?>

and the designer would work with something like so:

<html><head>
		<title>This is some sample text</title>
		<style>
			.hello { color: red; }
			address { display: inline;}
		</style>
	</head>
	<body>
		Hello <span class="hello aw_name">Mark</span>.
		<pre>
I hear you live at
<address class="aw_address">123 Straight Street.</address>
<address class="aw_city">Calgary</address>, <address class="aw_province">Alberta</address>
and your <span class="aw_children">1</span> children are 
<ul class="aw_children">
<li class="aw_1">Mark's Son</li>
</ul>
		</pre>
</body></html>
and the name and address will be replaced as before. Also, the number of children will be replaced in the appropriate span and the whole list of children; one li element for each child: Bob, Margret, and Jill.