FreeMind Conversion With C# & LINQPad

So I’ve recently been put on a project that requires me to investigate the source code for a bunch of existing applications and provide recommendations/estimates for updating them to include some new functionality. In order to accomplish this, I have to somehow organize my thoughts/notes in such a way that I can provide estimates for the amount of work it would be to perform the upgrades. In this particular case, there are 3 small .Net 2.0 (C#) applications and one beast of a C++ application.

My approach is generally to go through the code at a reasonably high level, taking as many notes as I can about what I see. Generally, this works out to be pretty high level observations about how things are organized, how coupled the classes may be, how many hard-coded values there are that may cause problems when trying to extend components. Things like that.

After I’ve got that, and I have a basic understanding of how the solutions behave/work (along with an understanding of what the upgrades are going to be) I can start to break down the upgrade details into manageable pieces. These pieces are small enough that I can hold all the different things that would need to change in my head at once (in general). This way (even though we all know how flawed estimation can be) I can give at least a somewhat reasonable guess as to the amount of work involved.

This may be a function of how I think but I have found that I tend to conceive of these tasks in a hierarchical fashion. That is to say, I start at a high level piece of functionality (user logins for example) and break it down into more pieces. For example if the task was to add profile pictures to users for a web application, that may involve file uploads, file type validation, or fetching the user photo from a service like Gravatar.

In order to keep track of all this, I have found that mind-mapping tools are a great help. On my last few projects where I have been doing this sort of estimation work, I have used the open source tool FreeMind (which I have become very fond of). It allows you to create the hierarchy of ideas in a navigable tree structure very easily and quickly.

Example Mind Map

Example Mind Map

You can easily navigate between nodes (using the arrow keys), insert a new sibling node (enter) or insert a child node (insert), all using the keyboard. Holding down ctrl and using the arrow keys lets you move nodes around as well.

This is great for getting your thoughts in order but eventually you are going to have to transfer these ideas into some other tool, be it excel or some sort of ticketing system. For this project our estimates are all going into a series of spreadsheets, so I need a nice way to get a flattened view of this data while still preserving the hierarchical information. For another project, I wanted to parse out some additional information I had encoded in the node text (such as estimated hours) and upload the nodes as tickets to the ticketing system we use at work (Assembla).

Since the FreeMind file format (.mm) is just an xml document, it is quite easy to parse this information and programmatically do what you want with it. In a past project, I parsed the XML file in a C# application which I then used to make web requests to create tickets in Assembla with the information I wanted. This was quite convenient since once you get a mind map with over 200 nodes, no one wants to enter that into a ticketing system by hand*. The way I did that was pretty cavalier and quite an ugly mess so I’d like to clean that up a bit.

What I have done for my current project is just utilized the amazing tool LINQPad to write some C# queries to parse the FreeMind file and generate a tab-indented text file (the tabs indicating the hierarchy) that I can then copy into excel and visually represent my hierarchy of ideas. If you don’t know what LINQPad is I would suggest you go check it out, it’s a a really handy tool for writing quick little C# snippets/programs/LINQ queries.

I use XML parsing facilities built into .Net (XDocument, XElement, etc.) and a couple simple classes and LINQ queries to build a set of nested “Node” objects which contain the text for the node and a child collection of nodes (providing the hierarchy). Running the code on the mind map featured previously yields a tab indented structure similar to the following:

User Profile Pictures

Select Image From Gallery

Retrieve Images From Server
Display Gallery
Associate Gallery Image With Profile

Upload Image From Computer

Upload File
Save File To Profile Data

Use Gravatar Image

Choose Email For Gravatar Image
Load Image From Generated Gravatar URL

The code that I used to generate this example is as follows:

void Main()
var outputPath = "Something.txt";
var inputPath = "";
var nodes = LoadFromFile(inputPath);
var lines = nodes.SelectMany(x => GetPrefixedString(x,""));
static IEnumerable<string> GetPrefixedString(Node node, string prefix){
prefix += "\t";
var nodeString = prefix + node.Text;
return nodeString
.Concat(node.Children.SelectMany(x => GetPrefixedString(x,prefix)));
static IEnumerable<Node> LoadFromFile(string filePath){
var xdoc = XDocument.Load(filePath);
var root = xdoc.Root;
if(root != null){
return root.Elements("node").Select(CreateNode);
return Enumerable.Empty<Node>();
static Node CreateNode(XElement element){
var text = "";
var textAttribute = element.Attribute("TEXT");
if(textAttribute != null){
text = textAttribute.Value;
return new Node(text){ Children = element.Elements("node").Select(CreateNode) };
class Node{
public string Text{get;set;}
public IEnumerable<Node> Children {get;set;}
public Node(string text){
Text = text;
Children = Enumerable.Empty<Node>();
public static class MyExtensions
public static IEnumerable<T> Unit<T>(this T item){
yield return item;

view raw


hosted with ❤ by GitHub

Now what I would like to be able to do is generalize the parsing of the mind map and the processing of the node hierarchy in such a way that it can be used for multiple applications. I need to think on it a little more about how exactly I am going to do that but I anticipate a future blog post once I am able to wrap my head around it. Hopefully I can release a nice compact library that people can easily use (that will probably have to wait until after my vacation).

*It should be noted that you can upload a csv file or something similar to the Assembla website, however, it isn’t possible to include ticket relationships (parent/child structure) as far as I am aware.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s