Link to home
Start Free TrialLog in
Avatar of petel2k
petel2k

asked on

XML how to deserialize C#

I have an XML that's returned from a WCF. The data is defined as Array OfArrayOfString.

The XML looks like
<?xml version=\"1.0\"?>\r\n<ArrayOfArrayOfString xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
  \r\n  <ArrayOfString>
    \r\n    <string>Group</string>\r\n    <string>Name</string>\r\n    <string>MONTH</string>\r\n    <string>AHT</string>\r\n    <string>EFFICIENCY</string>\r\n    <string>CREDIT</string>\r\n    <string>CRED_COUNT</string>\r\n    <string>MONITOR</string>\r\n    <string>SCOREADHERE</string>\r\n    <string>OVERALL</string>\r\n    <string>CALLDURIN</string>\r\n    <string>CALLDUROUT</string>\r\n    <string>WRAPIN</string>\r\n    <string>RATING</string>\r\n    <string>WRAPOUT</string>\r\n    <string>HOLDTIME</string>\r\n    <string>NUMOFMON</string>\r\n    <string>EXTN</string>\r\n
  </ArrayOfString>\r\n  <ArrayOfString>
    \r\n    <string>RATTLE         </string>\r\n    <string>JR</string>\r\n    <string>2012-10</string>\r\n    <string>484</string>\r\n    <string>96.34</string>\r\n    <string>3</string>\r\n    <string>1</string>\r\n    <string>
      73.8
      0
    </string>\r\n    <string>99.88</string>\r\n    <string>82.51</string>\r\n    <string>2435.68</string>\r\n    <string>330.90</string>\r\n    <string>84.42</string>\r\n    <string>60</string>\r\n    <string>6.33</string>\r\n    <string>823.62</string>\r\n    <string>5</string>\r\n    <string>7695</string>\r\n
  </ArrayOfString>\r\n  <ArrayOfString>
    \r\n    <string>RATTLE         </string>\r\n    <string>JR</string>\r\n    <string>2012-11</string>\r\n    <string>494</string>\r\n    <string>97.02</string>\r\n    <string>5</string>\r\n    <string>2</string>\r\n    <string>80.60</string>\r\n    <string>99.86</string>\r\n    <string>94.37</string>\r\n    <string>2072.72</string>\r\n    <string>332.35</string>\r\n    <string>45.23</string>\r\n    <string>100</string>\r\n    <string>3.55</string>\r\n    <string>773.57</string>\r\n    <string>5</string>\r\n    <string>7695</string>\r\n
  </ArrayOfString>\r\n  <ArrayOfString>
    \r\n    <string>Battle         </string>\r\n    <string>JR</string>\r\n    <string>
      2012-12</string>\r\n    <string>410</string>\r\n    <string>97.45</string>\r\n    <string>3.75</string>\r\n    <string>4</string>\r\n    <string>91.33</string>\r\n    <string>99.89</string>\r\n    <string>90.92</string>\r\n    <string>1570.67</string>\r\n    <string>308.60</string>\r\n    <string>44.05</string>\r\n    <string>75</string>\r\n    <string>5.20</string>\r\n    <string>500.55</string>\r\n    <string>3</string>\r\n    <string>7695</string>\r\n
    </ArrayOfString>\r\n  <ArrayOfString>
    \r\n    <string>Battle         </string>\r\n    <string>JR</string>\r\n    <string>2013-01</string>\r\n    <string>534</string>\r\n    <string>97.57</string>\r\n    <string>4</string>\r\n    <string>1</string>\r\n    <string>84.50</string>\r\n    <string>99.91</string>\r\n    <string>90.50</string>\r\n    <string>2241.95</string>\r\n    <string>297.75</string>\r\n    <string>115.38</string>\r\n    <string>80</string>\r\n    <string>8.50</string>\r\n    <string>860.93</string>\r\n    <string>8</string>\r\n    <string>7695</string>
    \r\n
  </ArrayOfString>\r\n  <ArrayOfString>
    \r\n    <string>Battle         </string>\r\n    <string>JR</string>\r\n    <string>2013-02</string>\r\n    <string>533</string>\r\n    <string>97.98</string>\r\n    <string>5</string>\r\n    <string>4</string>\r\n    <string>87.67</string>\r\n    <string>99.94</string>\r\n    <string>96.40</string>\r\n    <string>2630.45</string>\r\n    <string>387.97</string>\r\n    <string>251.62</string>\r\n    <string>100</string>\r\n    <string>30.12</string>\r\n    <string>955.63</string>\r\n    <string>3</string>\r\n    <string>7695</string>\r\n
  </ArrayOfString>\r\n  <ArrayOfString>
    \r\n    <string>Battle         </string>\r\n    <string>JR</string>\r\n    <string>2013-03</string>\r\n    <string>536</string>\r\n    <string>96.74</string>\r\n    <string>5</string>\r\n    <string>1</string>\r\n    <string>81.71</string>\r\n    <string>100</string>\r\n    <string>94.61</string>\r\n    <string>1684.88</string>\r\n    <string>349.05</string>\r\n    <string>169.62</string>\r\n
    <string>100</string>\r\n    <string>48.32</string>\r\n    <string>632.18</string>\r\n    <string>7</string>\r\n    <string>7695</string>\r\n
  </ArrayOfString>\r\n  <ArrayOfString>
    \r\n    <string>Battle         </string>\r\n    <string>MREID</string>\r\n    <string>2013-05</string>\r\n    <string>659</string>\r\n    <string>97.81</string>\r\n    <string>2.66</string>\r\n    <string>3</string>\r\n    <string>96.33</string>\r\n    <string>99.83</string>\r\n    <string>86.79</string>\r\n    <string>2801.35</string>\r\n    <string>409.02</string>\r\n    <string>301.35</string>\r\n    <string>53.20</string>\r\n    <string>42.53</string>\r\n    <string>931.05</string>\r\n    <string>6</string>\r\n    <string>7695</string>\r\n
  </ArrayOfString>\r\n  <ArrayOfString>
    \r\n    <string>Battle         </string>\r\n    <string>MREID</string>\r\n    <string>2013-06</string>\r\n    <string>655</string>\r\n    <string>98.85</string>\r\n    <string>4</string>\r\n    <string>4</string>\r\n    <string>95.50</string>\r\n    <string="">
      99.70</string>\r\n    <string>93.51</string>\r\n    <string>2599.90</string>\r\n    <string>496.63</string>\r\n    <string>382.73</string>\r\n    <string>80</string>\r\n    <string>46.87</string>\r\n    <string>916.33</string>\r\n    <string>4</string>\r\n    <string>7695</string>\r\n
    </ArrayOfString>\r\n  <ArrayOfString>    
      .
      .
      .
      .
    </ArrayOfArrayOfString>

