Learn More





DNN Community Blog

The Community Blog is a personal opinion of community members and by no means the official standpoint of DNN Corp or DNN Platform. This is a place to express personal thoughts about DNNPlatform, the community and its ecosystem. Do you have useful information that you would like to share with the DNN Community in a featured article or blog? If so, please contact .

The use of the Community Blog is covered by our Community Blog Guidelines - please read before commenting or posting.

XSLT Extension Objects

XSLTOne of the biggest complaints of anyone using XSLT in .Net is that we are stuck on XSLT 1.0.  While 1.0 provides a lot of capability it is easy to run headlong into the shortcomings of the language.  For a number of reasons which I’ll never understand, Microsoft has not chosen to support XSLT 2.0 or XPATH 2.0 in .Net which forces developers to either live with the limitations of 1.0 or use a 3rd party XSLT engine.  Neither of those options is really great.

There are a number of modules in DotNetNuke which rely heavily on XSLT for advanced formatting: Reports, Form & List and XML module are three that come immediately to mind. It would be great if we could break out of the limitations imposed by the reliance on XSLT 1.0.

Well, in fact you can.  .Net has supported the concept of XSLT Extension Objects for quite a long time.  Essentially, extension objects are .Net code that you can call from within your XSLT.  With this capability you can easily code whatever functionality is missing from XSLT 1.0.  This is just what a group of Microsoft MVPs did with the EXSLT.NET module which is a .NET implementation of EXSLT.  Much of the work done in EXSLT was subsequently incorporated in XSLT 2.0.

In order to use the EXSLT.Net module, your application needs to tell the .Net XslCompiledTransform class where the assembly is that contains your custom extensions.  This is done using the XsltArgumentList.  Implementing this code is rather trivial:

// Create XslCompiledTransform and load the stylesheet.
XslCompiledTransform xslt = new XslCompiledTransform();

// Create an XsltArgumentList.
XsltArgumentList xslArg = new XsltArgumentList();

// Add an object to calculate the new book price.
Extension obj = new DotNetNuke.Demo.Xslt.Extension();
xslArg.AddExtensionObject("DemoXslt", obj);

using (XmlWriter w = XmlWriter.Create("output.xml"))
    // Transform the file.
    xslt.Transform("blog.xml", xslArg, w);

Of course, unless you plan to write your own module to handle XSLT transformations this isn’t really all that useful.  The useful part is being able to apply this knowledge to an existing module that supports XSLT extensions.  The Reports module is the only module currently distributed with DotNetNuke which supports extension objects.  The 6.0 version of the XML module will also support extension objects and I am hoping that Form & List will also support this feature in its upcoming release.

Lets look at an example of using extension objects with the reports module.  In my example I am not going to focus on the XML data side of the equation.  I have installed the latest version of the reports module and added it to my page.  While logged in as a SuperUser, I created a new dummy query Select Test=’’ just so it would generate a little bit of xml.

    <Test />

I want to make sure that I am using the XSL Transformation Visualizer:


For my particular case I am going to pull some data from a user’s profile and then output this information in my XSLT.   I’m also going to generate a URL for displaying the Gravatar associated with a particular email address.  The first step is that I’ll need to define a class in .net that includes a method to get a users biography and a method to get the Gravatar URL.

Imports DotNetNuke.Entities.Users
Imports System.Text
Imports System.Security.Cryptography

Namespace DotNetNuke.Demo.Xslt
  Public Class Extension
    Public Function GetUserBio(
      ByVal portalid As Integer,
      ByVal UserId As Integer) As String

      Dim blogger As UserInfo =
        UserController.GetUserById(portalid, UserId)

      Dim bio As String =

      Return System.Web.HttpUtility.HtmlDecode(bio)
    End Function

    Public Function GetGravatarImage(
      ByVal email As String,
      ByVal size As Integer) As String

      Return String.Format(
        GetMd5Hash(email.ToLower), size)

    End Function

    Private Function GetMd5Hash(ByVal input As String) As String
      Dim md5 As MD5CryptoServiceProvider = 
			  New MD5CryptoServiceProvider()

			Dim bs As Byte() = Encoding.UTF8.GetBytes(input)
      bs = md5.ComputeHash(bs)
      Dim s As StringBuilder = New StringBuilder()
      For Each b As Byte In bs

      Return s.ToString

    End Function
  End Class
