Search code examples
c#xmlxml-deserialization

Is it possible to deserialize an xml into a dictionary without using linq-to-xml?


I'd like to deserialize an xml file. Here is the xml file in question :

<MessageList category="Alarm" version="1.0.0">
    <Item id="1">
        <Message key="Level" text="Alarm" />
        <Message key="Title" text="ERROR AT PLC UNIT" />
        <Message key="Detail" text="Change PLC unit. &#xD;&#xA;If it is out of order. please contact our service man." />
    </Item>
    <Item id="2">
        <Message key="Level" text="Alarm" />
        <Message key="Title" text="RE-SET PLC UNIT ( PROGRAM FS )" />
        <Message key="Detail" text="Turn off and restart. if the problem persists. check thet the switch on the controller is in RUN mode. &#xD;&#xA;If it is out of order. please contact our service man." />
    </Item>
    <Item id="3">
        <Message key="Level" text="Alarm" />
        <Message key="Title" text="" />
        <Message key="Detail" text="" />
    </Item>
    <Item id="4">
        <Message key="Level" text="Alarm" />
        <Message key="Title" text="" />
        <Message key="Detail" text="" />
    </Item>
    <Item id="5">
        <Message key="Level" text="Alarm" />
        <Message key="Title" text="" />
        <Message key="Detail" text="" />
    </Item>

Is it possible to deserialize an xml into a dictionary without using linq-to-xml? Hi, I'd like to deserialize an xml file. Here is the xml file in question I'd like to obtain two classes as shown below. A class linked to MessageList, which would contain all the other Items elements inside. As you'll have noticed, the items all have a unique id that represents them. So I'd like to use it as a dictionary key and contain the Message elements in a list as a dictionary value.

class MessageListClass
{
    public string category { get; set; }
    public string version { get; set; }
    public Dictionary<int, List<Message> > items { get; set; }
}
public class Message
{
    public string key { get; set; }
    public string text { get; set; }
}

For now, I've done it this way, using attributes from System.Xml.Serialization. It works well, but they're not dinctionaries. Is there a way to get a dinctionary like I'd like, using System.Xml.Serialization attributes and not Linq-to-Xml?

[XmlRoot("MessageList")]
    class MessageList
    {
        [XmlAttribute("category")]
        public string category { get; set; }
        [XmlAttribute("version")]
        public string version { get; set; }
        [XmlElement("Item")]
        public List<Item> items { get; set; }
    }
    public class Item
    {
        [XmlAttribute("id")]
        public int alarmId { get; set; }
        [XmlElement("Message")]
        public List<Message> messages { get; set; }
    }
    public class Message
    {
        [XmlAttribute("key")]
        public string key { get; set; }
        [XmlAttribute("text")]
        public string text { get; set; }
    }

Solution

  • I would suggest keeping separate models for serialization and other usages. This can help for cases like this where the models not exactly match. Classes dedicated for serialization are sometimes called "Data Transfer Object" or "DTOs".

    You can add a method to convert from one model to another:

    class MessageListDTO
    {
       [XmlAttribute("category")]
       public string Category { get; set; }
       [XmlAttribute("version")]
       public string Version { get; set; }
       [XmlElement("Item")]
       public List<ItemDTO> Items { get; set; }
    
       public MessageList ToModel(){
           return new MessageList(){
              Category = Category,
              Version = Version,
              Items = Items.ToDictionary(
                        i => i.AlarmId ,
                        i =>  i.Messages.Select(m => m.ToModel()).ToList())
        };
    }