I asked for UTF-8 Dammit!

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’?>

/xsl:output

/xsl:copy-of

/xsl:template

/xsl:stylesheet

;

 

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

String 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>

/xsl:output