You might be forgiven for thinking that given the same source document and the same transform doing a vanilla XSLT transform (no resolvers, parameters etc) would always give you the same output. Apparently not. The code below calls the same transform with the same source document 3 times in 3 slightly different ways. The first time the transform writes the output with an XmlTextWriter (which is internally writing to a stringbuilder). The second time the transform writes to a stringwriter (which internally is also writing to a stringbuilder). The third time the transform writes to a memory stream. In each case the output is different. The XmlTextWriter completely ignores the <?xml:namespace prefix = xsl />xsl:outputelement of the transform. The stringwriter doesn’t, but it specifies UTF-16 encoding in the xml declaration. The streamwriter is pretty much what we wanted. Indented output with an xml declaration and the correct encoding.
Code
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
namespace XSLEncodingTest
{
class EncodingTester
{
const string transform
= @”<?xml version=‘1.0’?>
“;
const string source = “
“;
[STAThread]
static void Main(string[] args)
{
XslTransform trans = new XslTransform();
trans.Load(new XmlTextReader(new StringReader(transform)));
XmlDocument doc = new XmlDocument();
doc.LoadXml(source);
// string builder (with xml writer)
StringBuilder sb = new StringBuilder();
XmlWriter xmlWriter = new XmlTextWriter(new StringWriter(sb));
trans.Transform(doc, null, xmlWriter);
Console.WriteLine(“String Builder + XML Writer”);
Console.WriteLine(”===============================”);
Console.WriteLine(sb.ToString());
// string builder
StringBuilder sb4UseWithoutXmlWriter = new StringBuilder();
TextWriter stringWriter = new StringWriter(sb4UseWithoutXmlWriter);
trans.Transform(doc, null, stringWriter);
Console.WriteLine(“\nString Builder + StringWriter”);
Console.WriteLine(”===============================”);
Console.WriteLine(sb4UseWithoutXmlWriter.ToString());
//memory stream (no xml writer)
MemoryStream memStream4UseWithoutXmlWriter = new MemoryStream();
trans.Transform(doc, null, memStream4UseWithoutXmlWriter);
memStream4UseWithoutXmlWriter.Flush();
memStream4UseWithoutXmlWriter.Seek(0, SeekOrigin.Begin);
Console.WriteLine(“\nMemory Stream (no XML Writer)”);
Console.WriteLine(”===============================”);
StreamReader reader2 = new StreamReader(memStream4UseWithoutXmlWriter);
Console.WriteLine(reader2.ReadToEnd());
Console.ReadLine();
}
}
}
Output
/xsl:outputString Builder + XML Writer
===============================
<new-document><foo><bar /></foo></new-document>
String Builder (no XML Writer)
===============================
<?xml version=“1.0” encoding=“utf-16”?>
<new-document>
<foo>
<bar />
</foo>
</new-document>
Memory Stream (no XML Writer)
===============================
<?xml version=“1.0” encoding=“utf-8”?>
<new-document>
<foo>
<bar />
</foo>
</new-document>