mac
mac

Reputation: 504

Deserialzing Xml into List<T> with C#

I am having trouble deserializing xml into a class that contains a list. Everything builds fine in the object until it gets to the list. I have read all the posts here and tried pretty much everything but it still seems to crap out.

XML: ("text.xml")

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<example>
   <id>123456</id>
      <messages>
         <message>
            <words>Hello</words>
         </message>
         <message>
            <words>world</words>
         </message>
      </messages>
</example>

Code:

 static void Main(string[] args) {
     try {
        XmlSerializer serializer = new XmlSerializer(typeof(Example));


        XmlDocument objDoc = new XmlDocument();
        objDoc.Load("test.xml");

        XmlReader reader = XmlReader.Create(new StringReader(objDoc.OuterXml));

        Example example;

        example = (Example)serializer.Deserialize(reader);
        Console.WriteLine(example.Id.ToString());
        Console.WriteLine(example.Messages.Count.ToString());
        Console.WriteLine(example.Messages[0].Words);
     }
     catch(Exception ex) {
        Console.Write(ex.Message);
     }
     Console.ReadLine();

  }

  [XmlRoot("example")]
  public class Example {
     [XmlElement("id")]
     public int Id {
        get {
           return id;
        }
        set {
           id = value;
        }
     }
     private int id;

     [XmlElement("messages")]
     public List<Message> Messages {
        get {
           return messages;
        }
        set {
           messages = value;
        }
     }
     private List<Message> messages;
  }

  [XmlRoot("message")]
  public class Message {
     [XmlElement("words")]
     public string Words {
        get {
           return words;
        }
        set {
           words = value;
        }
     }
     private string words;
  }

Output:

123456

1

Am I missing at tag somewhere that the Serializer needs? Or is what I'm trying to accomplish not possible? Any pointers or shove in the right direction is greatly appreciated.

Upvotes: 1

Views: 68

Answers (3)

jdweng
jdweng

Reputation: 34421

Try this

  [XmlRoot("example")]
  public class Example {
     [XmlElement("id")]
     public int Id { get; set;}

     [XmlElement("messages")]
     public Message messages {get; set;}
  }
  [XmlRoot("messages")]
  public class Messages {
     [XmlElement("message")]
     public List<Message> message { get; set;}

  }
  [XmlRoot("message")]
  public class Message {
     [XmlElement("words")]
     public string Words { get; set;}

  }​

Upvotes: 1

Jonesopolis
Jonesopolis

Reputation: 25370

I could see why you're confused. You're object structure doesn't match your XML though. You have a single messages node, and that node contains the list. So the structure really looks like:

[XmlRoot("example")]
public class Example
{
     [XmlElement("id")]
     public int Id { get; set; }

     [XmlElement("messages")]
     public Messages Messages { get; set; }
}

public class Messages
{
    [XmlElement("message")]
    public List<Message> Message { get; set; }
}

public class Message
{
    [XmlElement("words")]
    public string Words { get; set; }
}

runningg your code against that structure gets you the right output.

Upvotes: 1

will
will

Reputation: 38

Try this out:

Notice the definition of XmlArray and XmlArraItem. I'm sure someone else will have a better way but this will get it working. Also, you should use the 'using' statement to dispose of the xml reader.

public class Program
{
    public static void Main(string[] args)
    {
        try
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Example));

            using (XmlReader reader = XmlReader.Create("test.xml"))
            {

                Example example = (Example)serializer.Deserialize(reader);
                Console.WriteLine(example.Id.ToString());
                Console.WriteLine(example.Messages.Count.ToString());
                Console.WriteLine(example.Messages[0].Words);
            }
        }
        catch (Exception ex)
        {
            Console.Write(ex.Message);
        }
        Console.ReadLine();

    }

    [XmlRoot("example")]
    public class Example
    {
        [XmlElement("id")]
        public int Id
        {
            get
            {
                return id;
            }
            set
            {
                id = value;
            }
        }
        private int id;

        [XmlArray("messages")]
        [XmlArrayItem("message", typeof(Message))]
        public List<Message> Messages
        {
            get
            {
                return messages;
            }
            set
            {
                messages = value;
            }
        }
        private List<Message> messages;
    }

    [XmlRoot("message")]
    public class Message
    {
        [XmlElement("words")]
        public string Words { get; set; }
    }

Upvotes: 2

Related Questions