After developing with the Sitecore CMS for a couple of months I have seen what XSLT can offer in terms of a powerful web technology. I decided early on, before using Sitecore, that Vodka 2.0 would have to support XSL transforms since the content is stored as XML. The following is a sample of how to work with XML and XSLT in the second version of the Focused Games Framework (FGF 2.0).
While the XSLT code can go pretty much anywhere in the ASP.NET pipeline, for now I have put it in my main Controller. Note that this code is not final, I will be looking into a better way to streamline the content retrieval process.
1 2 3 4 5 6 | public class ContentController : Controller { public ActionResult Get(string uri) { Content content = GetContent(uri, -1); Content template = GetContent(content.TemplateId, -1); |
Next the XslTransformer class is instantiated and a test extension is added. Extensions can be simple or complext .NET classes. Again I plan to streamline this process and support loading from the web.config file.
1 2 3 4 5 6 7 8 9 10 11 12 13 | XslTransformer transformer = new XslTransformer(GetDocument); transformer.AddExtension( new XsltExtension { Namespace = "http://focusedgames.com/vodka", Provider = new VodkaXslExtensions() } ); ViewData["Content"] = transformer.Transform(uri, template.Meta.Uri); return View("Get", "~/Themes/FGDN/Theme.master"); } |
When the Transform method is invoked, the transformer attempts to load documents through a callback. This process will definitely be streamlined so that the re-implementation of the following method isn’t required. The callback method loads the content straight from the database through an SqlContentProvider object. Not much has really changed here since Vodka 1.0 except for the addition of support for both languages and versioning.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public Content GetContent(string uri, int parent) { SqlContentProvider scp = new SqlContentProvider(); NameValueCollection parameters = new NameValueCollection(); parameters.Add(SqlContentProvider.ConnectionStringParameterName, connectionString); scp.Initialize(parameters); Content content = scp.GetContent(uri.ToLower()); return content; } private XPathDocument GetDocument(Uri uri) { Content content = GetContent(uri.OriginalString, -1); XPathDocument document = new XPathDocument(new StringReader(content.Xml)); return document; } } |
And finally the simple extension object:
1 2 3 4 5 6 7 | public class VodkaXslExtensions { public string GetDate() { return DateTime.Now.ToString(); } } |
So what does this produce exactly? Well it takes the following XML…
1 2 3 4 5 6 7 8 9 | <?xml version="1.0"?>
<content>
<title>Home</title>
<description>
<p>This website is still under construction, please check back soon.</p>
<p>Thank you,</p>
<p><a href="http://jsedlak.com">John Sedlak</a></p>
</description>
</content> |
And uses the following XSLT file (stored in the Vodka Database)…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:test="http://focusedgames.com/vodka" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl test"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<h2>
<xsl:value-of select="title"/>
</h2>
<div class="Description">
<xsl:value-of select="description"/>
</div>
<p><xsl:value-of select="test:GetDate()"/></p>
</xsl:template>
</xsl:stylesheet> |
And produces the following HTML…
1 2 3 | <h2>Home</h2> <div class="Description">This website is still under construction, please check back soon.Thank you,John Sedlak</div> <p>9/21/2009 5:23:04 PM</p> |