Using StringWriter for XML Serialization
One problem with StringWriter
is that by default it doesn't let you set the encoding which it advertises - so you can end up with an XML document advertising its encoding as UTF-16, which means you need to encode it as UTF-16 if you write it to a file. I have a small class to help with that though:
public sealed class StringWriterWithEncoding : StringWriter{ public override Encoding Encoding { get; } public StringWriterWithEncoding (Encoding encoding) { Encoding = encoding; } }
Or if you only need UTF-8 (which is all I often need):
public sealed class Utf8StringWriter : StringWriter{ public override Encoding Encoding => Encoding.UTF8;}
As for why you couldn't save your XML to the database - you'll have to give us more details about what happened when you tried, if you want us to be able to diagnose/fix it.
When serialising an XML document to a .NET string, the encoding must be set to UTF-16. Strings are stored as UTF-16 internally, so this is the only encoding that makes sense. If you want to store data in a different encoding, you use a byte array instead.
SQL Server works on a similar principle; any string passed into an xml
column must be encoded as UTF-16. SQL Server will reject any string where the XML declaration does not specify UTF-16. If the XML declaration is not present, then the XML standard requires that it default to UTF-8, so SQL Server will reject that as well.
Bearing this in mind, here are some utility methods for doing the conversion.
public static string Serialize<T>(T value) { if(value == null) { return null; } XmlSerializer serializer = new XmlSerializer(typeof(T)); XmlWriterSettings settings = new XmlWriterSettings() { Encoding = new UnicodeEncoding(false, false), // no BOM in a .NET string Indent = false, OmitXmlDeclaration = false }; using(StringWriter textWriter = new StringWriter()) { using(XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings)) { serializer.Serialize(xmlWriter, value); } return textWriter.ToString(); }}public static T Deserialize<T>(string xml) { if(string.IsNullOrEmpty(xml)) { return default(T); } XmlSerializer serializer = new XmlSerializer(typeof(T)); XmlReaderSettings settings = new XmlReaderSettings(); // No settings need modifying here using(StringReader textReader = new StringReader(xml)) { using(XmlReader xmlReader = XmlReader.Create(textReader, settings)) { return (T) serializer.Deserialize(xmlReader); } }}
First of all, beware of finding old examples. You've found one that uses XmlTextWriter
, which is deprecated as of .NET 2.0. XmlWriter.Create
should be used instead.
Here's an example of serializing an object into an XML column:
public void SerializeToXmlColumn(object obj){ using (var outputStream = new MemoryStream()) { using (var writer = XmlWriter.Create(outputStream)) { var serializer = new XmlSerializer(obj.GetType()); serializer.Serialize(writer, obj); } outputStream.Position = 0; using (var conn = new SqlConnection(Settings.Default.ConnectionString)) { conn.Open(); const string INSERT_COMMAND = @"INSERT INTO XmlStore (Data) VALUES (@Data)"; using (var cmd = new SqlCommand(INSERT_COMMAND, conn)) { using (var reader = XmlReader.Create(outputStream)) { var xml = new SqlXml(reader); cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("@Data", xml); cmd.ExecuteNonQuery(); } } } }}