none
Deserialize XML into Class

    Question

  • I'm trying to deserialize my an XDocument into a Class, but I am tripping up in the following line:

    collectiondeliveryresponse = (DeliveryResponse)serializer.Deserialize(sr);


    Here is my XML which may contain any number of Recipient_Status Child Nodes:

    <TELEMESSAGE>
      <TELEMESSAGE_CONTENT>
        <MESSAGE_STATUS>
          <STATUS_ID></STATUS_ID>
          <STATUS_DESCRIPTION></STATUS_DESCRIPTION>
          <MESSAGE_ID>75587</MESSAGE_ID>
          <RECIPIENT_STATUS>
            <RECIPIENT_NAME></RECIPIENT_NAME>
            <DEVICE>
              <TYPE>40</TYPE>
              <VALUE>abc</VALUE>
              <STATUS>1100</STATUS>
              <DESCRIPTION>Email was delivered</DESCRIPTION>
              <STATUS_DATE>20130117 22:41:12</STATUS_DATE>
            </DEVICE>
          </RECIPIENT_STATUS>
          <RECIPIENT_STATUS>
            <RECIPIENT_NAME></RECIPIENT_NAME>
            <DEVICE>
              <TYPE>60</TYPE>
              <VALUE>21355</VALUE>
              <STATUS>1500</STATUS>
              <DESCRIPTION>SMS successfully sent</DESCRIPTION>
              <STATUS_DATE>20130117 22:41:13</STATUS_DATE>
            </DEVICE>
          </RECIPIENT_STATUS>
          <RECIPIENT_STATUS>
            <RECIPIENT_NAME></RECIPIENT_NAME>
            <DEVICE>
              <TYPE>10</TYPE>
              <VALUE>50621</VALUE>
              <STATUS>3000</STATUS>
              <DESCRIPTION>Message delivery in progress</DESCRIPTION>
              <STATUS_DATE>20130117 22:41:11</STATUS_DATE>
            </DEVICE>
          </RECIPIENT_STATUS>
        </MESSAGE_STATUS>
      </TELEMESSAGE_CONTENT>
      <VERSION>1</VERSION>
    </TELEMESSAGE>

    Here is my public class, where I believe the problem to be:

      public class DeliveryResponse 
            {
                // Public Properties
                public string Message_Id
                {
                    get { return Message_Id; }
                    set { Message_Id = value; }
                }
                public string Message_Key
                {
                    get { return Message_Key; }
                    set { Message_Key = value; }
                }
                public string Status_Time
                {
                    get { return Status_Time; }
                    set { Status_Time = value; }
                }
                public string Device_Value
                {
                    get { return Device_Value; }
                    set { Device_Value = value; }
                }
                public string Device_Type
                {
                    get { return Device_Type; }
                    set { Device_Type = value; }
                }
                public string Message_Status
                {
                    get { return Message_Status; }
                    set { Message_Status = value; }
                }
                public string Message_Status_Description
                {
                    get { return Message_Status_Description; }
                    set { Message_Status_Description = value; }
                }
                // Constructor
                public DeliveryResponse()
                {
                }
              
            }

    Here is my Deserialize Code:

    private void Deserialize(XDocument abc) { DeliveryResponse collectiondeliveryresponse = new DeliveryResponse(); XmlSerializer serializer = new XmlSerializer(collectiondeliveryresponse.GetType()); System.IO.StringReader sr = new System.IO.StringReader(xDocDeliveryResponse.ToString()); collectiondeliveryresponse = (DeliveryResponse)serializer.Deserialize(sr); sr.Close(); }


    This is the error message received:

    {System.InvalidOperationException: There is an error in XML document (1, 2). ---> System.InvalidOperationException: <TELEMESSAGE xmlns=''> was not expected.
       at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderDeliveryResponse.Read3_DeliveryResponse()
       --- End of inner exception stack trace ---
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, Object events)
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
       at System.Xml.Serialization.XmlSerializer.Deserialize(TextReader textReader)
       at Messaging.MainPage.Deserialize(XDocument abc)
       at Messaging.MainPage.delmediator_DelToExternalServiceCompleted(Object sender, PostToExternalServiceCompletedEventArgs e)
       at Messaging.svcMediator.MediatorServiceClient.OnPostToExternalServiceCompleted(Object state)}


    Friday, January 18, 2013 8:21 PM

