A better XmlWriter

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!");
    }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s