0

looking at the XSLCompiledTransform Class in .NET at trying to find a concise way to use it in F#. I am unfamiliar with string readers/writers but am looking at that as primary method to accomplish this. Or do I want XML readers?

I have a function that will take two arguments - an XML string and an XSLT stylesheet. I want to return a string of XML.

let applyXSLTransform xml xslFile =        
        let xslt = XslCompiledTransform()
        xslt.Load(xslFile)
        xslt.Transform(xml, outputToString); //This bit

It's nice and easy to do with files but seems a bit more involved to read and write to strings. I have seen a few C# samples and not having immediate success in getting them to work so still doing research onto readers and writers!

Cheers

Josh
  • 186
  • 1
  • 3
  • 17
  • A C# way is at https://stackoverflow.com/a/16395226/252228, I am not good at F#, perhaps a transpiler like https://github.com/jindraivanek/cs2fs can do the work for you. – Martin Honnen May 18 '21 at 09:34

2 Answers2

1

I don't think there is an easier way to use the API than using the XmlReader and XmlWriter interfaces. This is unfortunately quite tedious, but the following should do the trick:

open System.IO
open System.Text
open System.Xml
open System.Xml.Xsl

let applyXSLTransform xml (xslFile:string) =        
  let xslt = XslCompiledTransform()
  let sbuilder = StringBuilder()
  use swriter = new StringWriter(sbuilder)
  use sreader = new StringReader(xml)
  use xreader = new XmlTextReader(sreader)
  use xwriter = new XmlTextWriter(swriter)
  xslt.Load(xslFile)
  xslt.Transform(xreader, xwriter)
  sbuilder.ToString()

The code constructs StringBuilder, which is an in-memory object for constructing strings. It wraps this around StringWriter and XmlTextWriter to be passed to the Transform method. At the end, you read the contents of the StringBuilder using the ToString method. Similar thing happens to create XmlTextReader for data from StringReader, which contains your input XML.

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • This works well and marked as accepted since it handles the file load as well, though yours and Martin's are both functionally identical and I like both solutions. Not the most tedious thing I've encountered in my F# learnings by any means! – Josh May 18 '21 at 10:39
1

This is what I could come up with, trying to use the recommended XmlReader.Create factory methods instead of the .NET 1 legacy XmlTextReader:

open System
open System.Xml.Xsl
open System.Xml
open System.IO

let transform xml xslt =
    let processor = XslCompiledTransform()

    use xsltreader = XmlReader.Create(new StringReader(xslt))

    processor.Load(xsltreader)

    use xmlreader = XmlReader.Create(new StringReader(xml))
    
    use resultwriter = new StringWriter()

    processor.Transform(xmlreader, null, resultwriter)

    resultwriter.ToString()

But I have no deep knowledge of F#, just tried to convert my C# coding way to F#.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • As far as I can tell this works fine, "using" was a C# construct I was unfamiliar with so wasn't sure how to translate it. Thanks! – Josh May 18 '21 at 10:37