-1

I have an existing XML document that I am trying to map to a C# class.

I also created a unit test to ensure that the XML is being deserialized propertly.

However, the unit test is failing when expecting to have a count of 2 for PageName elements. When I debug, I see that the PageName element count is 0. Also in the debug view, the individual DeskBroker.Broker elements have 0 count as well.

Not sure if I am setting the XML attributes correctly. Can someone please review my work and see if I am using the correct annotations? I am sure I am missing something.

Thank you.

This is the XML:

<?xml version="1.0" encoding="utf-8"?>
<User>
 <FavoriteQuotePages>
  <Group name="Default">
   <PageName>NG Options</PageName>
   <PageName startdate="today" enddate="today">NG Options</PageName>
  </Group>
  <Group name="CUSTOM PAGES">
   <PageName sourcepagename="NG Options" daterange="TopDay" startdate="today" enddate="today" customfilters="[{&quot;fieldName&quot;:&quot;BidBOEName&quot;, &quot;expr&quot;:&quot;ION&quot;, &quot;cond&quot;:&quot;contains&quot;}]">ION ONLY</PageName>
   <PageName sourcepagename="NG Options" daterange="TopDay" startdate="today" enddate="today" customfilters="[{&quot;fieldName&quot;:&quot;BidBOEName&quot;, &quot;expr&quot;:&quot;CNG&quot;, &quot;cond&quot;:&quot;contains&quot;}]">CIE Only</PageName>
  </Group>
 </FavoriteQuotePages>
 <LayoutSettings>
  <PageDialog id="1" dialogname="market-page-dialog" modelname="MarketPageModel" viewname="_MarketPage" modelkey="" positionx="238.9965362548828" positiony="76.48611450195312" width="1275" height="650" />
 </LayoutSettings>
 <QuoteDefaults Product="NATURAL GAS">
  <ClearingEntities>
   <ID>12</ID>
  </ClearingEntities>
  <Quantity>100</Quantity>
  <ReserveQty></ReserveQty>
  <Timer>3</Timer>
  <DeskBrokers>
   <DeskBroker Desk="2366">
    <Broker Primary="False">2368</Broker>
   </DeskBroker>
   <DeskBroker Desk="2456">
    <Broker Primary="False">2657</Broker>
   </DeskBroker>
   <DeskBroker Desk="2302">
    <Broker Primary="False">2306</Broker>
   </DeskBroker>
   <DeskBroker Desk="2">
    <Broker Primary="False">82</Broker>
   </DeskBroker>
   <DeskBroker Desk="34">
    <Broker Primary="False">89</Broker>
   </DeskBroker>
   <DeskBroker Desk="64">
    <Broker Primary="False">15166</Broker>
   </DeskBroker>
  </DeskBrokers>
 </QuoteDefaults>
</User>

I have defined the XML as follows:

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace TestApplication
{
  #region UserPreferences

  [XmlRoot("User")]
  public class UserPreferences
  {
    #region Private Static Members

    private static XmlSerializer m_xmlSerializer = new XmlSerializer(typeof(UserPreferences));

    #endregion

    #region Public Properties

    [XmlArray("FavoriteQuotePages")]
    public List<PageGroup> FavoriteQuotePages { get; set; }

    [XmlArray("LayoutSettings")]
    public List<PageDialogSettings> LayoutSettings { get; set; }

    public QuoteDefaultSettings QuoteDefaults { get; set; }

    #endregion

    #region Constructors

    public UserPreferences()
    {
      FavoriteQuotePages = new List<PageGroup>();
      LayoutSettings = new List<PageDialogSettings>();
      QuoteDefaults = new QuoteDefaultSettings();
    }

    #endregion

    #region XML Serialization Methods

    public static string SerializeFrom(UserPreferences userPreferences)
    {
      try
      {
        XmlSerializerNamespaces xns = new XmlSerializerNamespaces();
        xns.Add(string.Empty, string.Empty);
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;
        settings.OmitXmlDeclaration = true;
        StringWriter writer = new StringWriter();
        XmlWriter xmlWriter = XmlWriter.Create(writer, settings);
        m_xmlSerializer.Serialize(xmlWriter, userPreferences, xns);
        String xml = writer.ToString();
        return xml;
      }
      catch (Exception ex)
      {
        throw ex;
      }
    }

    public static UserPreferences DeserializeFrom(string xml)
    {
      try
      {
        StringReader reader = new StringReader(xml);
        UserPreferences userPreferences = (UserPreferences)m_xmlSerializer.Deserialize(reader);
        return userPreferences;
      }
      catch (Exception ex)
      {
        throw ex;
      }
    }

    #endregion
  }

  #endregion

  #region PageGroup

  [XmlType("Group")]
  public class PageGroup
  {
    [XmlAttribute("name")]
    public string Name { get; set; }

    [XmlArray("Group")]
    public List<Page> Pages { get; set; }

    public PageGroup()
    {
      Pages = new List<Page>();
    }
  }

  #endregion

  #region Page

  [XmlType("PageName")]
  public class Page
  {
    [XmlElement]
    public string Name { get; set; }

    [XmlAttribute("startdate")]
    public DateTime StartDate { get; set; }

    [XmlAttribute("enddate")]
    public DateTime EndDate { get; set; }

    [XmlAttribute("daterange")]
    public string DateRange { get; set; }

    [XmlAttribute("customfilters")]
    public string CustomFilters { get; set; }

    [XmlAttribute("sourcepagename")]
    public string SourcePageName { get; set; }
  }

  #endregion

  #region PageDialogSettings

  [XmlType("PageDialog")]
  public class PageDialogSettings
  {
    [XmlAttribute("id")]
    public int Id { get; set; }

    [XmlAttribute("dialogname")]
    public string DialogName { get; set; }

    [XmlAttribute("viewname")]
    public string ViewName { get; set; }

    [XmlAttribute("modelname")]
    public string ModelName { get; set; }

    [XmlAttribute("modelkey")]
    public string ModelKey { get; set; }

    [XmlAttribute("positionx")]
    public double PositionX { get; set; }

    [XmlAttribute("positiony")]
    public double PositionY { get; set; }

    [XmlAttribute("width")]
    public int Width { get; set; }

    [XmlAttribute("height")]
    public int Height { get; set; }
  }

  #endregion

  #region QuoteDefaultSettings

  [XmlType("QuoteDefaults")]
  public class QuoteDefaultSettings
  {
    [XmlAttribute("Product")]
    public string Product { get; set; }

    [XmlElement]
    public int Quantity { get; set; }

    [XmlElement]
    public int ReserveQuantity { get; set; }

    [XmlElement]
    public int Timer { get; set; }

    [XmlArray("ClearingEntities")]
    [XmlArrayItem("ID")]
    public List<long> ClearingEntityIds { get; set; }

    [XmlArray]
    public List<DeskBroker> DeskBrokers { get; set; }

    public QuoteDefaultSettings()
    {
      ClearingEntityIds = new List<long>();
      DeskBrokers = new List<DeskBroker>();
    }
  }

  #endregion

  #region DeskBroker

  [XmlType("DeskBroker")]
  public class DeskBroker
  {
    [XmlAttribute("Desk")]
    public long DeskId { get; set; }

    [XmlArray]
    public List<Broker> Brokers { get; set; }

    public DeskBroker()
    {
      Brokers = new List<Broker>();
    }
  }

  #endregion

  #region Broker

  [XmlType("Broker")]
  public class Broker
  {
    [XmlAttribute]
    public bool Primary { get; set; }

    public long Id { get; set; }
  }

  #endregion
}

