0

Need your help in setting the xml attributes for XML deserialization.

This is my input xml:

<form>
<question id="QnA">
<answer>AnswerforA</answer>
</question>
<question id="QnB">
<answer>AnswerforB</answer>
</question>
<question id="QnC">
<answer>AnswerforC</answer>
</question>
</form>

The ids of each question element tag correspond to a class property and its value is the innertext of the corresponding answer element.

The .cs file will look like

 public class Test
{

   private string qnaAns;    
   private string qnbAns;   
   private string qncAns;   

    public string QnA
    {
    get{ return qnaAns;}
    set{qnaAns = value;}
    }

    public string QnB
    {
    get{ return qnbAns;}
    set{qnbAns = value;}
    }

    public string QnC
    {
    get{ return qncAns;}
    set{qncAns = value;}
    }
}

and I use the follwing code for deserialization

XmlSerializer ser = new XmlSerializer(typeof(Test));

XmlReader xr = new xmlReader(inputxml);

Test t = ser.Deserialize(xr) as Test;

Please let me know how to set the XML element/attribute for the Test class to achieve this.

Thanks for your time.

2
  • I'm a little too lazy to look through your code and figure out what you're having trouble with, so please let us know what's the issue you're having. Commented Oct 17, 2011 at 13:26
  • You should either structure your DTO to represent the data you are trying to serialize, or you would have to implement IXmlSerializable (not fun). See Matt's answer for an example of the first (and correct, IMO) option. Commented Oct 17, 2011 at 13:31

1 Answer 1

2
 [XmlRoot("form")]
    public class Form
    {
        [XmlElement("question")]
        public List<Question> Questions { get; set; }

        public Form()
        {
            Questions = new List<Question>();
        }
    }
    public struct Question
    {
        [XmlAttribute("id")]
        public string ID { get; set; }

        [XmlElement("answer")]
        public string Answer { get; set; }
    }

Then to serialize, I use the following extensions:

public static bool XmlSerialize<T>(this T item, string fileName) 
        { 
            return item.XmlSerialize(fileName, true); 
        } 
        public static bool XmlSerialize<T>(this T item, string fileName, bool removeNamespaces) 
        { 
            object locker = new object(); 

            XmlSerializerNamespaces xmlns = new XmlSerializerNamespaces(); 
            xmlns.Add(string.Empty, string.Empty); 

            XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); 

            XmlWriterSettings settings = new XmlWriterSettings(); 
            settings.Indent = true; 
            settings.OmitXmlDeclaration = true; 

            lock (locker) 
            { 
                using (XmlWriter writer = XmlWriter.Create(fileName, settings)) 
                { 
                    if (removeNamespaces) 
                    { 
                        xmlSerializer.Serialize(writer, item, xmlns); 
                    } 
                    else { xmlSerializer.Serialize(writer, item); } 

                    writer.Close(); 
                } 
            } 

            return true; 
        } 
        public static T XmlDeserialize<T>(this string s) 
        { 
            object locker = new object(); 
            StringReader stringReader = new StringReader(s); 
            XmlTextReader reader = new XmlTextReader(stringReader); 
            try 
            { 
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); 
                lock (locker) 
                { 
                    T item = (T)xmlSerializer.Deserialize(reader); 
                    reader.Close(); 
                    return item; 
                } 
            } 
            finally 
            { 
                if (reader != null) 
                { reader.Close(); } 
            } 
        } 
        public static T XmlDeserialize<T>(this FileInfo fileInfo) 
        { 
            string xml = string.Empty; 
            using (FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read)) 
            { 
                using (StreamReader sr = new StreamReader(fs)) 
                { 
                    return sr.ReadToEnd().XmlDeserialize<T>(); 
                } 
            } 
        } 

Hope this helps.

PS - The extensions came from my library on codeproject: http://www.codeproject.com/KB/dotnet/MBGExtensionsLibrary.aspx

Sign up to request clarification or add additional context in comments.

4 Comments

You can deserialize like this: Form form = new FileInfo("c:\\test.xml").XmlDeserialize<Form>();
not sure the extension methods are really worth it, but the overall approach (having a DTO model that mirrors the xml) is absolutely the right one.
Thanks for your answer. But my intention is not to have the List<Question> with two elements inside. Based on your code , I have to set the QnA property as public string QnA { get { return Questions[Questions.FindIndex(t => t.ID=="QnA")].Answer; } set { ; } } .. Is it possible to set the properties directly? Thanks.
Also, Also, is it possible to specify another parameter "section" along with "question" for the question object i.e The form can also be <form> <question id="QnA"> <answer>AnswerforA</answer> </question> <section id="QnB"> <answer>AnswerforB</answer> </section> </form>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.