End Namespace

In this example I am returning simple strings.  If I wanted to return a node set I would return an XPathNodeIterator which is returned from an XPathNavigator.   For my project, I’ve compiled this class in a DemoXSLT assembly and added this assembly to my /bin folder in my DotNetNuke website. At this point I can add this new extension object to my report definition:


It is important to remember what namespace you assigned to the .Net type so that you can call it from your XSLT. We now have all of the pieces in place and just need to create our XSLT.

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version='1.0' 
  exclude-result-prefixes ="demo">
	<xsl:output method="html" 

  <xsl:template match="/">
    <div class="section" id="about-me">
        About Me
        <xsl:value-of select="demo:GetUserBio(0,2)" 
          <img alt="Blogger Gravatar" 
			src="{demo:GetGravatarImage([email protected]', 150)}">

To use the extension object, I’ve defined a custom namespace which aliases the URN that I defined in the reports module.  Now if I want to call a method in my extension object I just prefix the method name with the “demo:” namespace.  Now if I add a few CSS classes to my portals.css I can generate a nice looking author block for my blog using the biography from my user profile and my Gravatar image:


This is just one of the many techniques that I’ll be showing in my session “A Closer Look at DotNetNuke Core Modules” at CMS Expo this coming week. 


There are currently no comments, be the first to post one.

Comment Form

Only registered users may post comments.


2sic Daniel Mettler (124)
Aderson Oliveira (15)
Alec Whittington (11)
Alex Shirley (10)
Andrew Nurse (30)
Anthony Glenwright (5)
Antonio Chagoury (28)
Ash Prasad (21)
Ben Schmidt (1)
Benjamin Hermann (25)
Benoit Sarton (9)
Beth Firebaugh (12)
Bill Walker (36)
Bob Kruger (5)
Brian Dukes (2)
Brice Snow (1)
Bruce Chapman (20)
Bryan Andrews (1)
cathal connolly (55)
Charles Nurse (163)
Chris Hammond (203)
Chris Paterra (55)
Clinton Patterson (28)
Cuong Dang (21)
Daniel Bartholomew (2)
Dave Buckner (2)
David Poindexter (3)
David Rodriguez (2)
Doug Howell (11)
Erik van Ballegoij (30)
Ernst Peter Tamminga (74)
Geoff Barlow (6)
Gifford Watkins (3)
Gilles Le Pigocher (3)
Ian Robinson (7)
Israel Martinez (17)
Jan Blomquist (2)
Jan Jonas (3)
Jaspreet Bhatia (1)
Jenni Merrifield (6)
Joe Brinkman (268)
John Mitchell (1)
Jon Henning (14)
Jonathan Sheely (4)
Jordan Coopersmith (1)
Joseph Craig (2)
Kan Ma (1)
Keivan Beigi (3)
Ken Grierson (10)
Kevin Schreiner (6)
Leigh Pointer (31)
Lorraine Young (60)
Malik Khan (1)
Matthias Schlomann (15)
Mauricio Márquez (5)
Michael Doxsey (7)
Michael Tobisch (3)
Michael Washington (202)
Mike Horton (19)
Mitchel Sellers (28)
Nathan Rover (3)
Navin V Nagiah (14)
Néstor Sánchez (31)
Nik Kalyani (14)
Peter Donker (52)
Philip Beadle (135)
Philipp Becker (4)
Richard Dumas (22)
Robert J Collins (5)
Roger Selwyn (8)
Ruben Lopez (1)
Ryan Martinez (1)
Salar Golestanian (4)
Sanjay Mehrotra (9)
Scott McCulloch (1)
Scott S (11)
Scott Wilkinson (3)
Scott Willhite (97)
Sebastian Leupold (80)
Shaun Walker (237)
Shawn Mehaffie (17)
Stefan Cullmann (12)
Stefan Kamphuis (12)
Steve Fabian (31)
Timo Breumelhof (24)
Tony Henrich (3)
Torsten Weggen (2)
Vicenç Masanas (27)
Vincent Nguyen (3)
Vitaly Kozadayev (6)
Will Morgenweck (37)
Will Strohl (163)
William Severance (5)
Try Evoq
For Free
Start Free Trial
a Demo
See Evoq Live
Need More Information?