Prototype 3
Prototype 3 basically a test of how good XSLT is at building a website (screenshot) which has navigation, list of news, info boxes, meta tags, breadcrumbs navigation. The core CMS Engine in also extended in 3 ways.
- A categories.xml defines the structure (categories) of the website
- Ability to list images
- A settings.xml allows a webmaster to define any simple text settings like a site’s name, author etc.
Download prototype3.zip.
/categories.xml
I wanted a way to formalize the structure of the website. An XML Structure file is the obvious way to define a hierachical structure of category names with associated “main pages”. That’s basically what I did:
<?xml version="1.0" encoding="UTF-8"?>
<categories>
<category name="Home" page="index">
<category name="News" page="news">
<category name="Local" page="news.local"></category>
<category name="International" page="news.int"></category>
</category>
<category name="Views" page="views"></category>
<category name="Gallery" page="gallery">
<category name="Rossi" page="gallery.rossi"></category>
<category name="All" page="gallery.all"></category>
</category>
<category name="Links" page="links"></category>
</category>
</categories>
This allows us to create XSLT Functions or Templates which we can call to give us a navigation. The template for a horizontal navigation bar looks (in essence) like this:
/design/subtemplates/navi.xsl
<xsl:template name="navibar">
<xsl:param name="category">Home</xsl:param>
<table class="navi">
<tr>
<xsl:for-each select="/site/categories//category[@name=$category]/*">
<xsl:call-template name="naviitem"/>
</xsl:for-each>
</tr>
</table>
</xsl:template>
It is then called from any page template using the following syntax:
/design/templates/page/simple.xsl
.
.
<xsl:include href="../subtemplates/navi.xsl"/>
<xsl:call-template name="navibar">
<xsl:with-param name="category" select="’Home’"/>
</xsl:call-template>
.
.
One could argue that this is a propietary syntax but it’s not really. The syntax can be changed at any time by the webmaster by changing the template definition in navi.xsl. This is not something that is part of the CMS other than as a bundled example.
Settings
Any template can use site-wide settings or texts by simply including a reference to the /site/settings element. This is a simple XML file with all tags defined freely by the webmaster:
/settings.xml
<?xml version="1.0" encoding="UTF-8"?>
<settings>
<site>
<name>Demo CMS Site</name>
<author>Jack Parker</author>
</site>
<option>My Option Here</option>
</settings>
So we can include the site’s author’s name in any template using XSLT:
/design/templates/page/simple.xsl
<meta name="author" content="{/site/settings/site/author}"/>
One could of course “misuse” this feature to define global styles or colors which can be changed centrally but that’s really the purpose of /design/styles/style.css.
Page Lists
Say we want to list some news articles on our news page with the newest first. We need a template which looks something like this:
/design/templates/subtemplates/lists.xsl
<xsl:template name="pagelist">
<xsl:param name="category"/>
<xsl:param name="sort"/>
<xsl:param name="order" select="’descending’"/>
<xsl:variable name="child_categories" select="/site/categories//category[@name=$category]/descendant-or-self::category"/>
<table class="pagelist">
<xsl:for-each select="/site/pages/page">
<xsl:sort select="*[name()=$sort]|@*[concat(’@',name())=$sort]" order="{$order}"/>
<xsl:variable name="current_page" select="."/>
<xsl:for-each select="$child_categories">
<xsl:variable name="child_category" select="@name"/>
<xsl:if test="$current_page/descendant::category/@name=$child_category">
<xsl:call-template name="pagelistitem">
<xsl:with-param name="page_node" select="$current_page"/>
</xsl:call-template>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</table>
</xsl:template>
And we call the following in our page:
<pagelist category="News" sort="pubDate" order="descending"/>
Of course this will also include our main news.htm page because it is also in the “News” category. To exclude this we need an if statement:
<xsl:if test="$current_page/@id!=/site/categories//category[@name=$child_category]/@page">
As you can see, the XPath gets a little hairy at times.
Link Lists
I also tried out some simple link lists in infoboxes on the right.

This is called in the page using a similar tag to the <pagelist>:
<linklist category="Links"/>
The template is almost identical to the one above but calls a different template to display individual items.
<xsl:template name="linklistitem">
<tr>
<td>
<a href="{concat(@id, ‘.htm’)}"><xsl:value-of select="title"/></a>
</td>
</tr>
</xsl:template>
<xsl:call-template name="linklistitem"/>
Architecture

Demo Site

Nice idea dude, i’ve been thinking about this one as well, but if you want to maintain it like a real CMS then it’s impossible using only XML and XSLT… You’ll always need something that creates your content dynamically.
Comment by Tom Luigjes — March 19, 2007 @ 8:55 pm