Component-Based Page Layouts
Printed newspapers and magazines are created by a team of content authors, editors, and people whose task it is to aggregate and lay out the content in a coherent and pleasing way.
Let's take the example of a magazine and simplify the workflow a little: authors deliver their content to the editor, who (obviously) edits the content. Subsequently, the content is ready to be positioned in the magazine's page layout. Content is not necessarily limited to text, but may also contain illustrations.
An electronic magazine is also an assemblage of text and image content. Moreover, other kinds of components can be included in a web page, including interactive components like applets, plug-ins, or ActiveX objects. Each component may be produced by a different author.
Let's examine how the assembly of such a site can be done with XHTML. XHTML is part of the next generation of publishing languages for the Web. One main advantage of XHTML is that, in contrast to its predecessor HTML, it can be extended with new elements. This article will demonstrate how, by using new elements and XSLT transformation sheets, you can aggregate content coming from external documents into a single XHTML document.
A Basic XHTML Page Layout
Well-structured web sites have an integrated look and feel. If each individual component author created his or her own vision of the site, it would end up very disorganized and visually confusing.
Looking at the structure of most web sites, we notice that they have a similar visual layout. At the top, a header; at the bottom, a footer; at the left, a navigation area or table of contents; and, at the right, the content. This visual structure is illustrated in figure 1.
|Figure 1: Typical site layout|
In the XHTML world, one way to create a layout like that shown in Figure 1 is to use either a frameset or a table. (In order to support the widest range of browsers, we must use both in the same page.) In XHTML, as well as in HTML 4.01, the
<frameset> element should be used in tandem with the
<noframe> element's content is used by browsers that do not support frames. This element can contain a table, and the table's cells can contain the components of the frameset. "But wait a minute," you ask, "How can I still use the components as
separate documents in the
<noframe> section?" Indeed, a good question.
Expand XHTML with a component Element
We know it is possible to include components as separate documents in a
<frameset> element, but not in the
<noframe> section. Let's then include in the
<noframe> section elements of our own invention named
<xscript:component>, and use a bit of XSLT
magic to obtain the same effect we get with the
The key to XHTML is the letter X, which indicates that it is eXtensible. This means we can add our own elements when we need to. So, to obtain the same layout in the
<noframe> section that we get in the
<frameset> section, we add to our XHTML a new element that is used to include external document content in cells of the table.
Inheriting Attributes From xlink:simple
The new element,
component, is basically a link to a resource. The latest XLink working draft makes it possible for an element to inherit the linking behavior from one of the XLink elements. XLink proposes two kind of links:
- a one-to-one link
- a one-to-many link
Since we need our
<xstyle:component> element to link to a single resource, we then use the
xlink:type="simple" attribute that will transform our element into a link. Several other attributes from the XLink language (like
xlink:href, xlink:title, xlink:show) are also useful, so let's integrate them into our element's list of attributes.
Using XSLT as an XLink Interpreter
An important thing to mention here is that we are using the XSLT
engine as an XLink interpreter. More specifically, it interprets the link
behavior indicated by the
xlink:show attribute. When this is set to the
"embed" value, the content of the linked resource is included in a table cell.
Otherwise an error message is included.
xlink attributes we add
xstyle attributes to indicate the component's MIME type, its height, its width, and the role it plays in the layout. The
xstyle prefix denotes that the attributes are of our invention; we will
associate the prefix
xstyle with the namespace URI of our choice (in this case http://www.talva.com/2000/xstyle). We do not use the
xlink:role attribute because we want to indicate the semantic meaning of the element in a
layout context, not in a linkage context. So, our element is a link to an external resource, and its basic properties are described by the following attributes:
xlink:type = "simple"
xlink:href = "URI"
xlink:title = "string"
xlink:show = "embed"
xstyle:type = "MIME type, e.g., image/svg or text/xhtml"
xstyle:height = "numerical value or percentage"
xstyle:width = "numerical value or percentage"
xstyle:role = "header|footer|table-of-content|content"
For instance, the
<xstyle:component>, which links our web site template to the header component (in this case, a vector graphics SVG document), looks like this:
<xstyle:component xlink:type="simple" xlink:href="header.svg" xlink:title="Header Layout Object" xlink:show="embed" xstyle:type="image/svg" xstyle:height="100%" xstyle:width="100%" xstyle:role="header"/>
Our XSLT transformation sheet must interpret the
<xstyle:component> element by first looking for the
xlink:show attribute. If this is set to the
embed value, then the
xstyle:type attribute is used as a switch to select the appropriate behavior.
For instance, in our example XSLT transformation sheet, every component of type "image/svg" is converted into an
<embed> element, which can then be displayed in a web browser using the Adobe SVG plug-in (now freely available from Adobe's site).
In cases where the
xstyle:type attribute is set to "text/xhtm", the referred document's content is inserted in the table cell.
Examining the XSLT Transformation Sheet
The template performing the XLink interpretation is the one that matches the
<xsl:template match="xstyle:component"> <xsl:choose> <!-- we embed the component's content only if the xlink:show attribute is set to 'embed' --> <xsl:when test="contains(@xlink:show,'embed')"> <xsl:choose> <xsl:when test="contains(@xstyle:type,'image/svg')"> <embed type="image/svg"> <xsl:attribute name="src"> <xsl:value-of select="./@xlink:href"/> </xsl:attribute> <xsl:attribute name="height"> <xsl:value-of select="./@xstyle:height"/> </xsl:attribute> <xsl:attribute name="width"> <xsl:value-of select="./@xstyle:width"/> </xsl:attribute> </embed> </xsl:when> <xsl:when test="contains(@xstyle:type,'text/xhtm')"> <xsl:apply-templates select="document(@xlink:href)/html:html/html:body/*"/> </xsl:when> <!-- put here other xstyle formats identified by the xstyle:type attribute. the attribute's value is the component MIME type. For example, if the component is an SVG document, then its MIME type is "image/svg". --> </xsl:choose> </xsl:when> <xsl:otherwise> <!-- We include an error message in the output document if the intended behavior is not to embed the content --> <p>Error: the <xstyle:component> elements only support the xlink:show attribute set to the value "embed".</p> </xsl:otherwise> </xsl:choose> </xsl:template>
<xstyle:component> is matched by the template
xstyle:type is equal to "text/xhtm", then the external document's content is loaded, parsed, and the resultant node set included in the current node set. In our case, the external document content replaces the
<xstyle:component> element. Thus, each time an
<xstyle:component> element is encountered by the XSLT engine, it is replaced by the external document's content. This magic is accomplished with the
However, we do not want to include the entire external document's content
in each table cell. For example, the XHTML
<head> element has no place in a table! We only want to include the content of each external document
<body> element. This is accomplished by the following expression.
html prefix is associated with the namespace URI for XHTML, http://www.w3.org/1999/xhtml).
Now that we have extracted the right node set, we simply want to copy its content as a replacement for the
<xstyle:component> node. The following template does just that:
<xsl:template match="*|@*|text()"> <xsl:copy> <xsl:apply-templates select="*|@*|text()"/> </xsl:copy> </xsl:template>
Now, Let's Go to the Lab....
If you are tempted to do some exploration of your own, here is my proposal for this week's lab experiment.But first, to do this experiment, you'll need an XSLT engine that is as compliant as possible with the 1999 W3C XSLT Recommendation. I used James Clark's XT processor.
- Place the following documents in the same directory: toc.htm, content.htm, footer.htm, header.svg, template.htm, template.xsl.
- Go get the Adobe SVG Viewer; you'll need it to view the SVG drawing (and also for a future lab experiment...).
- Process the template.htm document with the template.xsl transformation sheet in order to replace all
<xstyle:component>elements with the appropriate content extracted from the external components (i.e., documents).
- Try it with your own components.
You can also simply look at the template document, the transformation sheet, and the resultant document. Because the template.htm document is an XHTML document, your browser should immediately interpret and render it. Use the "View Source" option to examine its source.