Answers

  • Learn something new every day.  I normally use serialization when I am using the same class to serialize / de-serialize, which I guess is one of the reasons that I found this interesting.  Below are the classes that I created to de-serialize the original data:

     [Serializable]
     public class TELEMESSAGE
     {
      public MessageContent TELEMESSAGE_CONTENT
      {
       get;
       set;
      }
    
      public string VERSION
      {
       get;
       set;
      }
    
      public TELEMESSAGE()
      {
      }
    
      public static TELEMESSAGE Deserialize(XDocument document)
      {
       StringReader l_reader = null;
    
       try
       {
        l_reader = new StringReader(document.ToString());
        XmlSerializer l_serializer = new XmlSerializer(typeof(TELEMESSAGE));
        return (TELEMESSAGE)l_serializer.Deserialize(l_reader);
       }
       catch (Exception)
       {
        return null;
       }
       finally
       {
        if (l_reader != null)
        {
         l_reader.Close();
        }
       }
      }
     }
     public class MessageContent
     {
      public MessageStatus MESSAGE_STATUS
      {
       get;
       set;
      }
    
      public MessageContent()
      {
      }
     }
     public class MessageStatus
     {
      public string STATUS_ID
      {
       get;
       set;
      }
    
      public string STATUS_DESCRIPTION
      {
       get;
       set;
      }
    
      public string MESSAGE_ID
      {
       get;
       set;
      }
    
      [XmlElement("RECIPIENT_STATUS")]
      public List<RECIPIENT_STATUS> RecipientStatuses;
    
      public MessageStatus()
      {
      }
     }
     public class RECIPIENT_STATUS
     {
      public string RECIPIENT_NAME
      {
       get;
       set;
      }
    
      public Device DEVICE
      {
       get;
       set;
      }
    
      public RECIPIENT_STATUS()
      {
      }
     }
     public class Device
     {
      public string TYPE
      {
       get;
       set;
      }
    
      public string VALUE
      {
       get;
       set;
      }
    
      public string STATUS
      {
       get;
       set;
      }
    
      public string DESCRIPTION
      {
       get;
       set;
      }
    
      public string STATUS_DATE
      {
       get;
       set;
      }
    
      public Device()
      {
      }
     }
    Thanks, Louis, your post gave me the piece to tie it together.





    It would be greatly appreciated if you would mark any helpful entries as helpful and if the entry answers your question, please mark it with the Answer link.



    Monday, January 21, 2013 5:03 PM

