Tiles (XSL)

From LiteratePrograms

Jump to: navigation, search

This is about applying the idea of Apache.org Struts UI Tiles to XSL to create reusable view components.

Named templates are template subroutines. Theese will be our reusable tiles. We will use them to build html blocks with the current node children as items, and shape them with the desired structure.

Then we will build match templates for the data, one for each applicable tile as a different mode template.

And we will use it all to build a portal side column with boxes of different shape.

Contents

The tiles

We will define several named templates with block_class and item_class as parameters for later style with CSS.

Unordered list tile.

Here we will format current node children as items in a HTML UL list

  • @param block_class string optional The class attribute for the UL element
  • @param item_class string optional The class attribute for LI elements
<<tile_ulist.xsl>>=
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/1999/xhtml">
<xsl:template name="ulist">
	<xsl:param name="block_class"/>
	<xsl:param name="item_class"/>
	<xsl:element name="ul">
		<xsl:if test="$block_class">
			<xsl:attribute name="class">
                             <xsl:value-of select="string($block_class)" />
			</xsl:attribute>
		</xsl:if>
		<xsl:for-each select="*">
			<xsl:element name="li">
				<xsl:if test="$item_class">
					<xsl:attribute name="class">
                                             <xsl:value-of select="string($item_class)" />
                                        </xsl:attribute>
				</xsl:if>
				<xsl:value-of select="."/>
			</xsl:element>
		</xsl:for-each>
	</xsl:element>
</xsl:template>  
</xsl:stylesheet>

Paragraph sequence tile

Here we will format current node children as a sequence of paragraphs enclosed in a DIV block.

  • @param block_class string optional The class attribute for the DIV enclosing element
  • @param item_class string optional The class attribute for P elements
<<tile_para_seq.xsl>>=
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/1999/xhtml">
<xsl:template name="para_seq">
	<xsl:param name="block_class"/>
	<xsl:param name="item_class"/>
	<xsl:element name="div">
		<xsl:if test="$block_class">
			<xsl:attribute name="class">
                             <xsl:value-of select="string($block_class)" />
                        </xsl:attribute>
		</xsl:if>
		<xsl:for-each select="*">
			<xsl:element name="p">
				<xsl:if test="$item_class">
					<xsl:attribute name="class">
                                              <xsl:value-of select="string($item_class)" />
                                        </xsl:attribute>
				</xsl:if>
				<xsl:value-of select="."/>
			</xsl:element>
		</xsl:for-each>
	</xsl:element>
</xsl:template>  
</xsl:stylesheet>

Comma delimited sequence tile

Here we will format current node children as items in an inline comma-delimited sequence with items enclosed in HTML SPAN tags to assign them the class attribute.

  • @param block_class string optional The class attribute for the SPAN enclosing element
  • @param item_class string optional The class attribute for each item SPAN element
<<tile_comma_delim_seq.xsl>>=
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/1999/xhtml">
<xsl:template name="comma_delim_seq">
	<xsl:param name="block_class"/>
	<xsl:param name="item_class"/>
	<xsl:element name="span">
		<xsl:if test="$block_class">
			<xsl:attribute name="class">
                             <xsl:value-of select="string($block_class)" />
                        </xsl:attribute>
		</xsl:if>
		<xsl:for-each select="*">
			<xsl:element name="span">
				<xsl:if test="$item_class">
					<xsl:attribute name="class">
                                            <xsl:value-of select="string($item_class)" />
                                        </xsl:attribute>
				</xsl:if>
				<xsl:value-of select="."/>
			</xsl:element>
			<xsl:if test="not(position()=last())">
                             <xsl:text>, </xsl:text>
                        </xsl:if>
		</xsl:for-each>
	</xsl:element>
</xsl:template>  
</xsl:stylesheet>

The xml source data

Here we have layout description and data.

