0

I need to read XML and deserialize it into an object in C#. I created the file with the serialization part of the ToXmlFile(Object obj, string filePath) function as given further down. I have the following XML created in the file test.xml:

<NYSE_Daily_Prices>
    <stock_exchange>NYSE</stock_exchange>
    <stock_symbol>ADI</stock_symbol>
    <date>2000-01-03T00:00:00</date>
    <stock_price_open>93.5</stock_price_open>
    <stock_price_high>93.87</stock_price_high>
    <stock_price_low>88</stock_price_low>
    <stock_price_close>90.19</stock_price_close>
    <stock_volume>3655600</stock_volume>
    <stock_price_adj_close>39.97</stock_price_adj_close>
  </NYSE_Daily_Prices>
  <NYSE_Daily_Prices>
    <stock_exchange>NYSE</stock_exchange>
    <stock_symbol>ADI</stock_symbol>
    <date>2000-01-04T00:00:00</date>
    <stock_price_open>89.5</stock_price_open>
    <stock_price_high>91.5</stock_price_high>
    <stock_price_low>85.56</stock_price_low>
    <stock_price_close>85.62</stock_price_close>
    <stock_volume>2533200</stock_volume>
    <stock_price_adj_close>37.95</stock_price_adj_close>
  </NYSE_Daily_Prices>
  <NYSE_Daily_Prices>
    <stock_exchange>NYSE</stock_exchange>
    <stock_symbol>ADI</stock_symbol>
    <date>2000-01-05T00:00:00</date>
    <stock_price_open>85.62</stock_price_open>
    <stock_price_high>88.25</stock_price_high>
    <stock_price_low>83.19</stock_price_low>
    <stock_price_close>86.88</stock_price_close>
    <stock_volume>3228000</stock_volume>
    <stock_price_adj_close>38.51</stock_price_adj_close>
  </NYSE_Daily_Prices>

Here is my object:

public partial class NYSE_Daily_Prices
    {
        public string stock_exchange { get; set; }
        public string stock_symbol { get; set; }
        public System.DateTime date { get; set; }
        public double stock_price_open { get; set; }
        public double stock_price_high { get; set; }
        public double stock_price_low { get; set; }
        public double stock_price_close { get; set; }
        public int stock_volume { get; set; }
        public double stock_price_adj_close { get; set; }
    }

And this is the code to serialize/deserialize it:

public static class XmlHelper
{
    public static bool NewLineOnAttributes { get; set; }
    /// <summary>
    /// Serializes an object to an XML string, using the specified namespaces.
    /// </summary>
    public static string ToXml(object obj, XmlSerializerNamespaces ns)
    {
        Type T = obj.GetType();

        var xs = new XmlSerializer(T);
        var ws = new XmlWriterSettings { Indent = true, NewLineOnAttributes = NewLineOnAttributes, OmitXmlDeclaration = true };

        var sb = new StringBuilder();
        using (XmlWriter writer = XmlWriter.Create(sb, ws))
        {
            xs.Serialize(writer, obj, ns);
        }
        return sb.ToString();
    }

    /// <summary>
    /// Serializes an object to an XML string.
    /// </summary>
    public static string ToXml(object obj)
    {
        var ns = new XmlSerializerNamespaces();
        ns.Add("", "");
        return ToXml(obj, ns);
    }

    /// <summary>
    /// Deserializes an object from an XML string.
    /// </summary>
    public static T FromXml<T>(string xml)
    {
        XmlSerializer xs = new XmlSerializer(typeof(T));
        using (StringReader sr = new StringReader(xml))
        {
            return (T)xs.Deserialize(sr);
        }
    }

    /// <summary>
    /// Deserializes an object from an XML string, using the specified type name.
    /// </summary>
    public static object FromXml(string xml, string typeName)
    {
        Type T = Type.GetType(typeName);
        XmlSerializer xs = new XmlSerializer(T);
        using (StringReader sr = new StringReader(xml))
        {
            return xs.Deserialize(sr);
        }
    }

    /// <summary>
    /// Serializes an object to an XML file.
    /// </summary>
    public static void ToXmlFile(Object obj, string filePath)
    {
        var xs = new XmlSerializer(obj.GetType());
        var ns = new XmlSerializerNamespaces();
        var ws = new XmlWriterSettings { Indent = true, NewLineOnAttributes = NewLineOnAttributes, OmitXmlDeclaration = true };
        ns.Add("", "");

        using (XmlWriter writer = XmlWriter.Create(filePath, ws))
        {
            xs.Serialize(writer, obj);
        }
    }

