Reusable XSLT stylesheets

This next statement means something to someone: This will only work with XSLT 2.0 as variables in predicates contained in match expressions are not allowed in XSLT 1.0.
 
I was thinking about an XML solution that could be reusable (and listening to some Phillip Glass) when I came up with an idea for reusing the templates in an XSLT stylesheet. Normally a template in a stylesheet would be written in this way:
 
<xsl:template match="p">
...
</xsl:template>
 
This would, obviously, tell the stylesheet to process all of the "p" elements in the document in a particular way. Now, the problem with this approach is that the template is now rendered useless for an XML structure that would have a "para" element designating a paragraph rather than a "p" element.
 
A better way would be to define a series of variables that would specify the following:
  • the top-level element in the document to be transformed
  • the names of the elements that are to be transformed in the document
  • the names of the elements that are in the resulting output document

So, something like this is needed at the outset:

<xsl:variable name="fromTopLevelElement">Metadata</xsl:variable>
<xsl:variable name="toTopLevelElement">Files</xsl:variable>
<xsl:variable name="fromElementP">File</xsl:variable>
<xsl:variable name="toElementP">p</xsl:variable>

These variables are best expressed in a seperate XSLT document and imported into the main stylesheet using an xsl:import element.

Now, the templates themselves are a tad cumbersome, but the beauty of lies in the fact that there are no element names in the templates...just a bunch of calls to various variables defined elsewhere:

<xsl:template match="//*[name()=$fromTopLevelElement]">
 <xsl:element name="{$toTopLevelElement}">
  <xsl:apply-templates/>
 </xsl:element>
</xsl:template>

<xsl:template match="*[name()=$fromElementP]">
 <xsl:call-template name="paragraph">
  <xsl:with-param name="elementName">
   <xsl:value-of select="$toElementP"/>
  </xsl:with-param>
 </xsl:call-template>
</xsl:template>

<xsl:template name="paragraph">
     <xsl:param name="elementName"/>
     <xsl:element name="{$elementName}">
  <xsl:text>This is paragraph </xsl:text><xsl:value-of select="position()"/>
     </xsl:element>
</xsl:template>

There are a couple of things that I am not too thrilled about (i.e. the // in the match statements) so I need to clean those up a bit, but overall it gets the job done.
 
Generally, when working with structured documents expressed in XML and HTML, there are paragraphs that need to be generated. Of course these paragraph elements can be named anything whatsoever. If a truly modular XSLT stylesheet is needed then the templates that generate these tags can be stored in a stylesheet that is reusable and then imported from a stylesheet that will define the tag names.
 
To make it even less complicated (from a user standpoint) there can be a third file (an XML file) that can be used to define the names of the tags and then referenced from the stylesheet that is calling the templates or from the the one that is being imported into the main stylesheet. I think this is the approach I would take as it is the most user-friendly one I can think of.


Comments

Popular posts from this blog

Nothing will stand in the way of the Word

tightvnc keyboard mapping problem in Ubuntu 9.04

The Boys of Summer