I’m not a huge fan of the XmlWriter API. In particular, remembering to close every tag.
It would be nice to have something like Haml, where the nesting takes care of it. A bit tricky in C#, but you can get some of the effect by (ab)using IDisposable:
public class SelfClosingXmlWriter
{
private readonly XmlWriter _xmlWriter;
public SelfClosingXmlWriter(XmlWriter xmlWriter)
{
_xmlWriter = xmlWriter;
}
public XmlElementCookie WriteStartElement(string localName)
{
_xmlWriter.WriteStartElement(localName);
return new XmlElementCookie(_xmlWriter);
}
public XmlAttributeCookie WriteStartAttribute(string localName)
{
_xmlWriter.WriteStartAttribute(localName);
return new XmlAttributeCookie(_xmlWriter);
}
public void WriteRaw(string xml)
{
_xmlWriter.WriteRaw(xml);
}
public void WriteString(string xml)
{
_xmlWriter.WriteString(xml);
}
public void WriteAttributeString(string localName, string value)
{
_xmlWriter.WriteAttributeString(localName, value);
}
public class XmlElementCookie : IDisposable
{
private readonly XmlWriter _xmlWriter;
public XmlElementCookie(XmlWriter xmlWriter)
{
_xmlWriter = xmlWriter;
}
public void Dispose()
{
_xmlWriter.WriteEndElement();
}
}
public class XmlAttributeCookie : IDisposable
{
private readonly XmlWriter _xmlWriter;
public XmlAttributeCookie(XmlWriter xmlWriter)
{
_xmlWriter = xmlWriter;
}
public void Dispose()
{
_xmlWriter.WriteEndAttribute();
}
}
}
Which lets you go from this:
var writer = XmlWriter.Create("out.xml", settings);
writer.WriteStartElement("book");
writer.WriteStartElement("author");
writer.WriteStartElement("name");
writer.WriteString("Big John");
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteStartElement("title");
writer.WriteString("Amazing Cakes!");
writer.WriteEndElement();
writer.WriteEndElement();
To this:
var writer = new SelfClosingXmlWriter(XmlWriter.Create("out.xml", settings));
using (writer.WriteStartElement("book"))
{
using (writer.WriteStartElement("author"))
{
using (writer.WriteStartElement("name"))
{
writer.WriteString("Big John");
}
}
using (writer.WriteStartElement("title"))
{
writer.WriteString("Amazing Cakes!");
}
}