[Part 2] Assets, Atom Feeds, and AspectXML - The Triple Threat of Web Development?

by M. David Peterson

Related link: http://www.aspectxml.org



[UPDATE: 2005.09.07 05:32 p.m. MST]

I have gone back through this post and deleted all the existing "[UPDATE: ...]" entries such that this post can simply flow from beginning to end. I still need to finish off the explanation of the weaving process and then follow-up with the next entry in this series, that of bringing atom feeds together with the concept of site assets that are woven into the result output using the AOP approach used in the AspectXML project. I plan to finish this post off and then start work on the next post, publishing it tomorrow as one complete tutorial instead of the bits and pieces here and there that this post became. Please keep an eye out for [Part 3] Assets, Atom Feeds, and AspectXML - The Triple Threat of Web Development? around this same time tomorrow.



[ORIGINAL POST]

[A Quick Note: Saxon 6.5.4 was used to transform the files in this post. When we move to a true AspectXML implementation we will be using Saxon 8.5.1, and some changes will need to be made to our element naming practices to keep within the guidelines of the current XSLT 2.0 Working Draft specification. At the moment this is all conceptual, but when we move into the real-world implementation next week our element naming method will need to change.]

In developing this post I realized there needs to be a separation of concepts; The first concept covers the idea of weaving together separate data, layout, and layout definition files into a final output. Once this concept is understood is then much easier to understand how implementing AOP-based concepts can take things to the next level, bringing incredible power with very little additional code with each new project.

