Encode URLs in XSL

Issue: You are updating a system which relies (too much?) on XSL-transformations to generate web content, and the system in question needs to be outfitted with URL encoding. Furthermore, you are using Microsoft's XSL-transformations (XslCompiledTransform) and hence are forced to use XSLT 1.0. Note: If you are using a system where XSLT v2.0 is available, there is a built-in function called url:encode() that you can use:
<xsl:variable 
  name="url-encoded-company-name"
  select="url:encode($company-name)"/>
Oh, back to our problem at hand (or, rather, a solution): In the world of Microsoft and XSL, you can have the magic of JScript to help you out. This is how:
  1. Your XslCompiledTransform instances need to allow style sheets to execute scripts:
    //var transformer = new XslCompiledTransform(pathToFile);
    var settings = new XsltSettings(
      enableDocumentFunction: true, 
      enableScript: true);
    var transformer = new XslCompiledTransform(
      pathToFile, 
      settings, 
      new XmlUrlResolver());

    Note: I'm using C# 4's named parameters to visualize the API. If you're not running C# 4, don't pass the parameter names (the compiler will let you know you've done something bad ;-)). Also, the XmlUrlResolver passed in, is the default UrlResolver, so we're not doing anything magical there.

  2. In a logical spot (an included template-xsl?), add some namespaces:
    <xsl:stylesheet
      version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:msxsl="urn:schemas-microsoft-com:xslt"
      xmlns:url="http://a.unique.identifier/url-methods"
      exclude-result-prefixes="msxsl">
  3. In the same file, add your magical JScript function:
    <msxsl:script language="JScript" implements-prefix="url">
    function encode(string)
    {
      return encodeURIComponent(string);
    }
    </msxsl:script>
  4. In every XSL file that you would like to utilize this method, include the file itself ...
    <xsl:include href="UsefullStuff.xslt" />
  5. ... add the namespace ...
    <xsl:stylesheet
      version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:url="http://a.unique.identifier/url-methods">
  6. ... and then use the method where appropriate:
    <xsl:variable 
      name="url-encoded-company-name"
      select="url:encode(string($page-data/field[@id='company-name']/data/))"/>
    
    <td class="tabheadercell">
      <xsl:attribute 
        name="onclick">window.open('edit-company?name=<xsl:value-of
          select="$url-encoded-company-name"/>','_self');
      </xsl:attribute>
      Edit
    </td>
Some notes...
  1. a.unique.identifier is variable, as is url-methods. Put whatever you like there. Should look like a URL though.
  2. Make sure you send the string(...) value of your XSL selects to your method. Otherwise, bad things will happen.
Hope this helps.

Comments

Popular posts from this blog

Auto Mapper and Record Types - will they blend?

Unit testing your Azure functions - part 2: Queues and Blobs

Testing WCF services with user credentials and binary endpoints