tags:

views:

88

answers:

3

I am looking for a static function in the .NET framework which takes an XML snippet and an XSLT file, applies the transformation in memory, and returns the transformed XML.

I would like to do this:

string rawXml = invoiceTemplateDoc.MainDocumentPart.Document.InnerXml;
rawXml = DoXsltTransformation(rawXml, @"c:\prepare-invoice.xslt"));

// ... do more manipulations on the rawXml

Alternatively, instead of taking and returning strings, it could be taking and returning XmlNodes.

Is there such a function?

+1  A: 

Have you noticed that there is the XsltCompiledTransform class?

Tomalak
Yes. But that class has only filenames, stream, readers or writers as input arguments for its Transform method. It involves a lot of messing around with memorystreams to accomplish a simple transformation on an in-memory XML snippet.
Jan Willem B
XmlDocument implements IXPathNavigable, so you can pass it as input directly. For output, see http://stackoverflow.com/questions/1346995/how-to-create-a-xmldocument-using-xmlwriter-in-net
Matti Virkkunen
A: 

You can use the StringReader and StringWriter classes :

string input = "<?xml version=\"1.0\"?> ...";
string output;
using (StringReader sReader = new StringReader(input))
using (XmlReader xReader = XmlReader.Create(sReader))
using (StringWriter sWriter = new StringWriter())
using (XmlWriter xWriter = XmlWriter.Create(sWriter))
{
    XslCompiledTransform xslt = new XslCompiledTransform();
    xslt.Load("transform.xsl");
    xslt.Transform(xReader, xWriter);
    output = sWriter.ToString();
}
Thomas Levesque
Since there obviously *is* an `XmlDocument` already (he uses `….Document.InnerXml`), using `StringReader` seems superfluous.
Tomalak
...and pretty inefficient because the XML is serialized to a string and then parsed again.
Lucero
indeed, I didn't see he was already using a XmlDocument...
Thomas Levesque
it's not, actually. It looks like it, but it is the OpenXML SDK for reading docx files which has an API very similar to the XmlDocument API, and the API's are not compatible. So I think the downvote is not justified by that.
Jan Willem B
+2  A: 

A little know feature is that you can in fact transform data directly into a XmlDocument DOM or into a LINQ-to-XML XElement or XDocument (via the CreateWriter() method) without having to pass through a text form by getting an XmlWriter instance to feed them with data.

Assuming that your XML input is IXPathNavigable and that you have loaded a XslCompiledTransform instance, you can do the following:

XmlDocument target = new XmlDocument(input.CreateNavigator().NameTable);
using (XmlWriter writer = target.CreateNavigator().AppendChild()) {
  transform.Transform(input, writer);
}

You then have the transformed document in the taget document. Note that there are other overloads on the transform to allow you to pass XSLT arguments and extensions into the stylesheet.

If you want you can write your own static helper or extension method to perform the transform as you need it. However, it may be a good idea to cache the transform since loading and compiling it is not free.

Lucero