<<portal.xml>>=
<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/xsl" href="format.xsl"?>
<doc>
	<layout>
		<display-box box_name="my_categories" tile="para_seq"/>
		<display-box box_name="my_items" tile="ulist"/>
		<display-box box_name="my_likings" tile="comma_delim_seq"/>
	</layout>
	<data>
		<box>
			<name>my_items</name>
			<title>My Items</title>
			<items>
				<item1>First</item1>
				<item2>Second</item2>
				<item3>Third</item3>
			</items>
		</box>
		<box>
			<name>my_categories</name>
			<title>My Categories</title>
			<items>
				<item1>Categ1</item1>
				<item2>Categ2</item2>
				<item3>Categ3</item3>
			</items>
		</box>
		<box>
			<name>my_likings</name>
			<title>My Likings</title>
			<items>
				<item1>Country-side</item1>
				<item2>IT resources</item2>
				<item3>Sci-fi</item3>
			</items>
		</box>
	</data>
</doc>

The stylesheet

include tile stylesheets

<<include_tiles>>=
<xsl:include href="tile_comma_delim_seq.xsl"/>
<xsl:include href="tile_para_seq.xsl"/>
<xsl:include href="tile_ulist.xsl"/>

Mode templates for 'items'

Create templates for items element match with mode attribute.

<<modes_templates>>=
<xsl:template match="items" mode="ulist">
	<xsl:call-template name="ulist">
		<xsl:with-param name="block_class">cls_list_block</xsl:with-param>
		<xsl:with-param name="item_class">cls_list_item</xsl:with-param>
	</xsl:call-template>
</xsl:template>
<xsl:template match="items" mode="para_seq">
	<xsl:call-template name="para_seq">
		<xsl:with-param name="block_class">cls_para_block</xsl:with-param>
		<xsl:with-param name="item_class">cls_para_item</xsl:with-param>
	</xsl:call-template>
</xsl:template>
<xsl:template match="items" mode="comma_delim_seq">
    <div><p>
	<xsl:call-template name="comma_delim_seq">
		<xsl:with-param name="block_class">cls_comma_seq_block</xsl:with-param>
		<xsl:with-param name="item_class">cls_comma_seq_item</xsl:with-param>
	</xsl:call-template>
	</p></div>
</xsl:template>

'display-box' template with mode dispatching

Here we will display a one column table cell with a box within with data and shape specified in the display-box element attributes.

<<display_box_template>>=
<xsl:template match="display-box">
	<tr><td>
	<xsl:variable name="box_name"><xsl:value-of select="@box_name"/></xsl:variable>
	<xsl:variable name="tile"><xsl:value-of select="@tile"/></xsl:variable>
	<xsl:for-each select="/doc/data/box[name=$box_name]">
		<table class="cls_box_frame">
			<tr><td class="cls_box_title"><xsl:value-of select="title"/></td></tr>
			<tr><td>
				<xsl:choose>
				    <xsl:when test="$tile='para_seq'">
					<xsl:apply-templates select="items" mode="para_seq"/>
				    </xsl:when>
				    <xsl:when test="$tile='comma_delim_seq'">
					<xsl:apply-templates select="items" mode="comma_delim_seq"/>
				    </xsl:when>
				    <xsl:otherwise>
					<xsl:apply-templates select="items" mode="ulist"/>
				    </xsl:otherwise>
				</xsl:choose>
			</td></tr>
		</table>
	</xsl:for-each>
	</td></tr>
</xsl:template>

Start transforming from layout xml data

Apply templates to layout child elements.

<<format.xsl>>=
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/1999/xhtml">
  <xsl:output 
    method="html"
    encoding="iso-8859-1"
    indent="yes"
  />
include_tiles
modes_templates
display_box_template
<xsl:template match="/">
<html><head>
  <title>Page title</title>
  <style type="text/css">
        TABLE.cls_box_frame {border: outset medium; width: 100%}
	TD.cls_box_title {text-align: center; background-color: yellow; border: solid thin}
	LI.cls_list_item {color: red}
	P.cls_para_item {color: green}
	SPAN.cls_comma_seq_item {color: blue}
  </style>
</head>
<body>
	<table style="width: 130px; border: none">
	<xsl:apply-templates select="doc/layout/*" />
	</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

Testing

Open the file, or url if in web zone, with a web browser.

portal.xml

A column will appear with boxes of data and tile shapes specified on source display-box elements.

Download code
Views