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:
-
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.
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">
In the same file, add your magical JScript function:
<msxsl:script language="JScript" implements-prefix="url">
function encode(string)
{
return encodeURIComponent(string);
}
</msxsl:script>
In every XSL file that you would like to utilize this method, include the file itself ...
<xsl:include href="UsefullStuff.xslt" />
... 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">
... 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>
-
a.unique.identifier is variable, as is url-methods. Put whatever you like there. Should look like a URL though.
Make sure you send the string(...) value of your XSL selects to your method. Otherwise, bad things will happen.
Comments
encode url