Click here to Skip to main content
13,559,019 members
Click here to Skip to main content
Add your own
alternative version


39 bookmarked
Posted 18 Jul 2011
Licenced CPOL

Converting XML to an Dynamic Object using ExpandoObject

, 11 Aug 2014
Rate this:
Please Sign up or sign in to vote.
Load an XML document and convert it to a dynamic object


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.

System.Data.Entity.Design.PluralizationServices; (
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.

The Code

private static dynamic _getExpandoFromXml(String file, XElement node = null)
    if (String.IsNullOrWhiteSpace(file) && node == null) return null;
    // If a file is not empty then load the xml and overwrite node with the
    // root element of the loaded document
    node = !String.IsNullOrWhiteSpace(file) ? XDocument.Load(file).Root : node;

    IDictionary<String, dynamic> result = new ExpandoObject();

    // implement fix as suggested by [ndinges]
    var pluralizationService = 

    // use parallel as we dont really care of the order of our properties
    node.Elements().AsParallel().ForAll(gn =>
        // Determine if node is a collection container
        var isCollection = gn.HasElements  &&
                // if multiple child elements and all the node names are the same
                gn.Elements().Count() > 1 && 
                    e => e.Name.LocalName.ToLower() == gn.Elements().First().Name.LocalName) ||
                // if there's only one child element then determine using the PluralizationService if
                // the pluralization of the child elements name matches the parent node. 
                gn.Name.LocalName.ToLower() == pluralizationService.Pluralize(
        // If the current node is a container node then we want to skip adding
        // the container node itself, but instead we load the children elements
        // of the current node. If the current node has child elements then load
        // those child elements recursively
        var items = isCollection ? gn.Elements().ToList() : new List<XElement>() { gn };

        var values = new List<dynamic>();

        // use parallel as we dont really care of the order of our properties
        // and it will help processing larger XMLs
        items.AsParallel().ForAll(i => values.Add((i.HasElements) ? 
           _getExpandoFromXml(null, i) : i.Value.Trim()));

        // Add the object name + value or value collection to the dictionary
        result[gn.Name.LocalName] = isCollection ? values : values.FirstOrDefault();
    return result;

Example XML

<?xml version="1.0"?>
    <RegisteredUser>Remco Reitsma</RegisteredUser>
            <Name>SEO Package</Name>


dynamic license = _getExpandoFromXml('path to xml file');

// Getting the values from the dynamic object is really easy now.
var registeredUser = license.RegisteredUser;
var companyName = license.Company;

// Getting a collection is just as easy as it simply returns a list
var sites = license.Sites;
foreach(var site in sites)
   var host = site.Host;

// I am sure it's easy enough for you guys to extrapolate from this simple example.


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.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Netherlands Netherlands
No Biography provided

You may also be interested in...


Comments and Discussions

QuestionAttributes for the XML nodes Pin
Nikhil Pakki19-Mar-18 23:32
memberNikhil Pakki19-Mar-18 23:32 
QuestionBug on non US English Systems and "Fix" Pin
ndinges11-Aug-14 8:51
memberndinges11-Aug-14 8:51 
AnswerRe: Bug on non US English Systems and "Fix" Pin
RemcoReitsma13-Sep-14 9:41
memberRemcoReitsma13-Sep-14 9:41 
GeneralMy vote of 4 Pin
thund3rstruck7-Aug-14 7:15
memberthund3rstruck7-Aug-14 7:15 
GeneralMy vote of 5 Pin
Some D00d7-Aug-14 4:35
memberSome D00d7-Aug-14 4:35 
GeneralReally a good one Pin
vikashevs5-Aug-13 3:24
membervikashevs5-Aug-13 3:24 
QuestionSerialization Pin
BnR-Fouress13-Dec-12 1:56
memberBnR-Fouress13-Dec-12 1:56 
GeneralReally good stuff! but is not taking account of node attribu... Pin
Rinaldo J. Sassaroli13-Feb-12 13:26
memberRinaldo J. Sassaroli13-Feb-12 13:26 
GeneralRe: Really good stuff!but is not taking account of node attribu... Pin
alexquisi29-Nov-15 23:28
memberalexquisi29-Nov-15 23:28 
GeneralRe: Really good stuff!but is not taking account of node attribu... Pin
DaveKolb30-Apr-16 7:45
memberDaveKolb30-Apr-16 7:45 
GeneralHow do I use the object once created? Like added values into... Pin
Member 83291237-Nov-11 9:14
memberMember 83291237-Nov-11 9:14 
GeneralRe: I have added a small example to the article which would help... Pin
RemcoReitsma14-Dec-11 16:17
memberRemcoReitsma14-Dec-11 16:17 
GeneralAre you missing the keyword dynamic in your var p = result... Pin
cechode18-Jul-11 10:13
membercechode18-Jul-11 10:13 
GeneralRe: Hmm something got messed up during copy and paste because fo... Pin
RemcoReitsma18-Jul-11 15:49
memberRemcoReitsma18-Jul-11 15:49 
GeneralRe: Don't forget to vote up if you like the tip ;-) Pin
RemcoReitsma14-Dec-11 19:28
memberRemcoReitsma14-Dec-11 19:28 
GeneralReason for my vote of 2 code produced a stackover flow excep... Pin
cechode18-Jul-11 6:13
membercechode18-Jul-11 6:13 
GeneralRe: I've updated and simplified the code. There was indeed a bug... Pin
RemcoReitsma18-Jul-11 9:02
memberRemcoReitsma18-Jul-11 9:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.180515.1 | Last Updated 11 Aug 2014
Article Copyright 2011 by RemcoReitsma
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid