Xslt 1.0 biggest issues (kind of) solved
Xslt 1.0 has a number of issues that can make the life of an Xml developer frustrating. A lot of them are addressed by Xslt 2.0. Unfortunately the .NET Framework does not have an Xslt 2.0 compliant processor. Fortunately most of the biggest Xslt 1.0 pain points have workarounds. Having workarounds rather than real solutions is almost never ideal but almost always better than nothing.
Grouping
When working with Xml documents it is common to have a list of elements that contain an attribute whose value can be used to qualify a given element to a group. As opposed to Xslt 2.0 which contains the xsl:for-each-group instruction Xslt 1.0 does not natively support grouping. It’s probably one of the biggest (if not the biggest) weaknesses of Xslt 1.0. Although not that straightforward it is still possible to group items in Xslt 1.0. There are basically two techniques for doing this:
- Simple grouping ( *not really recommended* )
- so-called Muenchian grouping
Simple grouping is just looking for keys using preceding-sibling (or following-sibling) axis (something like: item[not(preceding-sibling::item/@group = @group)]). While it may work fine for small sets its performance is horrible and therefore using this method is not recommended. Instead you should group your items using so-called Muenchian grouping which is based on using keys and is way faster than simple grouping (also more complicated). You can find more details on Muenchian grouping in Wikipedia: https://en.wikipedia.org/wiki/Muenchian_grouping. The article also contains a link to in-depth explanation of how Muenchian grouping works.
Regular expressions
It’s not easy to work with strings in Xslt 1.0 let alone regular expressions. A lot of new string functions were introduced in Xslt 2.0. In addition a new instruction xsl:analyze-string enables using regular expressions. While most of the new string functions can be emulated in Xslt 1.0 using existing functions or (recursive) templates this is not the case with regular expressions. In this case the workaround is to use either scripts or extension objects in which it is possible to use regular expressions from .NET Framework. An example that uses an embedded script is shown below:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="https://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:my-scripts="urn:my-scripts"
exclude-result-prefixes="msxsl">
<xsl:output method="text"/>
<msxsl:script language="C#" implements-prefix="my-scripts">
<![CDATA[
public bool ValidateEmailAddress(string emailAddress)
{
return Regex.Match(emailAddress, @"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$").Success;
}
]]>
</msxsl:script>
<xsl:template match="/">
<xsl:variable name="addresses">
<email>john@contoso.com</email>
<email>john@contoso</email>
</xsl:variable>
<xsl:for-each select="msxsl:node-set($addresses)/*">
Address <xsl:value-of select="." /> is <xsl:if test="not(my-scripts:ValidateEmailAddress(.))">not </xsl:if>valid.
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
XHTML output method
In addition to Xml, Html and Text output methods available in Xslt 1.0 Xslt 2.0 introduces a new output method which is XHTML. Fortunately XslCompiledTransform allows for providing your own XmlWriter that will be used to write transformation results. If you provide a specialized version of XmlWriter that can write XHTML compliant documents you will be able to achieve the same functionality as the one enabled by Xslt 2.0. If you don’t have such a writer handy you can use the one that is part of Mvp.Xml library (https://mvpxml.codeplex.com/). See Oleg Tkachenko’s blog entry for some additional details https://www.tkachenko.com/blog/archives/000712.htm
DateTime support
There is no DateTime type defined in XPath 1.0. As a result working with date time in Xslt 1.0 is not easy. Xslt 2.0 on the other hand adopted uses XPath 2.0 type system. As a result DateTime type is first class citizen in Xslt 2.0. How to go about DateTime type in Xslt 1.0? Here are a few ideas you may try depending on your needs:
- Consider using ISO 8601 date format – it is easy to sort, compare and get date parts
- Check the built-in extension functions for formatting date and time (https://msdn.microsoft.com/en-us/library/ms256453.aspx)
- If none of the above works you may need to use scripts or extension objects
Techniques for emulating Xslt 2.0 features with Xslt 1.0 processor can be summarized as follows:
Problem |
Xslt 2.0 feature |
How to achieve this in Xslt 1.0 |
Grouping |
xsl:for-each-group instruction |
Muenchian grouping Simple grouping (small sets only) |
Regular expressions |
xsl:analyze-string instruction |
Embedded scripts/extension objects |
Xhtml output |
New xhtml output method |
Custom XmlWriter using xhtml rules to output transformation results |
Support for processing dates |
DateTime type |
Using ISO-8601 date format Built-in extension functions Scripts/extension objects |
Some of the workarounds I provided may require using scripts. If you are concerned about portability (using scripts will make your Xslt stylesheet not portable) you may want to use EXSLT (https://exslt.org) – a set of well-defined extensions for Xslt 1.0. XslCompiledTransform supports natively only two functions from the EXSLT set (exsl:node-set() and exsl:object-type()) but you can use EXSLT.NET module from the Mvp.Xml project (https://mvpxml.codeplex.com/wikipage?title=EXSLT.NET&referringTitle=Home). Since EXSLT is supported on quite a few platforms you should be able to create portable stylesheets.
Pawel Kadluczka
Comments
Anonymous
October 09, 2011
Yea, I think I'll just use Saxon for XSLT work. http://saxon.sourceforge.net/Anonymous
October 09, 2011
Or use XQSharp which is a native .Net XSLT 2.0 processor: http://www.xqsharp.com You guys have really dropped the ball with XSLT 2.0.Anonymous
October 09, 2011
Thanks! As you said, having workarounds rather than real solutions is almost never ideal, however. Maybe you could support XSLT 2.0 in the not-too-distant future?Anonymous
October 12, 2011
When can we expect XLST 2.0 support in core framework of .Net ? Its been a long time that XLST 2.0 is released. Hopefully it will be in place soon.