score:2

Formatting of XML output is controlled by XmlWriter not XElement or XDocument, so if you need precise control of formatting you will need to create your own writer by subclassing one of the implementations of XmlWriter, specifically XmlTextWriter whose Formatting property is mutable and can be changed during writing.

For instance, here is a version that disables indentation when the element depth exceeds 1:

public class CustomFormattingXmlTextWriter : XmlTextWriter
{
    readonly Stack<Formatting> stack = new Stack<Formatting>();

    public CustomFormattingXmlTextWriter(TextWriter writer, int indentDepth) : base(writer) 
    { 
        this.Formatting = Formatting.Indented; 
        this.IndentDepth = indentDepth;
    }
    
    int IndentDepth { get; }

    void OnElementStarted(string localName, string ns)
    {
        stack.Push(Formatting);
        // You could e.g. modify the logic here to check to see whether localName == CHILDELEMENT
        // if (localName == "CHILDELEMENT")
        if (stack.Count == IndentDepth+1)
            Formatting = Formatting.None;
    }

    void OnElementEnded()
    {
        var old = stack.Pop();
        if (old != Formatting)
            Formatting = old;
    }

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

    public override void WriteEndElement()
    {
        base.WriteEndElement();
        OnElementEnded();
    }
    
    public override void WriteFullEndElement()
    {
        base.WriteEndElement();
        OnElementEnded();
    }
}

public static partial class XNodeExtensions
{
    public static void SaveWithCustomFormatting(this XDocument doc, string filename, int indentDepth)
    {
        using (var textWriter = new StreamWriter(filename))
        using (var writer = new CustomFormattingXmlTextWriter(textWriter, indentDepth))
        {
            doc.Save(writer);
        }
    }
}

Using it, you can do:

myDoc.SaveWithCustomFormatting(fileName, 1);

which outputs, as required:

<ROOTELEMENT>
  <CHILDELEMENT><INFO1>Test a 1</INFO1><INFO2>Test a 2</INFO2></CHILDELEMENT>
  <CHILDELEMENT><INFO1>Test b 1</INFO1><INFO2>Test b 2</INFO2></CHILDELEMENT>
</ROOTELEMENT>

Notes:

  • You can modify the logic in CustomFormattingXmlTextWriter.OnElementStarted() to disable the formatting using any criteria you desire such as checking to see whether the incoming localName is CHILDELEMENT.

  • XmlTextWriter is deprecated in favor of XmlWriter -- but the latter does not have a mutable Formatting property. If you must needs use XmlWriter you might look at Is there a way to serialize multiple XElements onto the same line?.

Demo fiddle #1 here.


Related Articles