C#: Getting started with Saxon-HE XSLT transformation

The XslCompiledTransform class of .NET only supports XSLT 1.0 for some annoying reason. I needed support for version 2.0 and for that I found the free Saxon-HE library through NuGet.

Their API documentation is OK I suppose, although I wish the API was more .NET targeted. Also can’t say I’m impressed by their documentation on how to get started using this stuff.

Either way, here are the steps to do a simple XSLT transformation of an XML document.

using Saxon.Api;

var xslt = new FileInfo(@"C:\path\to\stylesheet.xslt");
var input = new FileInfo(@"C:\path\to\data.xml");
var output = new FileInfo(@"C:\path\to\result.xml");

// Compile stylesheet
var processor = new Processor();
var compiler = processor.NewXsltCompiler();
var executable = compiler.Compile(new Uri(xslt.FullName));

// Do transformation to a destination
var destination = new DomDestination();
using(var inputStream = input.OpenRead())
{
    var transformer = executable.Load();
    transformer.SetInputStream(inputStream, new Uri(input.DirectoryName));
    transformer.Run(destination);
}

// Save result to a file (or whatever else you wanna do)
destination.XmlDocument.Save(output.FullName);

Sure are a lot more steps than I feel necessary here, but oh well… that’s how you do it anyways *shrug*

  • Stefan Mitic

    Thanks man, this made my day!

  • http://twitter.com/TwoRedCells Red Cell Innovation

    I *think* for the line: transformer.SetInputStream(input, new Uri(xml.DirectoryName));
    you meant: transformer.SetInputStream(input, new Uri(input.DirectoryName));

    • http://www.geekality.net/ Torleif Berger

      That is most definitely correct! Thanks :D

    • Sebastian Uecker

      Actually I think it would even be transformer.SetInputStream(inputStream, new Uri(input.DirectoryName));

      • http://www.geekality.net/ Torleif Berger

        That might be correct too actually. Unable to test it, but looks right. Otherwise the intputStream isn’t actually used for anything at all… updating the post. Thanks :)

  • http://about.me/peSHIr Jarno Peschier

    And what if want to process and XML using an XSLT that are not on the web or locally on disk, but I have them in strings/stream. What do I need to pass as URI to SetInputStream? Setting null bombs (in an ugly way). Shouldn’t the first parameter be enough to set an input stream?

    • http://www.geekality.net/ Torleif Berger

      According to their documentation the baseUri parameter is: “The base URI of the principal input document. This is used for example by the document() function if the document contains links to other documents in the form of relative URIs.”

      So I’d say, try with an empty string, a bogus Uri, http://localhost or whatever?

      • http://about.me/peSHIr Jarno Peschier

        Tried setting it to null or to an Uri instance containing localhost or example.com, and all failed. In thr end I wound up writing XSLT input to TEMP file and seyting BaseUri to file path to TEMP folder. That at least worked.

        • http://www.geekality.net/ Torleif Berger

          Well that’s a bit annoying, but good to hear you found a workaround anyways. Let me know if you find a proper solution though :)