Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

DeSerialization - Element child nodes to string

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

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

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

Browsing the questions asked to the Experts of this forum, you will be amazed to see how many times people are headaching about monster regular expressions (regex) to select that specific part of some HTML or XML file they want to extract. The examp…
The article shows the basic steps of integrating an HTML theme template into an ASP.NET MVC project
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
Loops Section Overview

971 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