Use code blocks to extend your BizTalk custom XSLT maps

April 12th, 2010

Update 2010-04-13
Grant Samuels commented and made me aware of the fact that inline scripts might in some cases cause memory leaks. He has some further information here and you’ll find a kb-article here. 

I’ve posted a few times before on how powerful I think it is in complex mapping to be able to replace the BizTalk Mapper with a custom XSLT script (here’s how to). The BizTalk Mapper is nice and productive in simpler scenarios but in my experience it break down in more complex ones and maintaining a good overview is hard. I’m however looking forward to the new version of the tool in BizTalk 2010 – but until then I’m using custom XSLT when things gets complicated.

Custom XSLT however lacks a few things once has gotten used to have – such as scripting blocks, clever functoids etc. In some previously post (here and here) I’ve talked about using EXSLT as a way to extend the capabilities of custom XSLT when used in BizTalk.

Bye, bye external libraries – heeeello inline scripts ;)

Another way to achieve much of the same functionality even easier is to use embedded scripting that’s supported by the XslTransform class. Using a script block in XSLT is easy and is also the way the BizTalk Mapper makes it possible to include C# snippets right into your maps.

Have a look at the following XSLT sample:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    xmlns:code="http://richardhallgren.com/Sample/XsltCode"
    exclude-result-prefixes="msxsl code"
    >
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="@* | node()">
        <Test>
            <UniqueNumber>
                <xsl:value-of select="code:GetUniqueId()" />
            </UniqueNumber>
            <SpecialDateFormat>
                <xsl:value-of select="code:GetInternationalDateFormat('11/16/2003')" />
            </SpecialDateFormat>
            <IncludesBizTalk>
                <xsl:value-of select="code:IncludesSpecialWord('This is a text with BizTalk in it', 'BizTalk')" />
            </IncludesBizTalk>
        </Test>
    </xsl:template>

    <msxsl:script language="CSharp" implements-prefix="code">
        //Gets a unique id based on a guid
        public string GetUniqueId()
        {
            return Guid.NewGuid().ToString();
        }

        //Formats US based dates to standard international
        public string GetInternationalDateFormat(String date)
        {
            return DateTime.Parse(date, new System.Globalization.CultureInfo("en-US")).ToString("yyyy-MM-dd");
        }

        //Use regular expression to look for a pattern in a string
        public bool IncludesSpecialWord(String s, String pattern)
        {
            Regex rx = new Regex(pattern);
            return rx.Match(s).Success;
        }
    </msxsl:script>
</xsl:stylesheet>

All one has to do is to define a code block, reference the xml-namespace used and start coding! Say goodbye to all those external library dlls!

It’s possible to use a few core namespaces without the full .NET namespace path but all namespaces are available as long as they are fully qualified. MSDN has a great page with all the details here.

6 Responses to “Use code blocks to extend your BizTalk custom XSLT maps”

  1. Markus Olsson Says:

    Yeay, for once you write about something that I can relate to and not just hardcore biztalk stuff :)

    Really cool stuff, seems to (amongst other things) have great potential to improve readability in large/complex transformations. It would be interesting to know a bit more about the security implications. Under what credentials will the code execute? Is there any restrictions while the code is running (CAS, trust, etc)?

  2. Grant Samuels Says:

    Will this cause memory leakage as described:

    http://linderalex.blogspot.com/2008/06/memory-leak-using-biztalk-mapper.html
    http://support.microsoft.com/kb/918643

    Inline script seems to be the culprit in these scenarios?

  3. Mike Stephenson Says:

    Hi Richard

    Would be interested to hear your view on this….

    In general I tend to try to use external assemblies in preference to inline scripts as my default approach. The single most important reasons in my opinion for doing this is that developers dont effectively cover the unit testing of the helper functions when they are implemented as inline scripts. When they are in a helper class I get code coverage analysis to ensure they are tested properly and can implement things like check in policies to ensure they are doing their job.

    I think one of the biggest causes of bugs in maps I come across on our projects is poor code in inline scripts which has not been tested.

    Just wondered if you had a view on this or had covered this some other way

    Cheers
    Mike

  4. Richard Says:

    @Mike: First, thanks for your comment.

    I also think there is a very relevant point in your comment. When using longer methods with more complex logic we still usally try and do this in an external assembly. Partly is has to do with quality and testing as you mention. But it’s also much easier to develop and be more productive in pure code than in a script.

    However when that’s said I really like the option to use online script for easier and small chunks of code such as string, date manupulation and so on. These small methods usally goes untested and usally isn’t a problem.

  5. Stefan Says:

    I have a feeling that C# inline scripts can be compared to using vendor specific stored procedures in SQL, mixing HTML and php, etc. instead of separating structure and logic (well, xslt can be seen as logic perhaps :) but you get the idea).

    Bascially you lose portability of the otherwise portable XSLT in case you want to move to another platform in the future. Like migrating off a Oracle database needs conversion of the stored procedures, etc.

    I realize that inline scripting (and external libs) is a cool and powerful tool, but is there some other way? Is XSLT expressive enough to implement such functions self-contained, i.e. opening up the possibility of a standard library of common functions?

  6. Richard Says:

    @Stefan: I see you point. I do however think that XSLT 1.0 lacks so much functionality today that one has to find some way of extending it to solve small easy tasks without 100 lines of xslt ;) . EXSLT could be anotherway as I describe here. I don’t however feel that it gives you more portability and is vendor more agnostic solution …

Leave a Reply