Thursday, April 18, 2013

C# in memory XSLT processing

Needed to create an in memory (stream) based XSLT, was frustrated all the ready examples were file based, so documenting my solution for future reference and to share the love.

The convenience wrapper that references string names:


public static string DoXslTransform(string xslPath, string xmlBase, string relativeUri)
{

    XslCompiledTransform transform = 
      GetXslCompiledTransform(xslPath);

    Uri baseUri = new Uri(xmlBase);

    XmlReader xmlReader = GetXmlReader(baseUri, relativeUri);

    string data = GetXslToString(transform, xmlReader);

    xmlReader.Close();

    return data;
}

Method to create a stream based XmlReader:


public static XmlReader GetXmlReader(Uri baseUri, string relativeUri)
{
    XmlUrlResolver xmlUrlResolver = new XmlUrlResolver();

    xmlUrlResolver.Credentials = 
      System.Net.CredentialCache.DefaultCredentials;

    Uri fulluri = 
      xmlUrlResolver.ResolveUri(baseUri, relativeUri);

    Stream stream = (Stream)
      xmlUrlResolver.GetEntity(fulluri, null, typeof(Stream));
    return XmlReader.Create(stream);
}

Method to create a compiled transformer:


public static XslCompiledTransform GetXslCompiledTransform(string xslPath)
{
    XslCompiledTransform transform = new XslCompiledTransform();

    XmlReaderSettings xmlReaderSettings = 
      new XmlReaderSettings();
    xmlReaderSettings.DtdProcessing = DtdProcessing.Prohibit;
    xmlReaderSettings.CloseInput = true;

    XsltSettings xsltSettings = new XsltSettings(true, true);

    XmlResolver secureResolver = 
      new XmlSecureResolver(new XmlUrlResolver(), xslPath);

    transform.Load(XmlReader.Create(xslPath, xmlReaderSettings), 
      xsltSettings, secureResolver);

    return transform;
}

Method to do the transformation to string:


public static string GetXslToString(XslCompiledTransform transform, XmlReader xmlReader)
{
    MemoryStream memoryStream = 
      new MemoryStream();
    StreamWriter outStreamWriter = 
      new StreamWriter(memoryStream);

    transform.Transform(xmlReader, null, outStreamWriter);

    outStreamWriter.Flush();
    memoryStream.Position = 0;

    StreamReader reader = new StreamReader(memoryStream);
    
    return reader.ReadToEnd();
}