One of the coolest things with XSLT (as an opinion from a .NET developer) is the ability to consume .NET methods and rich functionality from within your XSLT templates. In most cases you won't need this functionality if the XSLT template is only working with outputting published data from content or media. However, in other cases, you may need to access external data or gain access to transformations that are simply not possible to accomplish with XSLT 1.1 alone.
Enter XSLT extensions! As with most custom functionality, XSLT extensions require a bit of configuration and coding to get started. The short of it is this:
Sounds easy, right? It really is, because even the last item is done for you automatically when you create new XSLT templates from the backoffice (for ones that are created after you add an extension library). Roll up your sleeves and create a simple extension. Listing 12-14 covers the basics of the public class and has but one method in it for the purposes of this example. The use case for this example may be that you are trying to figure out how many days old a particular page is and display that in the footer of each page.
LISTING 12-14: XsltExtensions.cs
using System; namespace UmbUsersGuide.Samples { public class XsltExtensions { public static string DayDiff(string startDate, string endDate) { // Parse the passed in dates to DateTime // objects. var sDate = DateTime.Parse(startDate); var eDate = DateTime.Parse(endDate); // Subtract the start date from the end date // and return the number of days return eDate.Subtract(sDate).Days.ToString(); } } }
Now, add the reference to the class in the <install root>/config/xsltExtensions.config file, as shown in Listing 12-15. This allows Umbraco to recognize that a class exists with public methods that are mapped to the specified alias. In this case, all the method calls from within the XSLT templates will be prefixed with umbusersguide.library:MethodName.
LISTING 12-15: xsltExtensions.config
<?xml version=“1.0” encoding=“utf-8” ?> <XsltExtensions> <ext assembly=“/UmbUsersGuide.Samples” type=“UmbUsersGuide.Samples.XsltExtensions” alias=“umbusersguide.library” /> </XsltExtensions>
To utilize this new method, create a new XSLT macro in the backoffice called PageAge.xslt, leaving both the Clean template selected and the Create Macro check boxes selected. You will notice that in the new XSLT template some automatically added attributes appear in the <xsl:stylesheet /> element, as highlighted in bold in Listing 12-16. To use the new method in your XSLT template, simply follow these steps:
If you thought XSLT templates were cool before, now there is virtually no limit to what you can accomplish with them (within technical design reasons of course).
<?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:Exslt.ExsltCommon=“urn:Exslt.ExsltCommon” xmlns:Exslt.ExsltDatesAndTimes=“urn:Exslt.ExsltDatesAndTimes” xmlns:Exslt.ExsltMath=“urn:Exslt.ExsltMath” xmlns:Exslt.ExsltRegularExpressions=“urn:Exslt.ExsltRegularExpressions” xmlns:Exslt.ExsltStrings=“urn:Exslt.ExsltStrings” xmlns:Exslt.ExsltSets=“urn:Exslt.ExsltSets” xmlns:umbusersguide.library=“urn:umbusersguide.library” exclude-result-prefixes=“msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets umbusersguide.library “> <xsl:output method=“xml” omit-xml-declaration=“yes”/> <xsl:param name=“currentPage”/> <xsl:template match=“/”> This page is <b><xsl:value-of select=“umbusersguide.library:DayDiff($currentPage/@createDate, umbraco.library:CurrentDate())”/></b> days old. </xsl:template> </xsl:stylesheet>
The possibilities are endless in terms of what you can return from an XSLT extension method. One other example worth noting is the XPathNodeIterator, which would be used to return structured (XML format, of course) data on which you could then run standard XPath statements.