Yesterday I had an interesting task. I needed to parse a collection of XML files in C# and wondered if there’s an easy way to just access the data without all the XPath/XML fuzz.
After some research I found a couple of approaches and I mixed and matched them to a pretty simple one using dynamic and the ExpandoObject:
You will need these namespaces:
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Dynamic;
using System.Xml.Linq;
This little helper function:
public static dynamic ConvertXmlStringToDynamic(string
{
XDocument doc = XDocument.Parse(xmlData);
string jsonText = JsonConvert.SerializeXNode(doc);
jsonText = jsonText.Replace(""@", """);
jsonText = jsonText.Replace(""#text"", ""text"");
var converter = new ExpandoObjectConverter();
return JsonConvert.DeserializeObject<ExpandoObject>(jsonText, converter);
}
I first create an XDocument which then gets converted to a json string using JsonConvert.SerializeXNode. The json string will then be deserialized into an ExpandoObject. Very hacky but works great with two caveats: The two replace methods are kind of hacky because the resulting keys in the ExpandoObject for XML attributes are prefixed with an @ character and the key of an XML element content is #text. This makes it impossible to access using their property names. So I simply hacked it by replacing those in the json string before I convert it. This can be dangerous! Double-check if nothing else got replaced by this by mistake!
Once you got your dynamic, you can simply access the data from your XML like this:
<?xml version="1.0" encoding="utf-8"?>
<Node1 Attribute1="test" Attribute2="another test">
<SubNode1 SomeMoreAttributes="again" />
<SubNode2>
Some element text
</SubNode2>
</Node1>
var sampleFile = @"C:some-file.xml";
var sampleXml = File.ReadAllText(sampleFile);
var data = Converter.ConvertXmlStringToDynamic(sampleXml);
var attribute1 = data.Node1.Attribute1;
var someMoreAttribute = data.Node1.SubNode1.SomeMoreAttributes;
var elementText = data.Node1.SubNode2.text;
The above served me well. Maybe there’s a simpler or better solution and if so, I’m happy to hear about it!
Photo by Pankaj Patel on Unsplash
Co-Founder and CEO of Royal Apps GmbH and Windows lead developer for Royal TS, a multi platform, multi protocol remote management solution, for Windows, macOS and mobile supporting RDP, VNC, SSH, Telnet, and many more.
Long time Microsoft MVP (2010-2020) supporting communities on- and offline as well as speaking at user groups and conferences about DevOps and other software development topics.