Open in new window


And it is created in the WCF like
int columnCount = table.Columns.Count;
                  int rowCount = table.Rows.Count;
                  List<string> captions = new List<string>();
                  for (int i = 0; i < columnCount; i++)
                  {
                      captions.Add(table.Columns[i].Caption); //first item will contain column headers
                  }
                  result.Add(captions);
                  for (int i = 0; i < rowCount; i++)
                  {
                      List<string> row = new List<string>();
                      for (int j = 0; j < columnCount; j++)
                      {
                          row.Add(table.Rows[i].ItemArray[j].ToString());
                      }
                      result.Add(row);
                  }
                  System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(List<List<string>>));
                  using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
                  {
                      serializer.Serialize(ms, result);
                      ms.Position = 0;
                      string data = new System.IO.StreamReader(ms).ReadToEnd();
                      return data;
                  }
              }
              catch
              {
                  return "";
              }

Open in new window


And I need to deserialize but don't know how
public void webService_GetSqlResultTableCompleted(object sender, WCFSvc1.GetSqlResultTableCompletedEventArgs e)
        {
            Int32 datGridIndex = dgMaster.SelectedIndex;
            
            
           // string xmlResult = e.Result;
            if (xmlResult == "")
            {
                MessageBox.Show("Error occured while executing SQL");
                return;
            }

            try
            {      // thos code does not work
                XmlSerializer serializer = new XmlSerializer(typeof(DBstream));
                StringReader reader = new StringReader(e.Result);
                DBstream result = (DBstream)serializer.Deserialize(reader);

.
.
}

[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
        public class DBstream
        {

            /// <remarks/>
            public DBdefinitions DBdefinitions;
        }

        public class DBdefinitions
        {
            
            public string dbGrp { get; set; }

           
            public string dbName { get; set; }
            
            public DateTime dbMonth { get; set; }
           
            public int dbAHT { get; set; }
           
            public decimal dbEffeciency { get; set; }
          
            public decimal dbCredit { get; set; }
            
            public int dbCreditCount { get; set; }

            public decimal dbMonitor { get; set; }

            public decimal dbScoreAdhere { get; set; }

            public decimal dbOverAll { get; set; }

            public decimal dbCallDur { get; set; }

            public decimal dbCallDurOut { get; set; }

            public decimal dbWrapIn { get; set; }

            public decimal dbRating { get; set; }

            public decimal dbWrapOut { get; set; }

            public decimal dbHoldTime { get; set; }

            public int dbNumOfMons { get; set; }

            public int dbExtn { get; set; }
           
        }

Open in new window

Avatar of Grant Spiteri
Grant Spiteri
Flag of Australia image

You need to use the xsd.exe tool which gets installed with the Windows SDK into a directory something similar to: C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin

On the first run, you use xsd.exe and you convert your sample XML into a XSD file (XML schema file):

xsd yourfile.xml
This gives you yourfile.xsd, which in a second step, you can convert again using xsd.exe into a C# class:

xsd yourfile.xsd /c
This should give you a file yourfile.cs which will contain a C# class that you can use to deserialize the XML file you're getting - something like:

XmlSerializer serializer = new XmlSerializer(typeof(msg));
msg resultingMessage = (msg)serializer.Deserialize('yourfile.xml');
Should work pretty well for most cases.

The XML serializer will take any stream as its input - either a file or a memory stream will be fine:

XmlSerializer serializer = new XmlSerializer(typeof(msg));
MemoryStream memStream = new MemoryStream(Encoding.UTF8.GetBytes(inputString));
msg resultingMessage = (msg)serializer.Deserialize(memStream);
or use a StringReader:

XmlSerializer serializer = new XmlSerializer(typeof(msg));
StringReader rdr = new StringReader(inputString);
msg resultingMessage = (msg)serializer.Deserialize(rdr);
Avatar of petel2k
petel2k

ASKER

Thanks for answering. Though I'm not sure I follow.

My silverlight app connects to a service via 'Service reference'  --> http://prodsvc/WCFData2.Services.ServiceInterface.svc

This service exposes a method which returns data from some query in XML format.

How would I use the xsd.exe tool?

Thanks
Avatar of petel2k

ASKER

BTW: I'm able to get the data via

 XmlSerializer serializer = new XmlSerializer(typeof(List<List<string>>));
                StringReader reader = new StringReader(xmlResult);
                List<List<string>> result = (List<List<string>>)serializer.Deserialize(reader);

result contains the data ie. result.row(0) contains the column names and subsequent rows contain the data.

I need to be able to run Linq against the rows to do calculations and summaries. What I need to do is convert the data so that lamda experssions with linq can be used and numeric columns can also be sorted by the user from the datagrid properly .

So that is why I created the class (thinking this would structure the data;
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
        public class DBstream
        {

            /// <remarks/>
            public DBdefinitions DBdefinitions;
        }

        public class DBdefinitions
        {
           
            public string dbGrp { get; set; }

           
            public string dbName { get; set; }
           
            public DateTime dbMonth { get; set; }
           
            public int dbAHT { get; set; }
           
            public decimal dbEffeciency { get; set; }
         
            public decimal dbCredit { get; set; }
           
            public int dbCreditCount { get; set; }

            public decimal dbMonitor { get; set; }

            public decimal dbScoreAdhere { get; set; }

            public decimal dbOverAll { get; set; }

            public decimal dbCallDur { get; set; }

            public decimal dbCallDurOut { get; set; }

            public decimal dbWrapIn { get; set; }

            public decimal dbRating { get; set; }

            public decimal dbWrapOut { get; set; }

            public decimal dbHoldTime { get; set; }

            public int dbNumOfMons { get; set; }

            public int dbExtn { get; set; }
           
        }
                                 

If there is a way I can move my results to something as this, I don't need to deserialize since it already can deserialize to rows, just not formated with types.
ASKER CERTIFIED SOLUTION
Avatar of Grant Spiteri
Grant Spiteri
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial