Quantum_Kernel
Quantum_Kernel

Reputation: 333

C# parse XML file to object

Using C#, is there a way to easily parse an XML file so that it can be used as an object?

Example XML:

<Config>
    <Ui>
        <Colour>black</Colour>
        <Size>small</Size>
    </Ui>
    <Output>
        <Mode>smb</Mode>
        <Version>2</Version>
    </Output>
</Config>

And then refer to the parameters in my application by

Config.Output.Mode

I've tried this method - How to Deserialize XML document

But when I try

var cfg = new Config();
cfg.Load(@"config.xml");
Console.WriteLine(cfg.Output.Mode);

visual studio indicates .Output.Mode is not valid.

Where Config.Load is

xmlData = File.ReadAllText(configPath);
    
var serializer = new XmlSerializer(typeof(Config));
    
using (var reader = new StringReader(xmlData))
{
    Config result = (Config)serializer.Deserialize(reader);
}

Upvotes: 1

Views: 22136

Answers (2)

Jacob Seleznev
Jacob Seleznev

Reputation: 8131

Here are the classes:

public class Config
{
    public UI UI { get; set; }
    public Output Output { get; set; }
}

public struct UI
{
    public string Colour { get; set; }
    public string Size { get; set; }
}

public struct Output
{
    public string Mode { get; set; }
    public int Version { get; set; }
}

The Deserialize function:

    public static T Deserialize<T>(string xmlString)
    {
        if (xmlString == null) return default;
        var serializer = new XmlSerializer(typeof(T));
        using (var reader = new StringReader(xmlString))
        {
            return (T) serializer.Deserialize(reader);
        }
    }

And here's a working version:

        Config cfg = Deserialize<Config>(xmlString);
        Console.WriteLine(cfg.Output.Mode);          

Upvotes: 5

Rufus L
Rufus L

Reputation: 37020

You have to create the classes that match the definition in the xml file in order to deserialize the file into an instance of the class. Note that I've named the properties with the same name as we have in the xml file. If you want to use different property names, then you'd need to add an attribute above the property that specifies the xml element that should map to it (like for the Ui, you would add the attribute: [XmlElement("Ui")]).

Note that I've also overridden the ToString methods for the classes so we can output them to the console in a nice fashion:

public class Config
{
    public UI Ui { get; set; }
    public Output Output { get; set; }

    public override string ToString()
    {
        return $"Config has properties:\n - Ui: {Ui}\n - Output: {Output}";
    }
}

public class UI
{
    public string Colour { get; set; }
    public string Size { get; set; }

    public override string ToString()
    {
        return $"(Colour: {Colour}, Size: {Size})";
    }
}

public class Output
{
    public string Mode { get; set; }
    public int Version { get; set; }

    public override string ToString()
    {
        return $"(Mode: {Mode}, Version: {Version})";
    }
}

Now all we have to do is create a StreamReader, point it to our file path, and then use the XmlSerializer class to Deserialize the file (casting the output to the appropriate type) into an object:

static void Main(string[] args)
{
    var filePath = @"f:\private\temp\temp2.txt";

    // Declare this outside the 'using' block so we can access it later
    Config config;

    using (var reader = new StreamReader(filePath))
    {
        config = (Config) new XmlSerializer(typeof(Config)).Deserialize(reader);
    }

    Console.WriteLine(config);

    GetKeyFromUser("\n\nDone! Press any key to exit...");
}

Output

enter image description here

Upvotes: 9

Related Questions