How I used LINQ to XML to Create Document Library Folders

Posted Thursday, January 17, 2008 5:29 PM by C-Dog's .NET Tip of the Day

I have been doing a lot of document library work lately and in my work I had a need to create a series of subfolders in the document library using a particular custom content type. This meant I was going to need to write a little code. I decided to keep the list of folders i needed to create in an XML document since this could easily represent the hierarchy I needed. I also need to set some properties on the content type as well as implement security on a per-folder level.

Well thinking about how my XML document was going to work out I started dreading navigating the XML document using the traditional .NET APIs. Let's face it. They are not fun to use. Looking for a better alternative, I decided to use LINQ to XML. I had heard about it but had not read anything on it yet, so I decided to look into it more. LINQ to XML gives you the power to get IntelliSense into your XML document using anonymous types. This turned out to make things a ton easier. To get started I used an XML document similar to the one below. My final version had some additional elements in it for my security settings, but I omited those for this example.

<DocumentLibrary>

  <Folder Name="Folder 1" ParentFolderType="" FolderType="">

    <Folder Name="Subfolder 1" ParentFolderType="Blah" FolderType="Blah"></Folder>

    <Folder Name="Subfolder 2" ParentFolderType="Blah" FolderType="Blah"></Folder>

  </Folder>

  <Folder Name="Folder 2" ParentFolderType="" FolderType=""></Folder>

  <Folder Name="Folder 3" ParentFolderType="" FolderType=""></Folder>

</DocumentLibrary>

This document is pretty simple. In this case I have a couple of folders with some nested subfolders. I also have some attributes that I was using to set custom properties on the content type. First, I am going to open up my XML file using the XDocument class. It has a constructor which takes a path to a file or URL among other things. I then use the Root property of the XDocument and call .Elements with a parameter of Folders. It naturally matches up all elements named Folder. Elements will return all elements of a given node. If you wanted all elements in the entire tree that matched you could call Descendants.

The next part of the LINQ query creates a new anonymous type. In my type, I copy over the values of a few attributes as well as get all child elemnts named Folder to get a list of subfolders. This is what I use to do recursion. Lastly I assign RoleMappings, but first I check to see if the value exists first using Any(). That along with the use of ? and : are the proper way to check for nulls. Also of note I am using the new var type to receive a collection of the anonymous type (again don't confuse these with the old VB6 variants). While debugging, you can see that this is actually an IEnumberable<XElement>.

// get the xml document from the feature folder

XDocument documentLibraryXml = XDocument.Load(folderStructureFilename);

 

// iterate through the root folder elements

var folders = from folder in documentLibraryXml.Root.Elements("Folder")

              select new

              {

                  Name = folder.Attribute("Name").Value,

                  FolderType = folder.Attribute("FolderType").Value,

                  ParentFolderType = folder.Attribute("ParentFolderType").Value,

                  SubFolders = folder.Descendants("Folder"),

                  RoleMappings = folder.Elements("Security").Any() ? folder.Element("Security").Elements("RoleMapping") : null

              };

At this point I have a nice anonymous type which provides full IntelliSense access to my XML. Now I just need to iterate on it. Inside my foreach, I call my methods to create my new SPFolder, set permissions, and then recursively call a method to create the subfolders. Things like folder.Name, folder.SubFolders all show up via IntelliSense.

So far I can say LINQ to XML has saved me a ton of time. This is a brief overview, ScottGu has a bit of info on LINQ to XML to help get you started. I think it is really powerful for any scenario where you are going to be working with a lot of XML. I didn't include any of the details about how I set security or created the folders themselves, but I have posted info on some of that in the past. If you need more info, feel free to contact me.

Read the complete post at http://www.dotnettipoftheday.com/blog.aspx?id=403