Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

DeSerialization - Element child nodes to string

Posted on 2011-09-07
5
Medium Priority
?
1,245 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 2000 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

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Create a Windows 10 custom Image with custom task bar and custom start menu using XML for deployment.
In this video, Percona Solution Engineer Dimitri Vanoverbeke discusses why you want to use at least three nodes in a database cluster. To discuss how Percona Consulting can help with your design and architecture needs for your database and infras…
In this video, Percona Solution Engineer Rick Golba discuss how (and why) you implement high availability in a database environment. To discuss how Percona Consulting can help with your design and architecture needs for your database and infrastr…
Suggested Courses

721 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