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:
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.
Mehran,
Your code got me started so a big thanks to you.
Wilfred
Post a Comment