How to deserialize xml to object

271,148

Solution 1

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);
}

Solution 2

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);
Share:
271,148
user829174
Author by

user829174

Updated on February 23, 2021

Comments

  • user829174
    user829174 over 3 years
    <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?

  • avs099
    avs099 about 12 years
    [XmlElement("Step")] is the key - to remove "step" nesting in XML (<Step><Step><Name>...)
  • dknaack
    dknaack about 12 years
    i don't understand. Sure [XmlElement("Step")] is the key, is right. What you mean with "- to remove "step" nesting in XML (<Step><Step><Name>...)". Thank you!
  • avs099
    avs099 about 12 years
    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: <Step><Step><Name>Name1</Name><Step><Name>Name2</Name></Step‌​></Step>. It took me a while some time ago to figure out how to remove outer <Step> block.
  • Shiko
    Shiko almost 8 years
    I tried without [XmlElement("Step")] in class and it is working
  • suchoss
    suchoss almost 7 years
    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);
  • Ahmed Ahmedov
    Ahmed Ahmedov almost 6 years
    @suchoss Yes, there are benefits of using "using". stackoverflow.com/a/26741192/466577
  • Josh
    Josh over 5 years
    @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.
  • David A. Gray
    David A. Gray almost 3 years
    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.