Planet Claire

some say she's from Mars

Umbraco experiment - style related constants in XSLT

by Claire 10/30/2010 2:43:00 PM

The Problem - constants in XSLT files

I often find myself using constants in xslt, especially when using the fabulous ImageGen package. But as these constants are often directly related to the theme of the website, which is controlled by the css and encapsulated in a /style or /css directory in my project, it feels wrong to hard code these constants in xslt files.  In fact I have already been bitten on the bum on one site I look after, when a design makeover caused these constants to change, and not all of the values were contained in the stylesheet - messy.

Example - Feature boxes on home page

  • The site I'm working on at the moment has a 2 x 3 grid of feature photos with captions, which link to internal pages.
  • Each photo has a specific width which is tightly tied to the design of the website and will change if the design of the website changes
  • Usually, this would be controlled in the .css file, but
  • The site editor wants to be able to switch photos & captions at will, therefore we let them by making appropriate doctypes in umbraco
  • The site editor doesn't want to know about resizing images before uploading, therefore we use ImageGen
  • In the xslt which renders the feature pics, ImageGen lets us specify a width
  • I want that width to be stored in a central place inside the /style directory, for easier maintenance

Experimental Solution

I've got an idea of how to get around my problem, but as there are always so many ways to do things, I'm not sure if it's the best, so I'm going to run with it for a while & see how we go.

XSLT extensions seem to be the standard way to access C# code from XSLT.  One thing I discovered through experimentation is that your XSLT extension library doesn't have to be a separate class library to work, you can just give the namespace of the class inside your website project.  I guess that if XSLT extensions are meant to represent re-usable libraries then it makes sense for them to be a separate class library, but in this case I want to keep my class file of constants inside the /style folder (for maintainability).

1. Add a class to the styles directory containing your style related constants

Here's my class

namespace SCB.css
{
public class StyleConstants
{

public const int HomePageFeatureWidth = 208;

public int GetHomePageFeatureWidth()
{
return HomePageFeatureWidth;
}
}
}

2. Register the XSLT extension

In umbraco's /config/xsltExtensions.config file, add this

<XsltExtensions>
<ext assembly="SCB" type="SCB.css.StyleConstants" alias="styleConst" />
</XsltExtensions>

3. Use the constant in your XSLT

Here's my XSLT file that renders the feature pics, automatically sizing the photos my editor has uploaded to the correct width

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp "&#x00A0;">
]>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library" xmlns:styleConst="urn:styleConst"
exclude-result-prefixes="msxml umbraco.library styleConst">


<xsl:output method="xml" omit-xml-declaration="yes"/>

<xsl:param name="currentPage"/>

<xsl:template match="/">
<xsl:for-each select="$currentPage/picturesWithHeadingsLinks">

<xsl:variable name="item" select="umbraco.library:GetXmlNodeById(./content/id)"></xsl:variable>
<a href="{umbraco.library:NiceUrl($item/link)}">
<img src="{concat('/umbraco/ImageGen.ashx?image=', umbraco.library:GetMedia($item/picture, 0)/umbracoFile, '&amp;width=', styleConst:GetHomePageFeatureWidth())}" alt="{$item/heading}"></img>
<h2>
<xsl:value-of select="$item/heading"/>
</h2>
</a>
</xsl:for-each>


</xsl:template>

</xsl:stylesheet>

(Please excuse the crappy code rendering above, I really need to do some work on my own website)

Note the styleConst references above.  This effectively means that I can now style the home page using only the files inside the /styles directory.  When things change, I know I don't have to go scouting through XSLT files or elsewhere for hardcoded constants.

Tags:

Umbraco

blog comments powered by Disqus