Templating engine?

has has.temp2 at virgin.net
Sat Jul 3 00:58:20 CEST 2004

Thomas Rösner aka TRauMa <remove.all.to.last.dot.trauma at digital-trauma.de> wrote in message news:<cc0uc6$1ub$1 at newsserv.zdv.uni-tuebingen.de>...

> Only one question left: if you use a dom-like aproach to templating, don't
> you force a certain tree like structure on the template? 

That's the idea, yes. Object model == tree structure. Same principle
as in GUI toolkits. Even macro-based templates will follow a tree
structure in their logic (though they're not as explicit about it),
unless they're based on unstructured flow control constructs like
GOTOs. Structured programming == tree structures. There is no escape.

> As far as I
> understood, there is nothing like getElementbyID() to access a node object
> regardless of where it is located in the tree. 

There isn't, but you could always hack such a feature in if you wanted
to. (How useful it would be in practice I don't know; it doesn't
really make much sense in context of Repeater objects.)

> Say, I got a node named
> "Menu", which is a div containing some links and a logo (menu.logo), and I
> have to access this logo, and later on the designer (likely me wearing my
> designer hat and being ignorant about such issues) decides to move the logo
> somewhere else... 

Depends where you move it. e.g. If you start with the following node


and rearrange it to:


then the hierarchy is still the same, so no change to presentation
logic is required.

It's only with gross alterations like changing the template node
hierarchy, renaming/re-typing nodes, etc. that the presentation logic
must also change; e.g.:


> Wouldn't that be a case of presentation forcing changes
> upon application logic?

Gross changes to presentation markup will require changes to
presentation logic. Same would be true for a templating system like
Cheetah or PSP that embeds presentation logic in markup. Same would be
true for a Tkinter- or wxPython-based GUI. And so on. None of these
scenarios should ever require changes to business logic if designed
for proper separation between application layers.

Also remember there's no reason your presentation logic should be
physically embedded in the application core where they're hard or
impossible to access. Presentation code could be kept in standalone
files that sit in the same directory as the HTML templates they belong
to.  Or if you feel that having separate files for presentation markup
and presentation logic is a bit messy, you could put both into a
single file where [e.g.] the presentation logic follows the markup:

---- file '/foo/bar/MyTemplate.tpl' ----


on render_template(node,...):

----- end file -----

Just use the following to read this file in and separate and compile
its constituent parts:

templatePath = '/foo/bar/MyTemplate.tpl'

f = open(templatePath)
html, controllerSrc = f.read().split('</html>')
controller = compile(controllerSrc, templatePath, 'exec')
template = HTMLTemplate.Template(controller, html)

Or write your own HTML preprocessor based on HTMLParser and you could
even embed individual Python functions within separate processing
instructions that you can strew throughout your HTML, then have the
preprocessor separate them out and assemble the pieces into HTML
document and controller module. There's lots of ways you could hack
it. If you come up with something cool, send me a URL and I'll be
pleased to link to it.

> do you know any comparable Template Engine for PHP?

I don't, but even if there aren't any HTMLTemplate is small and simple
enough that it should be reasonably straightforward to port.
(Portability and hackability were two of the issues guiding its
design; the Python version is itself a port. I'll assume PHP will have
a suitable SAX-based HTML parser you can bolt it onto.) The only two
areas you might have trouble with are:

1. the syntactic sugar in the API, but that can easily be done without
(see the vanilla API design below)

2. the object cloning, which might not be feasible on other languages,
but that code could be rewritten to use regular object instantiation
instead of copying.

------- HTMLTemplate Vanilla API Reference Design -------

Node -- Abstract base class
		node(name) -- get a node
		setNode(name, node) -- replace a node

Container (extends Node) -- A mutable HTML element ('con')
		att(name) -- get a tag attribute's value
		setAtt(name, value) -- set a tag attribute's value
		delAtt(name) -- delete a tag attribute

		content() -- get the HTML element's content with &<>" characters
automatically escaped
		raw() -- get the HTML element's raw content (i.e. no automatic
character escaping)
		setContent(value) -- get the HTML element's content with &<>"
characters automatically escaped
		setRaw(value) -- set the HTML element's raw content (i.e. no
automatic character escaping)

		omit() -- don't render this node
		omitTags() -- render this node's content only

Repeater (extends Container) -- A mutable, repeatable HTML element
		repeat(callback, sequence, *args) -- render an instance of this node
for each item in sequence

Template (extends Node) -- The top-level template node
		Template(callback, html, attribute='node', encoder=defaultEncoder,
		render(*args) -- render this template
		structure() -- print the object model's structure for diagnostic use

More information about the Python-list mailing list