Indenting attributes with XmlTextWriter

| No Comments | No TrackBacks

XmlTextWriter in .NET 1.X only supports indentation of the following node types: DocumentType, Element, Comment, ProcessingInstruction, and CDATA. No attributes. So how to get attributes indented anyway? If you can - wait .NET 2.0 with cool XmlWriterSettings.NewLineOnAttributes, otherwise - here is a hack how to get attributes indented with XmlTextWriter in .NET 1.X.

Well, XmlWriter isn't particularly low-level writer, it's abstract XML oriented API, so its implementation XmlTextWriter wouldn't allow you to just override WriteStartAttribute() method and inject indentation characters before each attribute - it would be considered as an exceptional attempt to write an attribute after a content has been already written. But when instantiating XmlTextWriter on top of some TextWriter, one can inject indentation before each attribute to that underlying TextWriter. It doesn't look particularly clean, but anyway:

public class AttributeIndentingXmlTextWriter : XmlTextWriter 
{
    private TextWriter w;
    private int depth;

    //Add constructors as needed
    public AttributeIndentingXmlTextWriter(TextWriter w)
        : base(w) 
    {
        this.w = w;
    }

    public override void WriteStartElement(string prefix, 
        string localName, string ns)    
    {
        depth ++;
        base.WriteStartElement(prefix, localName, ns);
    }

    public override void WriteFullEndElement()
    {
        depth--;
        base.WriteFullEndElement();
    }    

    public override void WriteEndElement()
    {
        depth--;
        base.WriteEndElement();
    }    

    public override void WriteStartAttribute(string prefix, 
        string localName, string ns)
    {
        if (base.Formatting == Formatting.Indented) 
        {   
            w.WriteLine();
            for (int i=1; i<Indentation*depth; i++)
                w.Write(IndentChar);
        }
        base.WriteStartAttribute(prefix, localName, ns);
    }
}
Usage:
XmlTextWriter w = 
  new AttributeIndentingXmlTextWriter(Console.Out);
w.Formatting = Formatting.Indented;
w.WriteStartDocument();
w.WriteStartElement("foo");
w.WriteAttributeString("attr1", "value1");
w.WriteAttributeString("attr2", "value2");
w.WriteAttributeString("attr3", "value3");
w.WriteStartElement("bar");
w.WriteAttributeString("attr1", "value1");
w.WriteAttributeString("attr2", "value2");
w.WriteAttributeString("attr3", "value3");
w.WriteString("some text");
w.WriteEndElement();
w.WriteEndElement();
w.WriteEndDocument();
The result is as follows:
<foo
  attr1="value1"
  attr2="value2"
  attr3="value3">
  <bar
    attr1="value1"
    attr2="value2"
    attr3="value3">some text</bar>
</foo>

Related Blog Posts

No TrackBacks

TrackBack URL: http://www.tkachenko.com/cgi-bin/mt-tb.cgi/333

Leave a comment