views:

106

answers:

2

Hello everyone,

I was wondering if there is a good approach in XSLT stylesheet design pattern to separate common and specific data representation.

I was trying, but got very confused and lost. I would appreciate any advice, tips, hints where I can read up on how to better separate XSLT stylesheets. And also, would really appreciate help with the example below as it doesn't work =/ THANK YOU!

I need to create a variety of HTML docs with different looks that would reuse some of the data. For example date of a document, signature details (name, job title) and so on. Also, I'm using quite a lot of global variables (because XML isn't structured well and data reused throughout a doc).

What I was trying to do, is to move all the templates that would create a common HTML structure in one stylesheet and then all specific bits will be in their own stylesheet.

Something like the following:

Common templetes stylesheet "commonTemplates.xsl"

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- Variables Local -->
...

<xsl:output method="html" doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" 
    doctype-system="http://www.w3.org/TR/html4/loose.dtd" indent="yes" />

<xsl:template match="/Bookings">
    <html>
        <head>
            <!-- populated by a template in a specific stylesheet -->
            <title><xsl:call-template name="docTitle"/></title>
        </head>
        <body>
            <xsl:apply-templates />
        </body>
    </html>
</xsl:template>

<!-- general template for date -->
<xsl:template match="/Bookings/Booking" name="docDate">
  <p class="date"><xsl:value-of select="./@Date"/></p>
</xsl:template>

<!-- general template for signature -->
<xsl:template match="/Bookings/Booking/Users" name="signature">
    <xsl:param name="signatureLine" select="'Yours sincerely,'"/>
    <div id="signature">
        <p><xsl:value-of select="$signatureLine"/></p>
        <p class="details">
            <!-- populated by a template in a specific stylesheet -->
            <xsl:apply-templates select="." mode="signature"/>
        </p>
    </div>
</xsl:template>

<!-- dummy templates signatures otherwise it complains that there is no such template -->
<xsl:template name="docTitle"/>    
</xsl:stylesheet>

Specific templetes stylesheet:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<!-- Imports -->
<xsl:import href="commonTemplates.xsl"/>

<!-- BODY CONTENT OF HTML PAGE -->
<xsl:template match="/Bookings/Booking">
    <xsl:call-template name="docDate"/>
    <!-- document's content -->
    <div>
        <xsl:call-template name="content" />
    </div>
</xsl:template>


<xsl:template name="docTitle">
    <xsl:text>Here is the document title</xsl:text>
</xsl:template>

<!-- some content at the end of which signature should be inserted -->
<xsl:template name="content">
    <p>SOME CONTENT</p>        
    <xsl:apply-templates />
</xsl:template>

<!-- specific rule to insert appropriate data for signature -->
<xsl:template match="/Bookings/Booking/Users" mode="signature">
    <span class="name"><xsl:value-of select="./@Name"/></span>
    <span class="job"><xsl:value-of select="./@Title"/></span>
</xsl:template>
</xsl:stylesheet>

Unfortunately, the template for signature doesn't work and I can't figure out why :( It does for the docTitle though.

The results HTML looks like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&gt;
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title></title>
   </head>
   <body>      
      <p class="date">16 February 2010</p>
      <div id="secondDeposit">
         <p>SOME CONTENT</p>
         <!-- here I get lots of empty space -->
      </div>    
   </body>

I was wondering if such idea could be implemented in general and how to do it properly, obviously mine doesn't work.

Also, which approach will be better in this case: include or import stylesheet? I think with one of them I don't need to list all the variables again.

I would appreciate any help! Sorry for a long post and if it's not as clear.

Thank you!

+3  A: 

I use the following method:

Template File (/templates/Main.xslt)

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
  <xsl:output method="xml" encoding="utf-8" />
  <xsl:include href="../functions/General.xslt"/>
  <xsl:template match="/">
    <html xml:lang="en">
      <head>
      </head>
      <body>
         Template Content
         <xsl:call-template name="PageContent" />
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Functions File (/functions/General.xslt)

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <!-- Generic functions used in the site go in here -->
</xsl:stylesheet>

Page File (/default.xslt)

There will be a few of these to define different layouts within the template. This is the XSLT file you call when doing your transformation.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:import href="templates/Main.xslt" />
    <xsl:output method="xml" encoding="utf-8" />
    <xsl:template match="/">
        <xsl:apply-imports />
    </xsl:template>
    <!-- CONTENT -->
    <xsl:template name="PageContent">
      <!-- Put your specific page stuff here -->
    </xsl:template>
</xsl:stylesheet>
Josh
A: 

It is a recommended best practive to accumulate commonly used templates in stylesheet files that will be imported by specific XSLT applications. Collections of such useful xstylesheet files make useful libraries.

Of course, a stylesheet module that is imported often imports other stylesheet modules.

An example is the FXSL library for functional programming in XSLT. Do look into how XSLT applications (the example testxxx.xsl files) import the functionality they need.

Dimitre Novatchev
@Dimitre Novatchev, Thank for the link. I've tried to look into examples, but I got lost in them =/ Maybe, you know some articles or any reading for beginners?Many thanks!
DashaLuna
@Daria This is the link to an FXSL 1.x article (FXSL for XSLT 1.0): http://conferences.idealliance.org/extreme/html/2003/Novatchev01/EML2003Novatchev01.htmlAnd this is a link to an FXSL 2.x article (FXSL for XSLT 2.0):http://web.archive.org/web/20070222111927/http://www.idealliance.org/papers/extreme/proceedings/xslfo-pdf/2006/Novatchev01/EML2006Novatchev01.pdf
Dimitre Novatchev