Determining the Relative Path in XLinq with Extension Methods
In Titan, I’m edging closer and closer to releasing a beta 1 for public consumption and one of the tasks that I’m working on to get me there is a lazy-loading folder browser dialog box that enables you to browse through the folder structure of a particular service without having to load the whole folder structure in one go. This is used specifically for specifying new service configurations and is of particular concern for the local file system provider. Have you ever tried to retrieve your whole hard disk structure in one go!?
My service methods were already using some XLinq to parse the XML response from the Box.net service call and the local file system provider, but for the Box.net service provider I needed a way of finding a particular folder based on it’s relative path. The contents of a fictitious Box.net folder structure could look like the following XML example.
folder id="0" name="" shared="0">tags>tags>files>files>folders>folder id="4384" name="Incoming" shared="0">tags>tag id="34" />tags>files>file id="68736" filename="cows.w3g" keyword="" shared="0" size="232386" created="1129537520" updated="1129537520">tags>tags>file>file id="68737" filename="silver.html" keyword="" shared="0" size="15805" created="1129537520" updated="1129537520">tags>tag id="35" />tags>file>files>folders>folder id="1234" name="Test" shared="0">folders>folder id="2345" name="wibble" shared="0">folders />folder>folder id="5432" name="wobble" shared="0">folders />folder>folders>folder>folder id="4321" name="Test2" shared="0">folders />folder>folders>folder>folders>folder>
So, if I want to retrieve the folder contents of the folder named Test, which has a relative path of “IncomingTest”, how do I find that in XLinq? Well, I looked at all kinds of different approaches using the Descendants and Ancestors methods, but none of them managed to produce the goods, because I needed a single string that I could compare against.
To solve the problem I decided to use an extension method to produce a single string from a collection. The results of an XLinq query are IEnumerable
This didn’t quite solve the problem, because for my scenario described above, this produces a single string of “IncomingTest”, which isn’t quite a relative path. So, I added an overload for the method that accepts a string separator to produce the following.
So, my final XLinq query that builds up the relative path and returns me the folders for a specific relative path looks like the following code example, where
relativePath is a string parameter to the method that specifies the relative path to the folder that I want to retrieve the child folders.
var query = (from d in xRoot.DescendantsAndSelf("folder") where "" + (from a in d.AncestorsAndSelf("folder") select a.Attribute("name").Value).Reverse().ToOneString("") == relativePath select d.Element("folders").Elements("folder")).First();
If there are any folders in the specified folder, then I can enumerate the resulting XElement collection and build up instances of my