Feed Sign in with OpenID OpenID

Simon Willison’s Weblog

Custom XML templating with PHP

Dynamic XML conversion using the SAX parser and a stack is the best new article I’ve seen on PHPBuilder in a very long time. It introduces several interesting ideas. The first is something I’ve been thinking about for a while now: using PHP’s output buffering to implement a kind of templating system so that all of the scripts in a system just have to generate an intermediate content type, then the output buffering function adds on the HTML framework and finalises the page. The second idea is ingenious: invent XML elements to represent specific behaviours, then handle them with a SAX before the page is displayed. Here’s some example code from the article:

<doc title="Pizza menu" bgcolor="lightblue">
	<bigheadline>
		Pizza Palace - Our Menu for  <dayofweek />
	</bigheadline>
	<br /><br />
	<b>Buon appetito!!!</b>
	<br /><br />
	
	<nicebox bordercolor="green">
		<product id="0" /><br />
		<product id="1" /><br />
		<product id="2" /><br />
		<product id="3" /><br />
		<product id="4" /><br />
	</nicebox>
</doc>

The tutorial describes a full implementation to make use of the custom tags demonstrated above. It’s advocating a full CMS where pages are described using a custom XML format, but the idea could be used in a whole load of different ways. I touched on this approach with my Form Validation prototype but this really shows how much further the concept can be taken. Best of all, the performance hit should be pretty minimal due to the absurd speed of PHP’s XML functions.

This is Custom XML templating with PHP by Simon Willison, posted on 4th July 2003.

View blog reactions

Next: Food for thought

Previous: Browser innovation is anything but dead

8 comments

  1. That's nice, but I think we've got something else for that: XSLT. It doesn't make to much sense to invent PHP scripts to parse XML to HTML if there already is another tool to do it for us, right?

    Manuzhai - 5th July 2003 10:03 - #

  2. I think you might want to have a look at the XML Transformer PEAR package I wrote. Slides from my PHP Conference talk are here.

    Sebastian Bergmann - 5th July 2003 11:02 - #

  3. Manuzhai: I disagree. XSLT solves a different problem: it transforms one type of XML document in to another. The SAX approach described in the article allows you to define custom tag behaviour - for example, it would give you the ability to embed <image id="34" /> in your document and have the SAX processor replace that with an HTML image tag with the correct alt attribute, width and height attributes for the image referenced in your database as having an ID of 34.

    Sebastian: wow, that looks like a really interesting package. I'll grab it and see what I can do with it. Thanks!

    Simon Willison - 5th July 2003 11:48 - #

  4. Okay, so you're propagating some of the Business Logic to a layer at a higher level so that you won't have to deal with it yourself. I still wonder if there is an XSLT implementation in userland PHP. It would be very nice (if the performance is sufficient) to just poop out XML to the ob and then transform it to HTML. It would kinda eliminate the need for a whole templating engine, and it's a standard. Oh, well.

    Manuzhai - 5th July 2003 13:27 - #

  5. Good article. Nice to see an approach to templating which doesn't involve placing control structures in the template.

    As the author point out at the end, one short coming I can see here is when you have nested tags;

    "With some add-ons, this stack processing is quite powerfull, but the code for the processing functions can become rather complicated when you add intelligence to them and give them access to other levels of the stack (the parent tags)."

    Working on Sax Filters (there's fairly documentation / explaination in the package), when I get spare moments, which for me presents a code structure which is clear enough to make processing complex documents fairly simple. Used Sax Filters when trying to map XUL to PHP-GTK, XUL effectively being a template syntax.

    Harry Fuecks - 7th July 2003 08:48 - #

  6. I have to agree here with Manuzhai. From working on a CMS that uses id's for adding files to pages (such as PDF's). This requires the end user to know the id of the file. You won't believe how easy this is to get wrong for an end user. (I've not worked out a better solution, though.) Also this is pretty meaningless in terms of semantics. What happens when a newer version of the file is uploaded? Does the new file get the old key? Does the user have to update all the primary keys to the new one? The user has to look up in a separate place for the image id?

    I think it's wise to abstract this away somehow. Database id's in the HTML template is not a good thing! I think that XSTL is the way to do this, although I've not really looked at it in detail.

    Swannie - 7th July 2003 09:47 - #

  7. I have been researching this topic recently. Here are some interesting links I would like to share:

    Creating Truly Skinnable Web Sites

    Custom Tag Libraries with XSLT

    Combining Markup using XML, XSLT and the MVC Design Pattern

    Style-free XSLT Style Sheets

    PerlTags

    XMLTemplate (Python)

    Template Languages in XSLT

    Enforcing Model-View Separation in Template Engines

    I am working on a PHP implementation of the "Designer Tags with XSLT" article trying to make the tags more generic than the example.

    Thanks,

    JT

    jtimm@iml.cc

    John Timm - 10th December 2003 04:55 - #

  8. One other possibility to consider (at least in PHP) is to take advantage of the output buffering functionality. For example:

    <?php function callback($buffer) { $xh = xslt_create(); xslt_set_encoding($xh, "ISO-8859-1"); xslt_set_base($xh, "file://" . getcwd() . "/"); $stylesheet = $_GET['stylesheet']; if (file_exists($stylesheet)) { $args = array( "/_xml" => $buffer ); $result = xslt_process($xh, "arg:/_xml", $stylesheet, NULL, $args); } return $result; } ob_start("callback"); // output xml declaration echo '<?xml version="1.0" encoding="ISO-8859-1"?>'; // output rest of XML document here (perhaps generated from database result). ob_end_flush(); ?>

    Basically, the generation and consumption/transformation of XML is all neatly managed here (sorry the code is messed up). Obviously implementing the appropriate XSL stylesheet is another thing.

    Regards

    JT

    jtimm@iml.cc

    John Timm - 10th December 2003 07:17 - #

Comments are closed.

Previously hosted at http://simon.incutio.com/archive/2003/07/04/customXML

A django site