I started looking on the Internet to find a straightforward way of loading in an XML file and converting it to an object on the fly. My goal was to dynamically load setting files in XML format for a web project I'm working on.
As the definition of the XML schema is very different per setup I thought of using the
dynamic keyword to load an XML document and access it as a simple object. After some browsing, I found some examples that used the
ExpandoObject. Unfortunately, they all either write about converting an object to XML or how to use XML-to-LINQ to map a specific dynamic class/object.
So I ended up writing a small recursive method that loads an XML document and converts it to a simple object.
I've noticed that even after 3 years, people are still finding this tip useful.
I thought it would be a good idea to share a small update which removes the need for a special type attribute to determine if a child node is part of a collection.
I suddenly realized that the feature I so hated and dreaded in Entity Framework could well be the solution I was looking for to remove the need to decorate my nodes with type=list attributes.
The feature I am talking about is pluralization. It's where in EF, we have a model with a class called
Course which automagically changed in a database table could
Courses. After some Googling, I came across the following little gem.
It allows for a
string to be pluralized or singularized. Then, I thought that this would fit very well in determining if a child element is part of a collection because often, if not always, the parent node name is a pluralization of its children's name.
Anyway, I've changed the logic that it will determine if a node is a container item if it has child elements that meet the following conditions:
- The item has 1 child element and its node name is a singularization of its parents name, or;
- The item has multiple child elements, but the child node names must all be the same.
I believe this will cover most of the scenarios and removes any need to have special type=list attributes.
private static dynamic _getExpandoFromXml(String file, XElement node = null)
if (String.IsNullOrWhiteSpace(file) && node == null) return null;
var doc = XDocument.Load(file);
node = doc.Root;
dynamic result = new ExpandoObject();
var pluralizationService = System.Data.Entity.Design.PluralizationServices.
foreach (var gn in node.Elements())
var isCollection = gn.HasElements &&
gn.Elements().Count() > 1 && gn.Elements().All
(e => e.Name.LocalName.ToLower() == gn.Elements().First().Name.LocalName) ||
gn.Name.LocalName.ToLower() == pluralizationService.Pluralize
var p = result as IDictionary<String, dynamic>;
var values = new List<dynamic>();
foreach (var item in gn.Elements())
values.Add((item.HasElements) ? _getExpandoFromXml(null, item) :
values.Add((gn.HasElements) ? _getExpandoFromXml(null, gn) :
p[gn.Name.LocalName] = isCollection ? values : values.FirstOrDefault();
dynamic license = _getExpandoFromXml('path to xml file');
var registeredUser = license.RegisteredUser;
var companyName = license.Company;
var sites = license.Sites;
foreach(var site in sites)
var host = site.Host;
One thing that is important to realize is that this is a very simple example and is by no means fool-proof. The code as it is would be useful in cases where you have control over the XML files that are provided. Also the use of
dynamic has some performance issues as internally it will need to do a lot of reflection during run time and you will also lose out on error checking of the dynamic objects during compiling.
It could be useful for example to read in a configuration file or a simple list of products.