To start off lets dive straight into some code: [NOTE: I have zipped up the code files and made them available at http://www.aspectxml.org/downloads/dataWeave.zip]

File One: page.xml


<page>
<layout>
<template name="master"/>
<output type="table"/>
</layout>
<content>
<header>This is the header</header>
<left_navigation>This is the left navigation</left_navigation>
<content>This is the main content area</content>
<footer>This is the footer</footer>
</content>
</page>



Explanation of File One: page.xml

In a nutshell, page.xml represents a single page within any given website which informs our transformation file what template to use during the transformation process, what type markup should be output, and then the content of each section, using the name of the element to match against the 'source' attribute of the 'row' or 'data' elements contained within the template specified.

The true goal of page.xml is to be as completely content-centric as possible, leaving the details of things like size, color, etc... to the chosen template. By separating these specific details we can, in essence, build on top of a system that is common within our development workplace where one department, usually marketing, can focus on the content, specify what type of format that content should be presented in, and where each specific piece of content should go within a page. By giving ownership of this file to the marketing department (or whichever department happens to own the content for your given website(s)) the art department, and the development department can focus on their own core agenda's without concern as to what the content will be or how its going to be integrated into the system once the content is complete, approved, and ready to be merged.

Actually, looking at this, maybe a better usage of the output/@type attribute would be 'web', or 'print' or something to that effect. But that takes all of two changes, one on page.xml, and one on outputDefinition.xml as you will see below. In reality the names really don't matter... actually, a better way to say that is names actually do matter quite a bit; but while one word or phrase might work really well for you and your marketing folks, the same may not be true within another company that just so happens to be based in Bangladesh. As such, keeping this flexible was an important consideration in its design.


File Two: layoutDefinition.xml


<templates>
<template name="master">
<layout>
<object>
<row>
<column>
<row source="header"/>
<row>
<column x="175px" y="auto">
<data source="left_navigation"/>
</column>
<column x="600px" y="auto">
<data source="content"/>
</column>
</row>
<row source="footer"/>
</column>
</row>
</object>
</layout>
</template>
</templates>



Explanation of File Two: layoutDefinition.xml

Here's where the art department comes into play. It is very common within the systems we have in place for the art department to have very specific needs in regards to size, shape, color, etc... And for good reason. Their job is to make things look as good as they possibly can, and they need the type of control given to them to allow them to make these specifications without the need to know the various markup languages as well.

In today's world HTML and CSS are fairly well known within the art department folks. But as we move towards a world where web sites become more application, or speaking in more web-centric terms, weblication specific, this is not always going to be the case in regards to their knowledge of markup languages such as XUL, XAML, in some ways SVG (although vector graphics are something the art folks probably have a better understanding of than us hacker folks). And when it comes to binding together the various pieces of a weblication through various code-behind and other binding mechanisms the separation gap is only going to increase.

As you can see I chose to use a standard 'column' 'row' layout architecture, with a 'data' element thrown in to specify when something is data specific instead of layout specific. Keep in mind two things: This was a quick "proof of concept" throw together, and: While most people can easily understand the concepts of columns and rows I am not totally convinced that this is the best overall approach as it doesn't allow for a very rich UI-language similar to that in which we find with XHTML, XAML, XUL, and SVG. While I recognize that requiring the art department to learn an entire UI markup language goes against the entire purpose behind the separation of layoutDefinition.xml and outputDefinition.xml, I do believe there can exist a happy medium where the ability to get a little more specific as to what goes where and what it should look like can still exist alongside a simple, easy to understand UI language that allows limitless expression without the requirement to become a UI-markup hacking guru. In fact through the recent (yesterday as a matter of fact) influence and suggestion of both Russ and Sylvain, followed up with positive comments to the affirmative from Don, Uche, and Kurt I have decided to revitalize my WWULF project (World Wide Ubiquarian Lingua Franca) part of which is focused on developing this exact UI language that can in turn be transformed into any mainstream markup language such as XHTML/CSS, XUL, XUL/SVG, SVG/CSS, and XAML, all dependent on the client/device making the request and just what that client/device has the capacity to render and implement in regards to client-side functionality.

While I had every intention to pick this project back up at some point in the not to distant future, with the current onslaught of UI-markup languages coming at us from every direction, coupled with the somewhat "Graphic Dev Tool" requirement of SVG, now seems like the perfect time to put some effort into this project. Expect to hear more about this in the not to distant future.


File Three: outputDefinition.xml


<output>
<definition type="table">
<element name="object">
<translation value="table"/>
<attributes>
<attribute name="x" value="width"/>
<attribute name="y" value="height"/>
</attributes>
</element>
<element name="column">
<translation value="td"/>
<attributes>
<attribute name="x" value="width"/>
<attribute name="y" value="height"/>
</attributes>
</element>
<element name="row">
<translation value="tr"/>
<attributes>
<attribute name="x" value="width"/>
<attribute name="y" value="height"/>
</attributes>
</element>
<element name="data">
<translation value="p"/>
</element>
</definition>
<definition type="div">
<element name="object">
<translation value="div"/>
<attributes>
<attribute name="x" value="width"/>
<attribute name="y" value="height"/>
</attributes>
</element>
<element name="column">
<translation value="div"/>
<attributes>
<attribute name="x" value="width"/>
<attribute name="y" value="height"/>
</attributes>
</element>
<element name="row">
<translation value="div"/>
<attributes>
<attribute name="x" value="width"/>
<attribute name="y" value="height"/>
</attributes>
</element>
</definition>
</output>




Explanation of File Three: outputDefinition.xml

In regards to the outputDefinition.xml file let me first state this is a very simple implementation meant only to showcase the general ideas behind such a file, what it contains, and why. This particular file structure is where we hackers come into play. This is our playground, so to speak, as this is where we take the layoutDefinition.xml file that contains the various template definitions available to the marketing folks and, based on the desired output format (again, specified by the marketing folks) match the elements contained in the layoutDefinition.xml file to there proper translation for the various possible output formats.

As mentioned in the last paragraph of the page.xml file, the names I chose for definition/@type really should be more specific to the output device or device platform (e.g. device=PC platform=WindowsXP/Firefox), or, at very least a focus placed on web, print, etc... But while using such specifications for CSS files embedded within the head tag of our html files and labeled alternative can work and work well (when desirous to display the content in a format more specific to the specified alternative format), this is because the device/platform has already been specified/accounted for and the web or print declaration for alternative CSS stylesheets is a way of further specifying the layout, colors, font-size, etc... when the end user is desirous to print a web page in a more printer friendly format, or view it on something other than your standard VGA 1024x768 monitor, which at the moment, I believe, happens to be the most common resolution in use.

This of course is way off topic. Focusing more on the file itself you will notice the output element contains two definition child elements, with the aformentioned type attribute. Below this you will notice the numerous 'element' children with a value attribute that is used to compare against the current element in focus when processing the layoutDefinition.xml file. As I am looking at this I am realizing that the 'translation' child element is really unnecessary, as I could have just as easily made the translation element an attribute of its 'element' parent, its value set to what is now the value of the attribute 'value' that is currently part of the translation 'element'(way to confusing of a sentence, reason enough to fix this problem. ;)

But in regards to understanding the weaving process, this is really a moot point, especially given the fact that all of this will be changing fairly drastically when we bring AspectXML into the picture. So, for now, please disregard the obvious bad usage format. While its definitely still capable of showcasing the weaving process my apologies for the its confusing nature.

The portion of this file to truly take note of is the name attribute of the 'element' node and this attributes value. You will notice the 'row', 'column', and 'data' values contained in this attribute, the same element names we find in our layoutDefinition.xml file. It should be fairly obvious that our stylesheet uses the value of the name attribute to compare to the name() of the current element being processed within the layoutDefinition.xml file, to then look-up the proper translation for the output.

You will also notice the attributes/attribute elements contained below the translation element. It will become more obvious when we walk through the transformation file how these come into play, but in regards to the attribute names and values contained within the 'attribute' elements, as already mentioned, this is really how I should have set up the 'element' node for translation, using the 'name' attribute to match against, and the 'value' attribute as what it should be translated to. But, again, this is more conceptual than actual implementation, so hopefully you can forgive me for my obvious oversight of the way things should have been.


File Four: dateWeave.xsl


<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:variable name="output" select="/page/layout/output/@type"/>
<xsl:variable name="layoutDef" select="document('layoutDefinition.xml')"/>
<xsl:variable name="outputDef" select="document('outputDefinition.xml')/output/definition[@type = $output]"/>
<xsl:variable name="template" select="/page/layout/template/@name"/>
<xsl:variable name="content" select="/page/content"/>

<xsl:strip-space elements="*"/>

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

<xsl:template match="/">
<xsl:apply-templates select="$layoutDef/templates/template[@name = $template]/layout/*"/>
</xsl:template>

<xsl:template match="*">
<xsl:variable name="name" select="name()"/>
<xsl:variable name="source" select="@source"/>
<xsl:variable name="content" select="$content/*[name() = $source]"/>
<xsl:variable name="outputDef" select="$outputDef/element[@name = $name]"/>
<xsl:element name="{$outputDef/translation/@value}">
<xsl:apply-templates select="@*[not(name() = 'source')]" mode="attMatch">
<xsl:with-param name="attributes" select="$outputDef/attributes"/>
</xsl:apply-templates>
<xsl:if test="$source"><xsl:value-of select="$content"/></xsl:if>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>

<xsl:template match="@*" mode="attMatch">
<xsl:param name="attributes"/>
<xsl:variable name="currentAttName" select="name()"/>
<xsl:variable name="translatedAttName" select="$attributes/attribute[@name = $currentAttName]/@value"/>
<xsl:attribute name="{$translatedAttName}"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>

</xsl:stylesheet>



Before we get in to the how, lets look at what happens when you apply page.xml to dataWeave.xsl with the output type set to 'table':



<?xml version="1.0" encoding="UTF-8"?>
<table>
<tr>
<td>
<tr>This is the header</tr>
<tr>
<td width="175px" height="auto">
<p>This is the left navigation</p>
</td>
<td width="600px" height="auto">
<p>This is the main content area</p>
</td>
</tr>
<tr>This is the footer</tr>
</td>
</tr>
</table>



So what just happened? To understand this we will need to walk through the transformation file step by step.

[IN PROGRESS]

---
[EXTENSION TO POST]

First the file updates:

page.xml


<page xmlns:join="http://aspectxml.org/atom/join">
<layout>
<template name="master"/>
<output type="table"/>
</layout>
<content>
<header>This is the header</header>
<left_navigation>This is the left navigation</left_navigation>
<content>This is the main content area.
<join:atom src="http://www.xsltblog.com/atom.xml" type="dropdown">This is a joined atom feed</join:atom>
</content>
<footer>This is the footer</footer>
</content>
</page>



when transformed with:

dataWeave.xsl


<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:join="http://aspectxml.org/atom/join"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:dc="http://purl.org/dc/elements/1.1/"
version="1.0"
exclude-result-prefixes="join atom dc">

<xsl:variable name="output" select="/page/layout/output/@type"/>
<xsl:variable name="layoutDef" select="document('layoutDefinition.xml')"/>
<xsl:variable name="outputDef" select="document('outputDefinition.xml')/output/definition[@type = $output]"/>
<xsl:variable name="template" select="/page/layout/template/@name"/>
<xsl:variable name="content" select="/page/content"/>

<xsl:strip-space elements="*"/>

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

<xsl:template match="/">
<xsl:apply-templates select="$layoutDef/templates/template[@name = $template]/layout/*"/>
</xsl:template>

<xsl:template match="*">
<xsl:variable name="name" select="name()"/>
<xsl:variable name="source" select="@source"/>
<xsl:variable name="content" select="$content/*[name() = $source]"/>
<xsl:variable name="outputDef" select="$outputDef/element[@name = $name]"/>
<xsl:element name="{$outputDef/translation/@value}">
<xsl:apply-templates select="@*[not(name() = 'source')]" mode="attMatch">
<xsl:with-param name="attributes" select="$outputDef/attributes"/>
</xsl:apply-templates>
<xsl:if test="$source"><xsl:apply-templates select="$content"/></xsl:if>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>

<xsl:template match="@*" mode="attMatch">
<xsl:param name="attributes"/>
<xsl:variable name="currentAttName" select="name()"/>
<xsl:variable name="translatedAttName" select="$attributes/attribute[@name = $currentAttName]/@value"/>
<xsl:attribute name="{$translatedAttName}"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>

<xsl:template match="text()">
<xsl:value-of select="."/>
</xsl:template>

<xsl:template match="join:atom[@type = 'dropdown']">
<xsl:variable name="textValue" select="."/>
<xsl:apply-templates select="document(@src)" mode="dropdown">
<xsl:with-param name="textValue" select="$textValue"/>
</xsl:apply-templates>
</xsl:template>

<xsl:template match="atom:feed" mode="dropdown">
<xsl:param name="textValue"/>
<xsl:value-of select="$textValue"/>
<a onclick="if (getElementById('childMenu').display = 'none' getElementById('childMenu').display = 'block';
else getElementById('childMenu').display = 'none';
return true;">
<xsl:value-of select="$textValue"/>
<ul id="childMenu" style="display:none">
<xsl:apply-templates select="atom:entry"/>
</ul>
</a>
</xsl:template>

<xsl:template match="atom:entry">
<li><a href="{atom:link/@href}"><xsl:value-of select="atom:title"/></a></li>
</xsl:template>
</xsl:stylesheet>


will result in:


<?xml version="1.0" encoding="utf-8"?>
<table>
<tr>
<td>
<tr>This is the header</tr>
<tr>
<td width="175px" height="auto">
<p>This is the left navigation</p>
</td>
<td width="600px" height="auto">
<p>This is the main content area.
<a onclick="if (getElementById('childMenu').display = 'none' getElementById('childMenu').display = 'block'; else getElementById('childMenu').display = 'none'; return true;">
<ul id="childMenu" style="display:none">
<li>
<a href="http://www.xsltblog.com/archives/2005/08/_part_2_assets_1.html"> [Part 2] Assets, Atom Feeds, and AspectXML - The Triple Threat of Web Development?</a>
</li>

<li>
<a href="http://www.xsltblog.com/archives/2005/08/past_present_an.html">Past, Present, and Future of Mozilla SVG</a>
</li>
<li>
<a href="http://www.xsltblog.com/archives/2005/08/siteredesign_in.html">Site-Redesign in Mid-Stream... Please excuse the non functionality and, even more so, the currently 'ugliness'... I promise it will get better :)</a>
</li>
<li>
<a href="http://www.xsltblog.com/archives/2005/08/gizmo_project_y.html">Gizmo Project: Yet Another Skype Wanna-Be? First Take: This Is What Skype Should 'Wanna-Be'</a>
</li>
<li>
<a href="http://www.xsltblog.com/archives/2005/08/ann_saxon_851_i.html">[ANN] Saxon 8.5.1 is available [via saxon-help]</a>
</li>
<li>
<a href="http://www.xsltblog.com/archives/2005/08/this_belongs_in_1.html">This belongs in 'Code of the Day' but in reality should be *AT LEAST* Code of the Month, if not Year</a>
</li>
<li>
<a href="http://www.xsltblog.com/archives/2005/08/c_30_and_the_fu_1.html">C# 3.0 and the future of the CLI</a>
</li>
<li>
<a href="http://www.xsltblog.com/archives/2005/08/i_love_it_when.html">I Love it When Opportunity Knocks; Especially When It Knocks On the Door of the House You Moved Into A Month or Two Back, Giving You Just Enough Time to Unpack, Get Settled, and Have The Sara Lee Ready and Waiting</a>
</li>
<li>
<a href="http://www.xsltblog.com/archives/2005/08/via_my_first_or_1.html">via My First O'Reilly Blog Post | Assets, Atom Feeds, and AspectXML - The Triple Threat of Web Development?</a>
</li>
<li>
<a href="http://www.xsltblog.com/archives/2005/08/interesting_com_1.html">Interesting Comments from DonXML Regarding Acrylic</a>
</li>
<li>
<a href="http://www.xsltblog.com/archives/2005/08/a_very_light_bl.html">A very light blogging week</a>
</li>
<li>
<a href="http://www.xsltblog.com/archives/2005/08/via_bill_de_har.html">via Bill de hÓra | One-Click HTML?</a>
</li>
<li>
<a href="http://www.xsltblog.com/archives/2005/08/via_ebay_i_now.html">via EBay | I Now Know What I Am Going To Get Edd Dumbill For Christmas [Link Source: Engadget]</a>
</li>
<li>
<a href="http://www.xsltblog.com/archives/2005/08/via_tim_bray_in.html">via Tim Bray | In the Works Tim... No, You Are Not the Only One Who has Connected the Dots</a>
</li>
<li>
<a href="http://www.xsltblog.com/archives/2005/08/im_not_sure_wha.html">I'm not sure what it may have been that Kurt stated in his Keynote at SVG 2005, but apparently someone is upset enough to have invoked a DOS attack on the transcript he posted earlier</a>
</li>
</ul>
</a>
</p>
</td>
</tr>
<tr>This is the footer</tr>
</td>
</tr>
</table>


We actually need to perform some CSS magic using an external CSS file to make the above unordered list appear as a menu, as opposed a standard unordered list. But this is less important at the moment than is understanding how we got to this point in the first place. So I plan to focus on this part of the tutorial first at which point we can work on turning the above into something much more usable on the web.

[IN PROGRESS]


Are there any particular to the above code that seem strange or difficult to understand without having a complete step-by-step walkthrough of the transformation file? If so, please post them as comments and I will be sure to put special emphasis as I continue forward with this post throughout this evening.