147
<StepList>
  <Step>
    <Name>Name1</Name>
    <Desc>Desc1</Desc>
  </Step>
  <Step>
    <Name>Name2</Name>
    <Desc>Desc2</Desc>
  </Step>
</StepList>

I have this XML, How should i model the Class so i will be able to deserialize it using XmlSerializer object?

user829174
  • 6,132
  • 24
  • 75
  • 125

2 Answers2

270

Your classes should look like this

[XmlRoot("StepList")]
public class StepList
{
    [XmlElement("Step")]
    public List<Step> Steps { get; set; }
}

public class Step
{
    [XmlElement("Name")]
    public string Name { get; set; }
    [XmlElement("Desc")]
    public string Desc { get; set; }
}

Here is my testcode.

string testData = @"<StepList>
                        <Step>
                            <Name>Name1</Name>
                            <Desc>Desc1</Desc>
                        </Step>
                        <Step>
                            <Name>Name2</Name>
                            <Desc>Desc2</Desc>
                        </Step>
                    </StepList>";

XmlSerializer serializer = new XmlSerializer(typeof(StepList));
using (TextReader reader = new StringReader(testData))
{
    StepList result = (StepList) serializer.Deserialize(reader);
}

If you want to read a text file you should load the file into a FileStream and deserialize this.

using (FileStream fileStream = new FileStream("<PathToYourFile>", FileMode.Open)) 
{
    StepList result = (StepList) serializer.Deserialize(fileStream);
}
NXT
  • 1,981
  • 1
  • 24
  • 30
dknaack
  • 60,192
  • 27
  • 155
  • 202
  • 1
    [XmlElement("Step")] is the key - to remove "step" nesting in XML (...) – avs099 May 09 '12 at 15:00
  • 1
    i don't understand. Sure `[XmlElement("Step")]` is the key, is right. What you mean with "- to remove "step" nesting in XML (...)". Thank you! – dknaack May 09 '12 at 15:03
  • 1
    it was not for you but for others who might be reading this answer :) if you do not have [XmlElement] then resulting XML will be like that: Name1Name2. It took me a while some time ago to figure out how to remove outer block. – avs099 May 09 '12 at 17:06
  • 1
    I tried without [XmlElement("Step")] in class and it is working – Shiko Sep 26 '16 at 09:10
  • Why do you use "using"? Is there any benefit in comparison with this aproach: XmlSerializer serializer = new XmlSerializer(typeof(StepList)); TextReader reader = new StringReader(testData); StepList result = (StepList) serializer.Deserialize(reader); – suchoss Sep 11 '17 at 19:13
  • 1
    @suchoss Yes, there are benefits of using "using". https://stackoverflow.com/a/26741192/466577 – Ahmed Ahmedov Aug 28 '18 at 20:40
  • @suchoss yes it guarantees cleanup of any object that is derived from IDisposable, in my personal experience, if I'm using anything that derives from IDisposable, I automatically calls .Dispose when it goes out of scope and ensures good cleanup of unmanaged resource. – Josh Jan 03 '19 at 15:02
  • This answer seems incomplete because when I use it with a class generated by pasting the XML into an empty class via Paste Special, I get Cannot deserialize type 'Sweeper365_DAL.OutboundEmailMessage' because it contains property 'message' which has no public setter. – David A. Gray Jul 01 '21 at 17:02
42

The comments above are correct. You're missing the decorators. If you want a generic deserializer you can use this.

public static T DeserializeXMLFileToObject<T>(string XmlFilename)
{
    T returnObject = default(T);
    if (string.IsNullOrEmpty(XmlFilename)) return default(T);

    try
    {
        StreamReader xmlStream = new StreamReader(XmlFilename);
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        returnObject = (T)serializer.Deserialize(xmlStream);
    }
    catch (Exception ex)
    {
        ExceptionLogger.WriteExceptionToConsole(ex, DateTime.Now);
    }
    return returnObject;
}

Then you'd call it like this:

MyObjType MyObj = DeserializeXMLFileToObject<MyObjType>(FilePath);
Morteza Jalambadani
  • 2,190
  • 6
  • 21
  • 35
Jay M
  • 979
  • 1
  • 12
  • 23