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:
- Write a C# class that represents the extension
- Add information about the class to the
/App_Data/Composite/Composite.config
file - 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 { [ConfigurationElementType(typeof(ConfigBasedXslExtensionInfo))] 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 />"); html.Append(WebUtility.HtmlEncode(parts[i])); } html.Append("</div>"); return XElement.Parse(html.ToString()).CreateNavigator(); } } }
These are the changes to be made in /App_Data/Composite/Composite.config
:
<configuration> <!-- skipped --> <Composite.Functions.Plugins.XslExtensionsProviderConfiguration> <XslExtensionProviders> <add name="ConfigurationBasedXslExtensionsProvider" type="Composite.StandardPlugins.Functions.XslExtensions.ConfigBasedXslExtensionsProvider"> <xslExtensions> <!--- skipped --> <add name="http://c1.composite.net/Example" type="Composite.Examples.ExtensionObject, App_Code" /> </xslExtensions> </add> </XslExtensionProviders> </Composite.Functions.Plugins.XslExtensionsProviderConfiguration> </configuration>
The XSLT function example:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:in="http://www.composite.net/ns/transformation/input/1.0" xmlns:e="http://c1.composite.net/Example" xmlns="http://www.w3.org/1999/xhtml" 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'" /> <html> <head></head> <body> <xsl:choose> <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" /> </form> </xsl:when> <xsl:otherwise> Thank you for the participation. <br /> The text you entered: <xsl:copy-of select="e:ParseLineBreaks(e:GetFormData('textArea1'))" /> </xsl:otherwise> </xsl:choose> </body> </html> </xsl:template> </xsl:stylesheet>
The highlights to the above example:
- We specify the namespace ("e") for our extension:
xmlns:e="http://c1.composite.net/Example"
- We use our first extesion method
GetFormData
to check if the form has been submitted:<xsl:variable name="formPosted" select="e:GetFormData('formId') = 'feedbackForm'" />
- 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'))" />