81

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.

1

4 Answers 4

145
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 :)

Sign up to request clarification or add additional context in comments.

2 Comments

That's great! How would you access an attribute though? For example, after parsing a .nuspec file I should be able to navigate to the following nuspec.package.dependencies.dependency.@version but @version is not recognised.
Anton, attributes are prefixed with an '@'. Also see newtonsoft.com/json/help/html/ConvertingJSONandXML.htm. I normally cast the ExpandoObject to a Dictionary. The attribute is accessible through that dictionary with the '@<attributename>' key.
6

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;
    }
}

1 Comment

and how do I use this?
4

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.

Comments

2

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;
        }
    }
}

1 Comment

I have used this; it works very well providing dynamic names and values inside a dynamic object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.