Home > database >  How do I deserialize XML into list<class>
How do I deserialize XML into list<class>

Time:09-23

Given the following HTTP POST response (the request works):

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<DataSet xmlns="http://tempuri.org/">
  <schema xmlns="http://www.w3.org/2001/XMLSchema">schema</schema>xml</DataSet>

And this XSD (XML Schema Definition, part):

<?xml version="1.0" encoding="utf-8"?>
<DataSet xmlns="http://tempuri.org/">
   <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
      <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
          <xs:complexType>
             <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element name="MTM">
                   <xs:complexType>
                     <xs:sequence>
                        <xs:element name="MTMDate" type="xs:dateTime" minOccurs="0" />
                        <xs:element name=......

.... More "column" elements follor after the MTMDate element.

My code to try and deserialize data returned in XML:

[XmlRoot("MTM")]
public class MTM
{
    [XmlElement("MTM")]
    public List<MTMItem> MTMData { get; set; }
}

public class MTMItem
{
    [XmlElement("MTMDate")]
    public DateTime MTMDate { get; set; }
}

HttpWebResponse response = (HttpWebResponse)request.GetResponse();

XmlSerializer xmlSerializer = new XmlSerializer(typeof(MTM));
MTM mtmData = (MTM)xmlSerializer.Deserialize(response.GetResponseStream());

When running, on the line MTM mtmData = .. I get the following error:

There is an error in XML document (2,2) IvalidOperationException: <DataSet xmlns='http://tempuri.org/'> was not expected

I presume I am getting the [XmlRoot("MTM")] part wrong and not following the XSD Schema correctly in order to deserialise into a List<MTM>?

EDIT:

data gets populated with byte[] data, is that my xml data that I then need to deserialize to a dataset?

  using (var stream = request.GetRequestStream())
  {
      stream.Write(data, 0, data.Length);
  }

CodePudding user response:

The XML content you've provided represents a .net object designed for representing database responses called a DataSet. You could write your own deserialization classes to pull just the data you want, but you are probably better off using the built-in behaviour in the .net framework according to the documentation

The part that is relevant is the section titled Create an XML Web service client. as the service already exists:

If you want to have Visual Studio generate the Web service proxy class for you, simply create the client project, and, in the Solution Explorer window, right-click the project, and then select Add > Service Reference. In the Add Service Reference dialog box, select Advanced, and then select Add Web Reference. Select the Web service from the list of available Web services (this may require supplying the address of the Web service endpoint if the Web service isn't available within the current solution or on the current computer). If you create the XML Web service proxy yourself (as described in the previous step), you can import it into your client code and consume the XML Web service methods

CodePudding user response:

Basing another answer on the assumption that we don't want to generate a web service client:

I suspect the difficulty you're having relates to the schema describing the objects inside the dataset, where a client built to consume this webservice would know that it needs to unpack the DataSet object and then interpret the results. The schema you're generating classes from doesn't say anything about the DataSet class because it assumes that an old-style asp.net XML Web Service client already knows that.

So I'd think that what you need to be able to interpret the "payload" of the DataSet according to the schema it provides is to create an XmlReader and navigate to the start of the payload element, effectively stripping off the DataSet wrapping. You want to advance the XmlReader to the root element of the payload, skipping over the associated schema, which is only description and not data. So you would want something like:

        using (var reader = XmlReader.Create(stream)) 
        {
            reader.ReadToDescendant("MTM");
            MTM mtmData = (MTM)serializer.Deserialize(reader);                
        }
  • Related