Solved

DeSerialization - Element child nodes to string

Posted on 2011-09-07
5
1,223 Views
Last Modified: 2012-05-12
Hello Experts,

Assume I want to deserialize the following XML:

<ROOT>
<STATUS>101</STATUS>
<PAYLOAD>
<PERSON>
<FIRSTNAME>xxx</FIRSTNAME>
<....>xxx</....>
</PERSON>
</PAYLOAD>
</ROOT>

Open in new window


I would like to deserialize this xml, but let the payload element outerxml (element + childnodes) to be stored as a string in the PayLoad property.

    [XmlRoot(ElementName="ROOT")]
    public class Example
    {
        private string status;
        private string payLoad;

        [XmlElement(ElementName = "PAYLOAD")]
        public string PayLoad
        {
            get { return payLoad; }
            set { payLoad= value.}
        }
        [XmlElement(ElementName = "STATUS")]
        public string Status
        {
            get { return status; }
            set { status = value; }
        }

    }

Open in new window


Example use:

Example MyExample = serializer.Deserialize(xmlstring);

Console.WriteLine(MyExample.PayLoad);

//Writes:
//<PAYLOAD><PERSON><FIRSTNAME>xxx</FIRSTNAME><....>xxx</....></PERSON></PAYLOAD>

Open in new window


Is this possible?

Thank you,
amr-it
0
Comment
Question by:amr-it
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
5 Comments
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 36496705
You could do something like this:
XmlSerializer MyExample = new XmlSerializer(typeof(Example));

MyExample.UnknownElement += new XmlElementEventHandler(deserializer_UnknownElement);

Example MyExample = serializer.Deserialize(xmlstring) AS Example;

...

static void deserializer_UnknownElement(object sender, XmlElementEventArgs e)
{
    Example obj = e.ObjectBeingDeserialized as Example;

    if (e.Element.Name == "PAYLOAD")
    {
        obj.PayLoad = e.Element.OuterXml;
    }
}

Open in new window

0
 
LVL 1

Author Comment

by:amr-it
ID: 36500900
Thank you kaufmed for your comment.
I forgot to mention that my serializer and deserializer methods are located in a helper class and are designed to be generic (handling many different types), meaning if possible, I don't want to cast to the Example type. I got it to work doing something very similair to what you have proposed and I would assume that the above would work.

But, is there any way to define this in the class design so that the deserializer directly knows how to handle it?
0
 
LVL 75

Accepted Solution

by:
käµfm³d   👽 earned 500 total points
ID: 36502347
You could define a method in your class which takes in a delegate parameter and then assign the delegate as the handler for the event mentioned above. The signature of the delegate would need to match the signature as demonstrated above. Then each delegate would take care of managing the types it works with.

I don't know your specific code, but here is a demonstration of what I'm talking about:
using System;
using System.Xml;
using System.Xml.Serialization;

namespace _27295319
{
    class Program
    {
        /// <summary>
        /// Entry point for application.
        /// </summary>
        /// <param name="args">The args.</param>
        /// \date 9/8/2011 8:41 AM
        static void Main(string[] args)
        {
            SerializerClass deserailzer = new SerializerClass(typeof(Example));

            deserailzer.SetUnknownElementHandler(deserializer_UnknownElement);
            Example obj = deserailzer.Deserialize(System.IO.File.OpenRead("input.xml")) as Example;
        }

        /// <summary>
        /// The handler that will be attached to the SerializerClass' internal XmlSerializer.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Xml.Serialization.XmlElementEventArgs"/> instance containing the event data.</param>
        /// \date 9/8/2011 8:42 AM
        static void deserializer_UnknownElement(object sender, XmlElementEventArgs e)
        {
            Example obj = e.ObjectBeingDeserialized as Example;

            if (obj != null && e.Element.Name == "PAYLOAD")
            {
                obj.PayLoad = e.Element.OuterXml;
            }
        }
    }

    /// <summary>
    /// Example class which handles deserialization of an object.
    /// </summary>
    /// \author Kenneth Kaufmann
    /// \date 9/8/2011 8:41 AM
    public class SerializerClass
    {
        private XmlSerializer deserializer;
        private XmlElementEventHandler unknownElementHandler;   // Keep track of the handler that was added so we can remove
                                                                //  it later if we need to

        /// <summary>
        /// Initializes a new instance of the <see cref="SerializerClass"/> class.
        /// </summary>
        /// <param name="typeToSerialize">The type to serialize.</param>
        /// \date 9/8/2011 8:40 AM
        public SerializerClass(Type typeToSerialize)
        {
            deserializer = new XmlSerializer(typeToSerialize);
        }

        /// <summary>
        /// Attaches a handler for the UnknownElementHandler.
        /// </summary>
        /// <param name="handler"></param>
        public void SetUnknownElementHandler(XmlElementEventHandler handler)
        {
            if (unknownElementHandler != null) deserializer.UnknownElement -= unknownElementHandler;

            unknownElementHandler = handler;
            deserializer.UnknownElement += unknownElementHandler;
        }

        /// <summary>
        /// Deserializes the specified source data.
        /// </summary>
        /// <param name="sourceData">The source data.</param>
        /// <returns></returns>
        /// \date 9/8/2011 8:41 AM
        public object Deserialize(System.IO.Stream sourceData)
        {
            return deserializer.Deserialize(sourceData);
        }
    }

    [XmlRoot(ElementName = "ROOT")]
    public class Example
    {
        private string status;
        private string payLoad;

        public string PayLoad
        {
            get { return payLoad; }
            set { payLoad = value; }
        }

        [XmlElement(ElementName = "STATUS")]
        public string Status
        {
            get { return status; }
            set { status = value; }
        }
    }
}

Open in new window

0
 
LVL 1

Assisted Solution

by:amr-it
amr-it earned 0 total points
ID: 36528798
Thank you for your response. I ended up with a better solution, creating a generic class so it can be used for serialization.

    [XmlRoot(ElementName="ROOT")]
    public class Example<T> where T : new()
    {
        private string status;
        private T apiPayLoad = new T();

        [XmlElement(ElementName="APIPAYLOAD")]
        public T APIPayLoad
        {
            get { return apiPayLoad; }
            set { apiPayLoad = value; }
        }

        [XmlElement(ElementName = "STATUS")]
        public string Status
        {
            get { return status; }
            set { status = value; }
        }

    }

Open in new window



Usage:

        public static T DeserializeFromXml<T>(string xml)
        {
            T result;
            XmlSerializer ser = new XmlSerializer(typeof(T));
            ser.UnknownElement += new XmlElementEventHandler(ser_UnknownElement);
            using (TextReader tr = new StringReader(xml))
            {
                result = (T)ser.Deserialize(tr);
            }
            return result;
        }

Open in new window


Example<Person> PersonPayLoad = DeserializeFromXML<Example<Person>>(xml);

Open in new window

0
 
LVL 1

Author Closing Comment

by:amr-it
ID: 36555754
Comment for accepting own solution + expert:
Hopefully this generic solution also can be used for someone.
0

Featured Post

MS Dynamics Made Instantly Simpler

Make Your Microsoft Dynamics Investment Count  & Drastically Decrease Training Time by Providing Intuitive Step-By-Step WalkThru Tutorials.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
NetCrunch network monitor is a highly extensive platform for network monitoring and alert generation. In this video you'll see a live demo of NetCrunch with most notable features explained in a walk-through manner. You'll also get to know the philos…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…

623 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question