Background
I'm developing a desktop application that can create/open a project (think of visual studio). I need to persist such a project object to a XML file (think of .csproj) and load that project object from the XML file.
Goals
- Store / load class MyProject to / from XML file
- Human-readable XML (manual edits are bad, but it could simplify some tasks)
- Valid XML that could be parsed from other languages / apps:
- File starts with XML Declaration like
<?xml version="1.1" encoding="utf-8"?>
since user defined strings in any culture may end up here, thus the encoding is important. Also see Does a valid XML file require an xml declaration? - Class namespaces can be specified (e.g. via
DataContractAttribute.NameSpace
)
- File starts with XML Declaration like
Q: What's the best way to persist an object into a readable & valid XML file?
There are many ways to create XML and for me it seems the [DataContract] attribute is the way to go, since this allows for simple serialization and deserialization back into an object (goal 1). When using an XmlTextWriter I can also specify Formatting.Indented
, which solves goal 2. However, I'm unable to create the XML declaration.
Edit: Solution based on Accepted Answer
Using the XmlTextWriter
was a dead end, it does not accept XmlWriterSettings
. There are too many (wrong/bad) ways to write XML. Using XmlWriter.Create(..)
with the desired settings indeed produces human readable XML including declaration. The created instance is some internal class like WellFormedXmlWriter
. The code:
public static void Store<T>(string filename, T obj)
where T : class
{
XmlWriterSettings settings = new XmlWriterSettings()
{
Indent = true, // human readable
OmitXmlDeclaration = false, // don't omit the encoding
Encoding = Encoding.UTF8
};
using (var xmlwriter = XmlWriter.Create(filename, settings))
{
DataContractSerializer ser = new DataContractSerializer(typeof(T));
ser.WriteObject(xmlwriter, obj);
}
}
public static T Load<T>(string filename)
where T : class
{
using (var xmlReader = XmlReader.Create(filename))
{
DataContractSerializer ser = new DataContractSerializer(typeof(T));
return (T)ser.ReadObject(xmlReader, true);
}
}