The Unit Tests:

using System;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestApplication
{
  [TestClass]
  public class UserPreferencesTests
  {
    [TestMethod]
    public void DeserializeExistingUserXml()
    {
      string filename = "user.xml";
      if (!File.Exists(filename))
      {
        throw new FileNotFoundException("Could not find file " + filename);
      }

      string xmlPreferences = File.ReadAllText(filename);
      DateTime startTime = DateTime.Now;
      UserPreferences preferences = UserPreferences.DeserializeFrom(xmlPreferences);
      TimeSpan duration = DateTime.Now.Subtract(startTime);

      Assert.IsTrue(duration.Milliseconds < 100, "The deseralization time took longer than 100ms: " + duration.Milliseconds + "ms");

      // Tests

      Assert.IsNotNull(preferences);
      Assert.AreEqual(2, preferences.FavoriteQuotePages.Count);

      var pageGroup = preferences.FavoriteQuotePages[0];
      Assert.AreEqual(2, pageGroup.Pages.Count);
      Assert.AreEqual("Default", pageGroup.Name);
      var page = pageGroup.Pages[0];
      Assert.AreEqual("NG Options", page.Name);
      page = pageGroup.Pages[1];
      Assert.AreEqual("NG Options", page.Name);

      pageGroup = preferences.FavoriteQuotePages[1];
      Assert.AreEqual(2, pageGroup.Pages.Count);
      Assert.AreEqual("CUSTOM PAGES", pageGroup.Name);

      Assert.AreEqual(1, preferences.LayoutSettings.Count);
      Assert.AreEqual(1, preferences.QuoteDefaults.ClearingEntityIds.Count);
      Assert.AreEqual(6, preferences.QuoteDefaults.DeskBrokers.Count);
    }
  }
}
Jose
  • 1,616
  • 4
  • 26
  • 38
  • 4
    If down voting a question, can you please place a reason for the down vote? Lets have some transparency here. – Jose Jun 26 '17 at 20:58
  • Looking at this question, may have a solution for me: https://stackoverflow.com/questions/364253/how-to-deserialize-xml-document?rq=1 – Jose Jun 27 '17 at 18:35

2 Answers2

0

Simply change

[XmlArray("Group")]
public List<Page> Pages { get; set; }

to

[XmlElement("PageName")]
public List<Page> Pages { get; set; }

Enjoy ;)

Note: Your XML uses "today" as startdate -- that does not work with DateTime.

Simon Mattes
  • 4,866
  • 2
  • 33
  • 53
  • Thanks Simon. I made the change to XMLElement("PageName"), and modified the startdate and enddate fields to be strings for now. But the PageName element and subelements in the XML are still not being parsed. Also, how would I define the field to contain innertext from PageName? – Jose Jun 27 '17 at 15:54
  • The problem here is that [XmlElement("PageName")] is not the same as the declaration [XmlType("PageName")] on the class Page itself -- one is the collection, the other one the single element -- change [XmlType("PageName")] to [XmlType("PageNameElement")] and the elements get populated. To get public string Name { get; set; } to work you have to change the [XmlElement] to [XmlText] since it is not an element but the actual content ;) – Simon Mattes Jun 28 '17 at 09:48
0

You simply have to change your PagweGroup page to this:

[XmlType("Group")]
public class PageGroup
{
    [XmlAttribute("name")]
    public string Name { get; set; }

    [XmlElement("PageName")]
    public List<Page> Pages { get; set; }

    public PageGroup()
    {
        Pages = new List<Page>();
    }
}

Instead of XmlArray("Group"), you must put XmlElement("PageName")

Note that after that, your XML has errors on the "today" string in startDate & endDate attributes

ericmas001
  • 603
  • 6
  • 12
  • Thanks Eric. I made the change, so now the List Pages field has Page objects, but looks like they do not contain the values from the document. – Jose Jun 27 '17 at 15:58