Monday, October 19, 2009

Remove all empty XML elements using LINQ

While working on the XamlWriter I had to do some post processing on the generated Xaml. One was to delete all nodes that did not have any attributes or contain any elements. The first pass of removing the empty nodes could generate more empty nodes and hence this problem is recursive in nature.

This was my first attempt
var query = doc.Descendants().Where(c => !c.HasAttributes && c.IsEmpty);
while (query.Count())
   query.Remove();

This could be certainly improved using the .Any operator

var query = doc.Descendants().Where(c => !c.HasAttributes && c.IsEmpty);
while (query.Any())
   query.Remove();

The problem with the above solution(s) is that the query is executed twice, once for the Any/Count method and once for the Remove method. The next approach provided 2x performance gains (in the best case scenario) over the above approach

void RemoveEmptyNodes(XElement root)
{
   var query = root.Descendants().Where(e => !e.HasAttributes && e.IsEmpty).ToList();
   query.Remove();
   if (query.Any())
      RemoveEmptyNodes(root);
}

The reason for the performance improvement is that although both the Any and the Remove operations are executed on the query, the .ToList operator executes and caches the result and hence the query is executed only once.

The concern I have with the above recursive solution is the memory requirement for the local variable query which is of type IEnumerable.

Maybe something like this will help but I don't understand GC (garbage collection) in .NET well enough to recommend this approach

void RemoveEmptyNodes(XElement root)
{
   var query = root.Descendants().Where(e => !e.HasAttributes && e.IsEmpty).ToList();
   query.Remove();
   if (query.Any())
   {
      query = null;
      RemoveEmptyNodes(root);
   }
}

Anyone with better or alternate approaches please post your thoughts as comments.

2 comments:

Mehran Toosi said...

Hi Wilfred,
really nice work!
I had intended to do this, but never got the time! (university, work,... you know :-)) but I'm so happy that finally some one else decided to create the xaml writer.
I believe that most of the silverlight developers will enjoy your useful work.

Wilfred Pinto said...

Mehran,

Your code got me started so a big thanks to you.

Wilfred