Sunday 4 May 2008

Using XSLTs as a template engine in Zend

I've been working my way through a book that is using the Zend framework to do—buzzword approaching—"Web 2.0" stuff, and it started to mention the Smarty template engine. It seems the author, as well as many other PHP developers love this silly template engine stuff made up placemarker tags. Whereas I'm sure Smarty has lots of really cool features which would make my life a lot easier, I really couldn't be bother to learn how it works, and figure out what it needs from me so that it does just that. I seem to prefer the idea of my application models spitting out well-formed XML and using XSLT to style this to whatever template style I want to use later on.

I don't know why I like the idea so much. I think it's the extent to which the model doesn't care how the data is rendered, it's job is just to deliver it and it does that through XML. There is of course a parsing delay involved in doing transforms and I'm going to try to get some data or results of my own to try and analyse that, but for the time being I'm happy. There's even the possibility of processing the document client-side by either delivering pure XML with a stylesheet declaration, or using a javascript library like Sarissa and falling back to server-side transforms onlyZend to do XSLT transform instead of rendering templates and it's just about working. But it's led me to thinking about the bigger picture. XSLT allows us to include multiple stylesheets in one document by using expressions such as import and include. So why can't we make a master XSLT template file which doesn't transform any XML itself, but simply matches the document root to apply its template only once, but then crucially providing a placeholder for an imported stylesheet in the right place. This would allow me to use it as a 'master view' which is combined with the view my controller action renders.

There is however, a few problems. Whereas now my view renders whatever XML its passed using a single stylesheet, it now has to use the master stylesheet, but the master itself has to be aware of which view-specific stylesheet to include. This is getting a bit too much like a template language – replacing strings in the master template file with a path to the view specific stylesheet, and that's what I'm trying to avoid. The other problem is with CSS. Putting persistant navigation in the master stylesheet is fine, but what happens when you want to change the CSS class of one of the link elements? You have no hook to the master from the view specific stylesheet. I thought about having the navigation as its own XML file – easily editable and adaptable. Then view scripts can be used to change that nav XML, marking which link should have a CSS class of "current" and combining it with any data XML the view has received assuming there and some mechanisms are in place for the master stylesheet to find those flags, and produce the right XHTML output. Perhaps xml namespaces are the right way to go here, in order to differentiate between nav and content XML. Ideally, minimising the number of transforms is a good idea, so I don't want to have to transform the nav XML data, then use another template to transform that result to the final output including the actual content. The content XML and nav XML could be combined just before XSLT processing. It would be simple to wrap content XML from the model with persistent data. But the problem still remains to tell the master stylesheet which view specific stylesheet to include in order to render it correctly.

Javascript may be an alternative. Client-side transforms has the nice quirk of sorting through XSLT which is really neat, but Javascript is so horrible to code with. I have to think about it more.

1 comment:

Michele said...

Silly Michele. Just put a reference to the view specific stylesheet in the wrapping XML around the content.