Adding an XSLT extension

Extend XSLT Functions with C# Code

If you want to execute some C# code from XSLT functions, you can create an XSLT extension object.

What you need to do is:

  1. Write a C# class that represents the extension
  2. Add information about the class to the /App_Data/Composite/Composite.config file
  3. Add a namespace to your XSLT function

As an example, here's a class that has 2 methods:

  • The first method gets a value from a HTTP posted form.
  • The second one does HTML-encoding of a text and converts new line characters "\r\n" into <br/> tags, so line breaks in text will be line breaks in XHTML.

Note that a class should be "public", not-static and should be marked with the necessary attribute, visible methods should be public and non-static.

using System;
using System.Net;
using System.Text;
using System.Web;
using System.Xml.Linq;
using System.Xml.XPath;
using Composite.Plugins.Functions.XslExtensionsProviders.ConfigBasedXslExtensionsProvider;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

namespace Composite.Examples 
	public class ExtensionObject 
		public string GetFormData(string key) 
			var httpContext = HttpContext.Current; 

			if (httpContext == null || httpContext.Request == null || httpContext.Request.Form == null) 
				return string.Empty; 

			return httpContext.Request.Form[key] ?? string.Empty; 

		public XPathNavigator ParseLineBreaks(string text) 
			string[] parts = text.Split(new string[] {Environment.NewLine}, StringSplitOptions.None);
			StringBuilder html = new StringBuilder("<div>"); for (int i = 0; i < parts.Length; i++) 
				if (i > 0) 
					html.Append("<br />");


			return XElement.Parse(html.ToString()).CreateNavigator(); 

These are the changes to be made in /App_Data/Composite/Composite.config:

  <!-- skipped -->
      <add name="ConfigurationBasedXslExtensionsProvider" 
          <!--- skipped -->
          <add name="" 
               type="Composite.Examples.ExtensionObject, App_Code" />

The XSLT function example: 

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="" xmlns:in="" xmlns:e="" xmlns="" exclude-result-prefixes="xsl in">
  <xsl:template match="/">
    <!-- Using the extension method in order to check if current form was submitted -->
    <xsl:variable name="formPosted" select="e:GetFormData('formId') = 'feedbackForm'" />
          <xsl:when test="not($formPosted)">
            <form method="post">
              <!-- Some markup here -->
              <input type="hidden" name="formId" value="feedbackForm" />
              <textarea name="textArea1" />
              <br />
              <input type="submit" />
            Thank you for the participation. <br /> The text you entered: <xsl:copy-of select="e:ParseLineBreaks(e:GetFormData('textArea1'))" />

The highlights to the above example:

  1. We specify the namespace ("e") for our extension: xmlns:e=""
  2. We use our first extesion method GetFormData to check if the form has been submitted: <xsl:variable name="formPosted" select="e:GetFormData('formId') = 'feedbackForm'" />
  3. We use second method ParseLineBreaks (on the output of the first method) to correctly present the data the user has entered in the form: <xsl:copy-of select="e:ParseLineBreaks(e:GetFormData('textArea1'))" />