Using LINQ to Query Data in a Mindjet MindManager Map

As most of you may know by now, earlier this year I left Mindjet to join Microsoft.  Mindjet is a Microsoft Gold Certified partner who makes the mind mapping software MindManager.  Since I have been at Microsoft, I've been "drinking from the fire hose" and learning about many cool technologies; my challenge is to explain their relevance to my customers. 

LINQ (Language Integrated Query) is a new feature in C# 3.0 and integrated into Visual Studio 2008, which will be released in February 2008.  It allows for a very concise natural-language querying of data sets that is integrated with the Visual Studio 2008 Intellisense. 

Throughout the time that I was at Mindjet, we had requests for how the topics in Mindjet MindManager maps could be used as data sources for other applications.  I started the Mindjet Labs to show people how to do this.  Since the MindManager Map is stored as XML data inside the .mmap file (a zip archive), it is fairly easy to get at the data.  This is very similar to the rationale behind the Office Open XML File Formats that are in Office 2007.  The hard part comes in understanding the XML (it's a bit verbose).  After four years of working with it, when I see the MindManager XML I can visualize the map, similar to how Mouse in the film The Matrix could see the lady in the red dress through falling characters on a screen. Because the XSD schemas for each MindManager map are stored in the zip archive as well as the content, you have an exact description of the MindManager XML format within each .mmap file.  Using these schemas and the XSD.exe tool that comes with the .Net SDK, you can create C# or VB.Net classes that can be used to deserialize the MindManager XML using XMLSerializer in the .Net Framework.

XmlSerializer serializer = new XmlSerializer(typeof(Mindjet.MindManager.Map));

Mindjet.MindManager.Map map = serializer.Deserialize(zipStream) as Map;

Once I deserialize the Map, to make that Map work with LINQ, I need to get a collection of Topics in the map as an enumerable object: IEnumerable<Topic>.  I put the deserializing and code to return the collection of Topics into .Net assembly so anyone can use it; source code and binary are attached to this post.

The Query

In a MindManager Map, you can assign task priorities top any topic (the colored circles) and that information is stored in the XML data for each topic:

image

A sample query on this data might be to report how many of each priority topic is in the map.  In the simple map above, there are 3 priority1, 1 priority 2, and 3 priority 3 topics.  Using LINQ you would query the map like this:

class LINQtoMindManager

{

    public void QueryDemo()

    {

        MindManagerMap map = new MindManagerMap("test.mmap");

 

       var query = from topic in map.AllTopics

             where topic.Task != null && topic.Task.TaskPrioritySpecified

             group topic by topic.Task.TaskPriority into g

             select new { Priority = g.Key, Count = g.Count()};

 

         foreach (var result in query)

         {

              Console.WriteLine(result.Priority + ": " + result.Count);

         }

     }

}

That will then write the following results for the map pictured above:

urnmindjetPrio1: 3
urnmindjetPrio2: 1
urnmindjetPrio3: 3

What makes it easy is that LINQ can iterate or query over any collection that supports IEnumerable<> or IQueryable<>.  Feel free to download the source code for this MindManager Library and use it in your project!

MindManagerMapReader.zip