XML Request Transformations - XSLTpages

XML Request Transforms (or XSLTpages) is new syntax for building web applications.

XRT is not another framework... it is a new way of describing the resources available in your webapp. You can think of it like an Apache virtual host config file, or a Java(TM) Servlet web.xml file.

About XRT

The idea behind XRT is that by creating a new syntax for describing web applications we can build RESTfull webapps in a very agile way. XRT can allow you to dispatch resource handling based on resource paths but also on other things or combinations of things:

Example

Here's an example XRT document that describes a simple web based bookmark application:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet  version="1.0"
                 xmlns:http="http://www.tapsellferrier.co.uk/namespace/xslt_http_ns"
                 xmlns:python="http://www.tapsellferrier.co.uk/xslt-dynamic-function-languages/python"
                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xsl:exclude-result-prefixes="python">

    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />

    <xsl:include href="bookmark-created.xslt"/>
    <xsl:include href="bookmark-list.xslt"/>

    <xsl:template match="/">
        <xsl:apply-templates select="/http:request"/>
    </xsl:template>

    <!-- List all the records -->
    <xsl:template match="http:request[http:method = 'GET']">
        <xsl:variable name="bookmarks" select="python:bookmark.listall()"/>
        <xsl:apply-templates select="$bookmarks">
            <xsl:with-param name="http" select="/http:request"/>
        </xsl:apply-templates>
    </xsl:template>

    <!-- Create new records -->
    <xsl:template match="http:request[http:method = 'POST']">
        <xsl:variable name="toadd" select="//http:parameter[http:name = 'href']/http:value"/>
        <xsl:variable name="updated" select="python:bookmark.add(string($toadd))"/>
        
        <xsl:apply-templates select="$updated" mode="created">
            <xsl:with-param name="statuscode">201</xsl:with-param>
            <xsl:with-param name="toadd" select="$toadd"/>
            <xsl:with-param name="request" select="/http:request"/>
        </xsl:apply-templates>
    </xsl:template>

</xsl:stylesheet>
                

XRT uses the W3C's XSLT language to specify the web application. XSLT is a very powerfull functional language with facilities for talking to code written in imperative languages.

Example imperative code

An example of XRT calling an imperative language can be seen in the above XRT in the second xsl:template match. The python method bookmark.listall is called. Here's the text of that method:

def listall():
    if not os.path.exists(filename):
        return

    f = open(filename, "r+")
    for bookmark in f:
        yield bookmark
    f.close()
    return
                

XRT takes the output of this method and transforms it into XML and then passes it back to the XSLT script. In this way user's do not need to conform to any particular framework rules.

XRT and Agile development

XRT doesn't need to call imperative languages of course; with XSLT it's trivial to import XML documents. So one very agile way to develop webapps is to:

Example include

Note that the above XRT isn't the whole story. You will notice that the xsl:include statements which are there to bring in further XRT. Here's the text of the bookmark-list.xslt file:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet  version="1.0" 
                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="items">
        <html>
            <head>
                <link rel="stylesheet" href="list.css" type="text/css"/>
            </head>
            <body>
                <h1>Bookmarks</h1>
                <xsl:choose>
                    <xsl:when test="not(item)">
                        <div>No bookmarks yet</div>
                    </xsl:when>
                    <xsl:otherwise>
                        <ul>
                            <xsl:for-each select="item">
                                <li><xsl:value-of select="."/></li>
                            </xsl:for-each>
                        </ul>
                    </xsl:otherwise>
                </xsl:choose>
                <form method="POST" action="/">
                    <fieldset>
                        <label>Title</label><input type="text" name="title" value=""/><br/>
                        <label>Href</label><input type="text" name="href" value=""/><br/>
                        <label>Keyword</label><input type="text" name="keyword" value=""/><br/>
                        <input type="submit" name="add" value="add"/>
                    </fieldset>
                </form>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>
                

This XRT is called when the first XRT applies templates to the python call.

Of course, it's not necessary to use includes, you could put the whole XRT into one file. But that would make it less readable.

Ongoing development

XRT is a work in progress. There are demonstrations that you can play with available in the CVS module.

At the moment you need Apache/mod_python to make XRT work and the only language that can be called is python. I hope to change that by reimplementing XRT in C. At that stage users will be able to call code in any language from XRT.

Can you help?

Yes, you probably can because XRT needs work in a number of areas:

If you want to help in anyway you probably need to check out the savannah project where XRT is hosted.


Fri Mar 10 23:19:52 UTC 2006Nic Ferrier