tags:

views:

867

answers:

4

In native programming the IXMLDOMDocument2 object had a tranformNode() method:

public BSTR transformNode(IXMLDOMNode stylesheet);

So in the end i could tranform an XML document using:

public string TransformDocument(IXMLDOMDocument2 doc, IXMLDOMDocument2 stylesheet)
{
   return doc.TransformNode(stylesheet);
}

i'm trying to find the managed equivalent. i've already discovered XmlDocument object:

public string TransformDocument(XmlDocument doc, XmlDocument stylesheet)
{
   //return doc.TransformNode(stylesheet); //TransformNode not supported
}

So what is the managed way to tranform xml?

i've stumbled across the depricated XslTransform object, but none of the 18 overloads takes an xml document, or an xml stylesheet.

The replacment Microsoft indicates is the mouthful: System.Xml.Xsl.XslCompiledTransform. But like it's depricated cousin, none of XslCompiledTransform's 14 overloads takes xml in an input parameter.

So what's the accepted method to transform xml in C# .NET 2.0?

Put it another way: complete the following helper method:

public string TransformDocument(XmlDocument doc, XmlDocument stylesheet)
{
   //todo: figure out how to transform xml in C#
}


Answer

Waqas had the answer. Here is another, very similiar, solution:

/// <summary>
/// This method simulates the XMLDOMDocument.TransformNode method
/// </summary>
/// <param name="doc">XML document to be transformed</param>
/// <param name="stylesheet">The stylesheet to transform with</param>
/// <returns></returns>
public static string Transform(XmlDocument doc, XmlDocument stylesheet)
{
    XslCompiledTransform transform = new XslCompiledTransform();
    transform.Load(stylesheet); // compiled stylesheet

    System.IO.StringWriter writer = new System.IO.StringWriter();
    transform.Transform(doc, XmlWriter.Create(writer));

    return writer.ToString();   
}

Note: If you're a performance weenie, you might want to create an overload to pass the pre-compiled transform, if you're going to transforming more than once.

public static string Transform(XmlDocument doc, XslCompiledTransform stylesheet)
{
   ...
}
A: 

First load the XSL and the XML doc.

XmlDocument xsldoc = new XmlDocument();
xsldoc.Load(xslfile);

XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(xmlfile);

Load the xsl into a transform object.

XslCompiledTransform xsldoctrans = new XslCompiledTransform();
xsldoctrans.Load(xsldoc);

Transform it into a memorystream that can be read.

MemoryStream ms = new MemoryStream();
xsldoctrans.Transform(xmldoc, (XsltArgumentList)null, ms);

Then get the transformed data:

byte[] bTransformeddata = ms.ToArray();
string sTransformeddata = xsldoctrans.OutputSettings.Encoding.GetString(bTransformeddata);
Wolf5
+5  A: 

The functions take IXPathNavigable objects as input (and XmlDoucment/XmlNode classes implement IXPathNavigable).

Here's how it would work:

public string TransformDocument(XmlDocument doc, XmlDocument stylesheet)
{
   XslCompiledTransform transform = new XslCompiledTransform();
   transform.Load(stylesheet); // compiled stylesheet
   System.IO.StringWriter writer = new System.IO.StringWriter();
   transform.Transform(doc, null, writer);
   return writer.ToString();
}

Optimizations and improvements:

  • Cache the compiled stylesheet if you use it more than once.
  • Load the XSL directly into the XslCompiledTransform instead of building an XmlDocument first.
  • Use XmlNode instead of XmlDocument to make the function more generic.
waqas
+1 for nice touches about optimisations and improvements
Kev
@anonymousstackoverflowuser Sorry about that. Missed an argument. Fixed.
waqas
Answer status regained! i edited question with the option of wrapping the StringWriter *in* an XmlWirter.
Ian Boyd
A: 

How about:

static void Main(string[] args)
{
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(pathToXmlOrXMLString);

    XslCompiledTransform xsl = new XslCompiledTransform();
    xsl.Load(pathToXsl);

    string result = TransformDocument(doc, xsl);

}

static string TransformDocument(XmlDocument doc, XslCompiledTransform xsl)
{    
    StringBuilder sb = new StringBuilder();
    using (StringWriter sw = new StringWriter(sb))
    {
     xsl.Transform(doc.CreateNavigator(), null, sw);
    }

    return sb.ToString();
}
Kev
A: 

The solution I use in production code, looks similar to Wolf's, but calls the XslCompiledTransform.Transform method with an XPathDocument (initializable from a string containing XML) and an XmlWriter which directs the output to a StringBuilder.

devio