Of late, I'm a fan of XSLT Extensions in Umbraco. They
are an extremely useful feature of Umbraco that span the .NET and XSLT gap I've seen often. To
give credit where it's due - Per Ploug Hansen is really the one who showed
my the light in terms of XSLT Extensions at Codegarden US
2008. Thanks! In fact, one of my ongoing efforts is
refactoring the Commerce for Umbraco UI layer to use XSLT
Extensions rather than ASP.NET User Controls - I think this will
allow a much slimmer implementation of this commerce project for
Umbraco users.
I've had need to create unique HTML meta tags (title,
description, keywords) for nodes generated from non-Umbraco data
several times recently and have come up with the following approach
- using XSLT Extensions, SubSonic, and a simple C# class. In
one case
the generated nodes are listings (
http://www.planetmold.com/professional-listings/Los%20Angeles-Long%20Beach-CA.aspx)
where the data key is a unique string [Los Angeles-Long
Beach-CA]. Using Url Rewriting I create a unique Url -the
first step in my SEO routine here. Also, using the data key I
retrieve our data records and generate the unique HTML meta
content.
How does this work? Simple, but there are a few parts to
keep aligned. The code below is shown front to back (in
Umbraco terms).
1 - In the Umbraco template set the macro parameter
guid to use the querystring parameter
p using the shorthand notation
[@] to retrieve the querystring:
<?UMBRACO_MACRO macroAlias="ProductMeta" guid="[@p]"></?UMBRACO_MACRO>
2 - Create the macro parameter guid in the
macro ProductMeta

3 - Make an entry in your xsltExtensions.config
file to register the extension
<?xml version="1.0" encoding="utf-8"?>
<XsltExtensions>
...
<ext assembly="/bin/xsltextensions" type="commercexslt.productmeta" alias="meta" />
...
</XsltExtensions>
4 - Create the corresponding macro XSLT (simplified here)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<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:meta="urn:meta"
exclude-result-prefixes="msxml umbraco.library meta">
<xsl:output method="html" omit-xml-declaration="yes"/>
<xsl:param name="currentPage"/>
<xsl:variable name="productGuid" select="//macro/guid"/>
<xsl:variable name="description" select="meta:MetaDescription($productGuid)"/>
<xsl:variable name="keywords" select="meta:MetaKeywords($productGuid)"/>
<xsl:template match="/">
<title><xsl:value-of select="meta:MetaTitle($productGuid)"/></title>
<meta name='description' content='{$description}'></meta>
<meta name='keywords' content='{$keywords}'></meta>
</xsl:template>
</xsl:stylesheet>
5 - Create the C# class to get the data (yep, simplified
again)
using System;
using System.Collections.Generic;
using System.Text;
using SubSonic;
namespace commercexslt
{
public class productmeta
{
public static string MetaTitle(string ProductGUID)
{
Guid _productGUID = new Guid(ProductGUID);
// returns an ActiveRecord class which wraps the ProductMeta table
c4uXslt.ProductMetum title = new c4uXslt.ProductMetum("productGUID", _productGUID);
if (title.HtmlTitle.Length != 0)
return title.HtmlTitle;
else
return "the default title";
}
...
Note that I'm using SubSonic to access my data source - you may
choose that method or any other that works for you. The
important items to note are:
1 - I return a string type
2 - The method is marked public
static
6 - Just for completeness, the underlying content table looks
like this

That's it!
Now, when the node renders based on the querystring parameter we
generate not only the correct data but also unique HTML meta
content. And, since this data is SQL-based and managed
separately from Umbraco we don't need to worry about keeping nodes
in sync with external data. Also, since we're dealing with
15,000 unique records and related content this approach ensures we
have unique content for each data item - an important SEO
consideration.
-Paul