Convert XML to Dynamic Object Using ExpandoObject

XML scheme is very different per setup. Using dynamic keyword to load an XML document across it is as a simple object. After some browsing, there are examples that used the ExpandoObject but 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 this method is a recursive method that loads XML document and converts it into a simple object.

 

Here’s 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
    if (!String.IsNullOrWhiteSpace(file))
    {
        var doc = XDocument.Load(file);
        node = doc.Root;
    }
    dynamic result = new ExpandoObject();
    var pluralizationService = System.Data.Entity.Design.PluralizationServices.
    PluralizationService.CreateService(CultureInfo.CurrentCulture);
    foreach (var gn in node.Elements())
    {
        // The code determines if it is a container node based on the child
        // elements with the same name. If there is only one child element,
        // then it uses the PluralizationService to determine if the pluralization of the child elements name 
        // matches the parent node. If so then it's most likely a collection 
        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
                (gn.Elements().First().Name.LocalName).ToLower()
            );
                    
        var p = result as IDictionary<String, dynamic>;
        var values = new List<dynamic>();
        // 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
        if (isCollection)
            foreach (var item in gn.Elements())
            {
                values.Add((item.HasElements) ? _getExpandoFromXml(null, item) :
                    item.Value.Trim());
            }
        else
            values.Add((gn.HasElements) ? _getExpandoFromXml(null, gn) :
                gn.Value.Trim());

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

Check out the rest of the code in this blog post: http://www.codeproject.com/Tips/227139/Converting-XML-to-an-Dynamic-Object-using-ExpandoO

Leave a Reply

Your email address will not be published. Required fields are marked *