1

Closed

XmlWriter extension

description

Sometimes I just like to write some code. I try to think of something to make usage of framework parts even better. I remembered the burnden of writing and XML file using the XmlWriter class. Loosing track of all the WriteStartXXX and WriteEndXXX in a method can be hard to fix and Visual Studio removing any indenting when reformatting is accidently executed doesn't help.
 
I saw the Tracer class in the logging code block of the Enterprise Library. This class is supposed to be used in a using() { ... } constuction. The constructor takes care of starting the trace and when the object is disposed ending the trace is taken care of.
 
With this in mind and using my personal favorite feature: extension methods. I came up with the following:
 
Extension usage:
 
using (var w = XmlWriter.Create("D:\Text.xml"))
{
using (w.StartDocument())
{
using (w.StartElement("TestElement"))  
{  
  w.WriteString("test123");  
}  
}
}
 
So no new functionality just making usage more friendly.
 
The extension class (no NUnit tests and documentation just yet :-)
 
public static class XmlWriterExtensions {

public abstract class XmlWriterWatcher : IDisposable
{
protected XmlWriter writer;  
private bool disposed = false;  

public XmlWriterWatcher(XmlWriter writer)  
{  
  this.writer = writer;  
}  

protected abstract void CallWriteEndMethod();            

#region IDisposable Members  

public void Dispose()  
{  
  Dispose(true);  
  GC.SuppressFinalize(this);  
}  

public void Dispose(bool disposing)  
{  
  if (!this.disposed)  
  {  
    // If disposing equals true, dispose all managed and unmanaged resources.  
    if (disposing)  
    {  
      CallWriteEndMethod();  
      writer = null;  
    }  

    // Call the appropriate methods to clean up   
    // unmanaged resources here.  
  }  
  disposed = true;  
}  

#endregion  

~XmlWriterWatcher()  
{  
  Dispose(false);  
}  
}

public class StartElementWatcher : XmlWriterWatcher
{
private bool useWriteFullElementEnd = false;  

public StartElementWatcher(XmlWriter writer)  
  : base(writer)  
{  
}  

public StartElementWatcher(XmlWriter writer, bool useWriteFullElementEnd)  
  : base(writer)  
{  
  this.useWriteFullElementEnd = useWriteFullElementEnd;  
}  

protected override void CallWriteEndMethod()  
{  
  if (useWriteFullElementEnd)  
    writer.WriteFullEndElement();  
  else  
    writer.WriteEndElement();  
}  
}

public class StartDocumentWatcher : XmlWriterWatcher
{
public StartDocumentWatcher(XmlWriter writer)  
  : base(writer)  
{  
}  

protected override void CallWriteEndMethod()  
{  
  writer.WriteEndDocument();  
}  
}

public class StartAttributeWatcher : XmlWriterWatcher
{
public StartAttributeWatcher(XmlWriter writer)  
  : base(writer)  
{  
}  

protected override void CallWriteEndMethod()  
{  
  writer.WriteEndAttribute();  
}  
}

public static StartElementWatcher StartElement(this XmlWriter writer, string localName)
{
writer.WriteStartElement(localName);  
return new StartElementWatcher(writer);  
}

public static StartElementWatcher StartElement(this XmlWriter writer, string localName, string ns)
{
writer.WriteStartElement(localName, ns);  
return new StartElementWatcher(writer);  
}

public static StartElementWatcher StartElement(this XmlWriter writer, string prefix, string localName, string ns)
{
writer.WriteStartElement(prefix, localName, ns);  
return new StartElementWatcher(writer);  
}

public static StartElementWatcher StartElement(this XmlWriter writer, string localName, bool useWriteFullEndElement)
{
writer.WriteStartElement(localName);  
return new StartElementWatcher(writer, useWriteFullEndElement);  
}

public static StartElementWatcher StartElement(this XmlWriter writer, string localName, string ns, bool useWriteFullEndElement)
{
writer.WriteStartElement(localName, ns);  
return new StartElementWatcher(writer, useWriteFullEndElement);  
}

public static StartElementWatcher StartElement(this XmlWriter writer, string prefix, string localName, string ns, bool useWriteFullEndElement)
{
writer.WriteStartElement(prefix, localName, ns);  
return new StartElementWatcher(writer, useWriteFullEndElement);  
}

public static StartDocumentWatcher StartDocument(this XmlWriter writer)
{
writer.WriteStartDocument();  
return new StartDocumentWatcher(writer);  
}

public static StartDocumentWatcher StartElement(this XmlWriter writer, bool standalone)
{
writer.WriteStartDocument(standalone);  
return new StartDocumentWatcher(writer);  
}

public static StartAttributeWatcher StartAttribute(this XmlWriter writer, string localName)
{
writer.WriteStartAttribute(localName);  
return new StartAttributeWatcher(writer);  
}

public static StartAttributeWatcher StartAttribute(this XmlWriter writer, string localName, string ns)
{
writer.WriteStartAttribute(localName, ns);  
return new StartAttributeWatcher(writer);  
}

public static StartAttributeWatcher StartAttribute(this XmlWriter writer, string prefix, string localName, string ns)
{
writer.WriteStartAttribute(prefix, localName, ns);  
return new StartAttributeWatcher(writer);  
}

}
 
Let me know if you like it (or have suggestions or improvements) and I'll add them (and NUnit tests and documentation).
 
Since I love writing extensions I would be glad to be on the developement team of this project.
 
Corrently I pubish my short C# code pieces at http://csharptidbits.blogspot.com (the extension described above is at http://csharptidbits.blogspot.com/2009/03/nice-xmlwriter-extender.html) but I'd rather like them to be in a library that is actually used by people.
 
Regards, Jacco
Closed Mar 21, 2009 at 10:20 AM by Jacco
Added the class to the libary

comments