    /// <summary>
    /// Deserializes an object from an XML file.
    /// </summary>
    public static T FromXmlFile<T>(string filePath)
    {
        StreamReader sr = new StreamReader(filePath);
        try
        {
            var result = FromXml<T>(sr.ReadToEnd());
            return result;
        }
        catch (Exception e)
        {
            throw new Exception("There was an error attempting to read the file " + filePath + "\n\n" + e.InnerException.Message);
        }
        finally
        {
            sr.Close();
        }
    }
}

And the code I use to request the deserialization:

string filePath = $@"C:\Users\dmast\Documents\Upskilled\C#\C# Programming Project\MoneyBMineWpfApp\MoneyBMineWpfApp\OfflineFilesXML\{listRecentSearches.SelectedItem.ToString()}";
            NYSE_Daily_Prices result = XMLReadWrite.XmlHelper.FromXmlFile<NYSE_Daily_Prices>(filePath);

I keep getting the caught exception:

catch (Exception e)
                {
                    throw new Exception("There was an error attempting to read the file " + filePath + "\n\n" + e.InnerException.Message);
            }

Any help would be much appreciated :)

2
  • When throwing a new Exception (which should not be the base Exception class by the way) just put the actual exception as the inner exception. Now, what does the inner exception say? Commented Apr 18, 2020 at 20:15
  • The argument to throw includes e.InnerException.Message but you have not shown the output from that throw, not have you written code to show e.Message. Commented Apr 18, 2020 at 20:46

1 Answer 1

1

Davide. Your code looks fine to me. I tried it locally.

Are you sure, that you provide the right path to the file?

I changed a little xml, because I assume it should have a root element. Now .xml file looks like this:

<root>
  <Prices>
    <NYSE_Daily_Prices>
      <stock_exchange>NYSE</stock_exchange>
      <stock_symbol>ADI</stock_symbol>
      <date>2000-01-03T00:00:00</date>
      <stock_price_open>93.5</stock_price_open>
      <stock_price_high>93.87</stock_price_high>
      <stock_price_low>88</stock_price_low>
      <stock_price_close>90.19</stock_price_close>
      <stock_volume>3655600</stock_volume>
      <stock_price_adj_close>39.97</stock_price_adj_close>
    </NYSE_Daily_Prices>
    <NYSE_Daily_Prices>
      <stock_exchange>NYSE</stock_exchange>
      <stock_symbol>ADI</stock_symbol>
      <date>2000-01-04T00:00:00</date>
      <stock_price_open>89.5</stock_price_open>
      <stock_price_high>91.5</stock_price_high>
      <stock_price_low>85.56</stock_price_low>
      <stock_price_close>85.62</stock_price_close>
      <stock_volume>2533200</stock_volume>
      <stock_price_adj_close>37.95</stock_price_adj_close>
    </NYSE_Daily_Prices>
    <NYSE_Daily_Prices>
      <stock_exchange>NYSE</stock_exchange>
      <stock_symbol>ADI</stock_symbol>
      <date>2000-01-05T00:00:00</date>
      <stock_price_open>85.62</stock_price_open>
      <stock_price_high>88.25</stock_price_high>
      <stock_price_low>83.19</stock_price_low>
      <stock_price_close>86.88</stock_price_close>
      <stock_volume>3228000</stock_volume>
      <stock_price_adj_close>38.51</stock_price_adj_close>
    </NYSE_Daily_Prices>
  </Prices>
</root>

I created 1 more class Root:

    [XmlRoot("root")]
    public class Root
    {
        [XmlArray("Prices")]
        [XmlArrayItem("NYSE_Daily_Prices")]
        public List<NYSE_Daily_Prices> Prices { get; set; } = new List<NYSE_Daily_Prices>();
    }

Tested this code in console application, it works fine:

    class Program
    {
        static void Main(string[] args)
        {
            var deserializedObject = XmlHelper.FromXmlFile<Root>(Environment.CurrentDirectory + @"\file.xml");
        }
    }

enter image description here

I hope it helps!

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you Anna, you were right about adding the root element to the xml file. I didn't add a location for the debug files. After I did so I executed the code and the path was accepted but the xml file had an inner exception due to duplicate root elements. All is working well now :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.