All replies

  • You'll have to try a c# forum.
    Friday, January 18, 2013 9:45 PM
  • I'm trying to deserialize my an XDocument into a Class, but I am tripping up in the following line:

    collectiondeliveryresponse = (DeliveryResponse)serializer.Deserialize(sr);

    Here is my XML which may contain any number of Recipient_Status Child Nodes:

    <TELEMESSAGE>
      <TELEMESSAGE_CONTENT>
        <MESSAGE_STATUS>
          <STATUS_ID></STATUS_ID>
          <STATUS_DESCRIPTION></STATUS_DESCRIPTION>
          <MESSAGE_ID>75587</MESSAGE_ID>
          <RECIPIENT_STATUS>
            <RECIPIENT_NAME></RECIPIENT_NAME>
            <DEVICE>
              <TYPE>40</TYPE>
              <VALUE>abc</VALUE>
              <STATUS>1100</STATUS>
              <DESCRIPTION>Email was delivered</DESCRIPTION>
              <STATUS_DATE>20130117 22:41:12</STATUS_DATE>
            </DEVICE>
          </RECIPIENT_STATUS>
          <RECIPIENT_STATUS>
            <RECIPIENT_NAME></RECIPIENT_NAME>
            <DEVICE>
              <TYPE>60</TYPE>
              <VALUE>21355</VALUE>
              <STATUS>1500</STATUS>
              <DESCRIPTION>SMS successfully sent</DESCRIPTION>
              <STATUS_DATE>20130117 22:41:13</STATUS_DATE>
            </DEVICE>
          </RECIPIENT_STATUS>
          <RECIPIENT_STATUS>
            <RECIPIENT_NAME></RECIPIENT_NAME>
            <DEVICE>
              <TYPE>10</TYPE>
              <VALUE>50621</VALUE>
              <STATUS>3000</STATUS>
              <DESCRIPTION>Message delivery in progress</DESCRIPTION>
              <STATUS_DATE>20130117 22:41:11</STATUS_DATE>
            </DEVICE>
          </RECIPIENT_STATUS>
        </MESSAGE_STATUS>
      </TELEMESSAGE_CONTENT>
      <VERSION>1</VERSION>
    </TELEMESSAGE>

    Here is my public class, where I believe the problem to be:

      public class DeliveryResponse 
            {
                // Public Properties
                public string Message_Id
                {
                    get { return Message_Id; }
                    set { Message_Id = value; }
                }
                public string Message_Key
                {
                    get { return Message_Key; }
                    set { Message_Key = value; }
                }
                public string Status_Time
                {
                    get { return Status_Time; }
                    set { Status_Time = value; }
                }
                public string Device_Value
                {
                    get { return Device_Value; }
                    set { Device_Value = value; }
                }
                public string Device_Type
                {
                    get { return Device_Type; }
                    set { Device_Type = value; }
                }
                public string Message_Status
                {
                    get { return Message_Status; }
                    set { Message_Status = value; }
                }
                public string Message_Status_Description
                {
                    get { return Message_Status_Description; }
                    set { Message_Status_Description = value; }
                }
                // Constructor
                public DeliveryResponse()
                {
                }
              
            }

    Here is my Deserialize Code:

    private void Deserialize(XDocument abc) { DeliveryResponse collectiondeliveryresponse = new DeliveryResponse(); XmlSerializer serializer = new XmlSerializer(collectiondeliveryresponse.GetType()); System.IO.StringReader sr = new System.IO.StringReader(xDocDeliveryResponse.ToString()); collectiondeliveryresponse = (DeliveryResponse)serializer.Deserialize(sr); sr.Close(); }

    This is the error message received:

    {System.InvalidOperationException: There is an error in XML document (1, 2). ---> System.InvalidOperationException: <TELEMESSAGE xmlns=''> was not expected.
       at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderDeliveryResponse.Read3_DeliveryResponse()
       --- End of inner exception stack trace ---
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, Object events)
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
       at System.Xml.Serialization.XmlSerializer.Deserialize(TextReader textReader)
       at Messaging.MainPage.Deserialize(XDocument abc)
       at Messaging.MainPage.delmediator_DelToExternalServiceCompleted(Object sender, PostToExternalServiceCompletedEventArgs e)
       at Messaging.svcMediator.MediatorServiceClient.OnPostToExternalServiceCompleted(Object state)}

    Friday, January 18, 2013 10:21 PM
  • I'm not and XML serializer expert but the error message:

    <TELEMESSAGE xmlns=''>

    Seems to indicate it is expecting something other than nothing.

    When parsing things it seems to me the parser has to "base" the parsing on a known standard...

    Try this:

    http://www.w3schools.com/tags/att_html_xmlns.asp

    http://en.wikipedia.org/wiki/XML_namespace


    JP Cowboy Coders Unite!


    Friday, January 18, 2013 10:29 PM
  • A couple of comments to begin with,

    public string Message_Id
    {
     get { return Message_Id; }
     set { Message_Id = value; }
    }
    

    is the same as

    public string Message_Id
    {
     get;
     set;
    }
    

    and a lot less verbose.

    By convention, serialization methods are normally a static member of the class that they serialize.

    You method takes an XDocument "abc" as an argument, but what you are deserializing is something called xDocDeliveryResponse, which I can only presume is something from a web method.  Are you sure that the XML that you show in your post is actually what is getting passed in?


    It would be greatly appreciated if you would mark any helpful entries as helpful and if the entry answers your question, please mark it with the Answer link.

    Friday, January 18, 2013 11:00 PM
  • After further reviewing your information, I have found further issues.  The XML data that you provided will not be deserialized by your class.  The format that your class is looking for is something like:

    <?xml version="1.0" encoding="utf-8"?>
    <DeliveryResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                      xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <Message_Id>Message Id</Message_Id>
        <Message_Key>Message Key</Message_Key>
        <Status_Time>Status Time</Status_Time>
        <Device_Value>Value</Device_Value>
        <Device_Type>Device Type</Device_Type>
        <Message_Status>Message Status</Message_Status>
        <Message_Status_Description>Message Status Decision</Message_Status_Description>
    </DeliveryResponse>

    I am providing a modified class below for you to play with, which is your class, with some modifications.  The sample still will not de-serialize the data that you wish because the definition is wrong.  I have also provided a serialization method so that you can experiment with what the serialized format of your class currently is:

     [Serializable]
     public class DeliveryResponse
     {
      // Public Properties
      public string Message_Id
      {
       get;
       set;
      }
    
      public string Message_Key
      {
       get;
       set;
      }
    
      public string Status_Time
      {
       get;
       set;
      }
    
      public string Device_Value
      {
       get;
       set;
      }
    
      public string Device_Type
      {
       get;
       set;
      }
    
      public string Message_Status
      {
       get;
       set;
      }
    
      public string Message_Status_Description
      {
       get;
       set;
      }
      
      // Constructor
      public DeliveryResponse()
      {
      }
    
      public static DeliveryResponse Deserialize(XDocument document)
      {
       StringReader l_reader = null;
    
       try
       {
        l_reader = new StringReader(document.ToString());
        XmlSerializer l_serializer = new XmlSerializer(typeof(DeliveryResponse));
        return (DeliveryResponse)l_serializer.Deserialize(l_reader);
       }
       catch (Exception)
       {
        return null;
       }
       finally
       {
        if (l_reader != null)
        {
         l_reader.Close();
        }
       }
      }
    
      public static void Serialize(DeliveryResponse response)
      {
       TextWriter l_writer = null;
    
       try
       {
        l_writer = new StreamWriter("SampleData.xml");
        XmlSerializer l_serializer = new XmlSerializer(typeof(DeliveryResponse));
        l_serializer.Serialize(l_writer, response);
       }
       finally
       {
        if (l_writer != null)
        {
         l_writer.Close();
        }
       }
      }
     }
    


    It would be greatly appreciated if you would mark any helpful entries as helpful and if the entry answers your question, please mark it with the Answer link.

    Friday, January 18, 2013 11:42 PM
  • Just for fun, I decided to try and construct a set of classes, yes I said set, that would be able to de-serialize the data that you provided.  Not sure that it can be done.

    The issue is the variable number of RECIPIENT_STATUS elements.  If this list of RECIPIENT_STATUS was wrapped in another element, such as:

    <STATUS>
     <RECIPIENT_STATUS />
     <RECIPIENT_STATUS />
     <RECIPIENT_STATUS />
    </STATUS>

    Then serialization becomes much easier.  If you can influence the schema of your data, then that is the route that I would go....if not, you may be stuck with manually constructing the classes by parsing the XDocument.

    It would be greatly appreciated if you would mark any helpful entries as helpful and if the entry answers your question, please mark it with the Answer link.

    Saturday, January 19, 2013 12:42 AM
  • Hi jmcpsd,

    I'll merge another duplicate thread to this thread. 

    Thanks.


    Bob Shen
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    Monday, January 21, 2013 11:24 AM
    Moderator
  • The issue is the variable number of RECIPIENT_STATUS elements.

    That's not a problem. Attach an XmlElement attribute to a list to serialize it as a succession of elements.

    Monday, January 21, 2013 3:44 PM
  • The issue is the variable number of RECIPIENT_STATUS elements.

    That's not a problem. Attach an XmlElement attribute to a list to serialize it as a succession of elements.

    The issue here is that the name of the list would also be serialized, which is the reason that I suggested encapsulating the RECIPIENT_STATUS in another element, which would facilitate your suggestion.  The issue here is not one of serialization, it is de-serialization of existing data as it existed in the original post.


    It would be greatly appreciated if you would mark any helpful entries as helpful and if the entry answers your question, please mark it with the Answer link.

    Monday, January 21, 2013 4:08 PM
  • The issue is the variable number of RECIPIENT_STATUS elements.

    That's not a problem. Attach an XmlElement attribute to a list to serialize it as a succession of elements.

    The issue here is that the name of the list would also be serialized

    No, with an XmlElement attribute attached to the list, only the items are serialized.

    For example, this class:

    public class RECIPIENT_STATUS
    {
        public string RECIPIENT_NAME;
    }
    public class MESSAGE_STATUS
    {
        [XmlElement("RECIPIENT_STATUS")]
        public List<RECIPIENT_STATUS> RecipientStatuses;
    }

    Following code:

    XmlSerializer ser = new XmlSerializer(typeof(MESSAGE_STATUS));
    using (FileStream f = new FileStream(@"c:\temp\test.xml", FileMode.Create))
    {
        ser.Serialize(f, new MESSAGE_STATUS {
            RecipientStatuses = {
                new RECIPIENT_STATUS { RECIPIENT_NAME = "first" },
                new RECIPIENT_STATUS { RECIPIENT_NAME = "second" }
            }
        });
    }

    gives the following xml:

    <?xml version="1.0"?>
    <MESSAGE_STATUS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <RECIPIENT_STATUS>
        <RECIPIENT_NAME>first</RECIPIENT_NAME>
      </RECIPIENT_STATUS>
      <RECIPIENT_STATUS>
        <RECIPIENT_NAME>second</RECIPIENT_NAME>
      </RECIPIENT_STATUS>
    </MESSAGE_STATUS>

    And of course that xml is deserialized as the original object.

    I think the only thing that could be a problem is the STATUS_DATE timestamp. I'm going to try deserializing the whole xml from the OP.

    Monday, January 21, 2013 4:49 PM
  • Learn something new every day.  I normally use serialization when I am using the same class to serialize / de-serialize, which I guess is one of the reasons that I found this interesting.  Below are the classes that I created to de-serialize the original data:

     [Serializable]
     public class TELEMESSAGE
     {
      public MessageContent TELEMESSAGE_CONTENT
      {
       get;
       set;
      }
    
      public string VERSION
      {
       get;
       set;
      }
    
      public TELEMESSAGE()
      {
      }
    
      public static TELEMESSAGE Deserialize(XDocument document)
      {
       StringReader l_reader = null;
    
       try
       {
        l_reader = new StringReader(document.ToString());
        XmlSerializer l_serializer = new XmlSerializer(typeof(TELEMESSAGE));
        return (TELEMESSAGE)l_serializer.Deserialize(l_reader);
       }
       catch (Exception)
       {
        return null;
       }
       finally
       {
        if (l_reader != null)
        {
         l_reader.Close();
        }
       }
      }
     }
     public class MessageContent
     {
      public MessageStatus MESSAGE_STATUS
      {
       get;
       set;
      }
    
      public MessageContent()
      {
      }
     }
     public class MessageStatus
     {
      public string STATUS_ID
      {
       get;
       set;
      }
    
      public string STATUS_DESCRIPTION
      {
       get;
       set;
      }
    
      public string MESSAGE_ID
      {
       get;
       set;
      }
    
      [XmlElement("RECIPIENT_STATUS")]
      public List<RECIPIENT_STATUS> RecipientStatuses;
    
      public MessageStatus()
      {
      }
     }
     public class RECIPIENT_STATUS
     {
      public string RECIPIENT_NAME
      {
       get;
       set;
      }
    
      public Device DEVICE
      {
       get;
       set;
      }
    
      public RECIPIENT_STATUS()
      {
      }
     }
     public class Device
     {
      public string TYPE
      {
       get;
       set;
      }
    
      public string VALUE
      {
       get;
       set;
      }
    
      public string STATUS
      {
       get;
       set;
      }
    
      public string DESCRIPTION
      {
       get;
       set;
      }
    
      public string STATUS_DATE
      {
       get;
       set;
      }
    
      public Device()
      {
      }
     }
    Thanks, Louis, your post gave me the piece to tie it together.





    It would be greatly appreciated if you would mark any helpful entries as helpful and if the entry answers your question, please mark it with the Answer link.



    Monday, January 21, 2013 5:03 PM
  • For the date, I would change your Device class like this:
    public class Device
     {
      public string TYPE
      {
       get;
       set;
      }
    
      public string VALUE
      {
       get;
       set;
      }
    
      public string STATUS
      {
       get;
       set;
      }
    
      public string DESCRIPTION
      {
       get;
       set;
      }
    
      [XmlIgnore]
      public DateTime STATUS_DATE
      {
       get;
       set;
      }
      [XmlElement("STATUS_DATE")]
      public string STATUS_DATE_STRING
      {
       get { return STATUS_DATE.ToString("yyyyMMdd HH:mm:ss", CultureInfo.InvariantCulture); }
       set { STATUS_DATE = DateTime.ParseExact(value, "yyyyMMdd HH:mm:ss", CultureInfo.InvariantCulture); }
      }
    
      public Device()
      {
      }
     }


    • Edited by Louis.fr Monday, January 21, 2013 5:08 PM
    Monday, January 21, 2013 5:07 PM
  • My original point to the poster was that his original class would not de-serialize his data because his class definition did not meet the requirements of the data.  I started a de-serialization, as an example for him, to point him down the right path and because it seemed like something fun to do at the time.

    I do appreciate your input.


    It would be greatly appreciated if you would mark any helpful entries as helpful and if the entry answers your question, please mark it with the Answer link.

    Monday, January 21, 2013 5:14 PM
  • public string Message_Id { get { return Message_Id; } set { Message_Id = value; } }

    It gives me a System.StackOverflowException because of an infinite recursion.


    Monday, January 21, 2013 8:56 PM
  • Duplicate thread:

    http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/a4053929-71f8-41de-9d87-73fb9996c74a


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, January 22, 2013 9:57 AM