Converting XML to a dynamic C# object

C#XmlJson

C# Problem Overview


I've used the following C# code to convert a string of JSON data to a dynamic object using the JSON.Net framework:

// Creates a dynamic .Net object representing the JSON data
var ProductDB = JsonConvert.DeserializeObject<dynamic>(JsonData);

Once converted, I can access the elements directly using code like this:

// Variables to be used
string ProductID;
string ProductType;
int ProductQty;

// Loop through each of the products
foreach (dynamic product in ProductDB.products)
{
    ProductID = product.id;
    ProductType = product.type;
    ProductQty = product.qty;
}

Is there anything similar to this for working with XML data? I could just use JSON.net to convert my XML to JSON and then re-use the code above, but that feels like cheating.

Thanks.

C# Solutions


Solution 1 - C#

XDocument doc = XDocument.Parse(xmlData); //or XDocument.Load(path)
string jsonText = JsonConvert.SerializeXNode(doc);
dynamic dyn = JsonConvert.DeserializeObject<ExpandoObject>(jsonText);

I think "cheating" is the answer - the xml solutions are very long :)

Solution 2 - C#

An alternative for future visitors, the one from ITDevSpace doesn't include attributes on elements with children.

public class XmlWrapper
{
	public static dynamic Convert(XElement parent)
	{
		dynamic output = new ExpandoObject();

		output.Name = parent.Name.LocalName;
		output.Value = parent.Value;

		output.HasAttributes = parent.HasAttributes;
		if (parent.HasAttributes)
		{
			output.Attributes = new List<KeyValuePair<string, string>>();
			foreach (XAttribute attr in parent.Attributes())
			{
				KeyValuePair<string, string> temp = new KeyValuePair<string, string>(attr.Name.LocalName, attr.Value);
				output.Attributes.Add(temp);
			}
		}

		output.HasElements = parent.HasElements;
		if (parent.HasElements)
		{
			output.Elements = new List<dynamic>();
			foreach (XElement element in parent.Elements())
			{
				dynamic temp = Convert(element);
				output.Elements.Add(temp);
			}
		}

		return output;
	}
}

Solution 3 - C#

Cinchoo ETL - an open source library available to parse xml into dynamic object

using (var p = ChoXmlReader.LoadText(xml).WithXPath("/"))
{
    foreach (dynamic rec in p)
        Console.WriteLine(rec.Dump());
}

Checkout CodeProject article for some additional help.

Disclaimer: I'm the author of this library.

Solution 4 - C#

From @FSX's answer I have successfully used the solution from "Parse XML to dynamic object in C#":

public class XmlToDynamic
{
    public static void Parse(dynamic parent, XElement node)
    {
        if (node.HasElements)
        {
            if (node.Elements(node.Elements().First().Name.LocalName).Count() > 1)
            {
                //list
                var item = new ExpandoObject();
                var list = new List<dynamic>();
                foreach (var element in node.Elements())
                {                        
                    Parse(list, element);                        
                }
 
                AddProperty(item, node.Elements().First().Name.LocalName, list);
                AddProperty(parent, node.Name.ToString(), item);
            }
            else
            {
                var item = new ExpandoObject();
 
                foreach (var attribute in node.Attributes())
                {
                    AddProperty(item, attribute.Name.ToString(), attribute.Value.Trim());
                }
 
                //element
                foreach (var element in node.Elements())
                {
                    Parse(item, element);
                }
 
                AddProperty(parent, node.Name.ToString(), item);
            }
        }
        else
        {
            AddProperty(parent, node.Name.ToString(), node.Value.Trim());
        }
    }
 
    private static void AddProperty(dynamic parent, string name, object value)
    {
        if (parent is List<dynamic>)
        {
            (parent as List<dynamic>).Add(value);
        }
        else
        {
            (parent as IDictionary<String, object>)[name] = value;
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionstuartmView Question on Stackoverflow
Solution 1 - C#HeatherDView Answer on Stackoverflow
Solution 2 - C#CrashMView Answer on Stackoverflow
Solution 3 - C#CinchooView Answer on Stackoverflow
Solution 4 - C#RMalkeView Answer on Stackoverflow