Click here to Skip to main content
15,949,686 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a class which I generated from XSD, I am serializing it, I have scenario that some elements will be added in specific condition, This is my class


C#
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd" , "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class ValidateIdEntityReqType
{
  private string aCCNOField;
     private string mOBNOField;
	  private MySearchType sEARCHTYPEField;
	  private System.DateTime fRMDATEField;
	      private System.DateTime tODATEField;
  public string ACCNO
    {
        get
        {
            return this.aCCNOField;
        }
        set
        {
            this.aCCNOField = value;
        }
    }
	
	  public string MOBNO
    {
        get
        {
            return this.mOBNOField;
        }
        set
        {
            this.mOBNOField = value;
        }
    }
	
	
	  public MySearchType SEARCHTYPE
    {
        get
        {
            return this.sEARCHTYPEField;
        }
        set
        {
            this.sEARCHTYPEField = value;
        }
    }

	
	    [System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
    public System.DateTime FRMDATE
    {
        get
        {
            return this.fRMDATEField;
        }
        set
        {
            this.fRMDATEField = value;
        }
    }
	
	
	    [System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
    public System.DateTime TODATE
    {
        get
        {
            return this.tODATEField;
        }
        set
        {
            this.tODATEField = value;
        }
    }

}



The properties FromDate and ToDate will be added in specific condition,The problem is when I am providing values to these two properties,it is not adding these in XML,and no error is appearing as well,Other elements are adding.

Second I am serializing this class in two different cases, In one case MOBNO should appear in XML and in other case it should not appear,what should I do to implement this feature?

What I have tried:

I have tried adding XMLelement Attribute too


C#
<pre> string output = string.Empty;
        XmlSerializer xsSubmit = new XmlSerializer(typeof(MyRequestClass));
        using (StringWriter sww = new StringWriter())
            {
                using (XmlWriter writer = XmlWriter.Create(sww))
                {
                    //  sww.WriteLine(@"<?xml version=""1.0"" encoding=""UTF-8""?>");
                    xsSubmit.Serialize(writer , env);
                    output = sww.ToString();
                }
            }

        var doc = XDocument.Parse(output);
        Enumerable<XElement> emptyElements;
        emptyElements = from descendant in doc.Descendants()
                        where descendant.IsEmpty || string.IsNullOrWhiteSpace(descendant.Value)
                        select descendant;
        emptyElements.Remove();
        doc.Root.RemoveAttributes();
        output = doc.ToString();
Posted
Updated 14-Mar-17 2:47am
v3
Comments
madhav_jain 14-Mar-17 5:42am    
give us the code what u have tried for serializing the class..
Syed Salman Raza Zaidi 14-Mar-17 7:43am    
See my updated question

1 solution

This is a detailed answer that covers a number of points both in and not in your question however you may encounter them in future:
* Elements versus Attributes
* Element/Attribute names different to property names
* Custom element & attribute serialization: Enums & CData types
* Optional node serialization
* How to avoid the "file not found" serialization exception

I've included some comments that will hopefully help explain how & why.
C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace WorkingWithXml
{
    class Program
    {
        static void Main(string[] args)
        {
            var data = new XmlRootClass
            {
                Id = 12345567890123456789,
                Title = "Widget",
                Amount = new AmountType { Value = 123.45, CurrencyID = CurrencyCodeType.USD },
                Description = new CData("This is a description with embedded html"),
            };

            var raw = XmlConverter.FromClass(data);

            var newData = XmlConverter.ToClass<XmlRootClass>(raw);

            Debugger.Break();
        }
    }


    // Naming a root element
    [XmlRoot(ElementName = "Product", IsNullable = false)]
    public class XmlRootClass
    {
        [XmlElement("id123)")]
        public ulong Id { get; set; }
        public string Title { get; set; }

        // a value type element with an attribute
        [XmlElement("amt")]
        public AmountType Amount { get; set; }

        // Custom element data format
        [XmlElement("description", typeof(CData))]
        public CData Description { get; set; }

        // example of optional serialization
        [XmlElement, DefaultValue(false)]
        public bool IsAvailable { get; set; }

    }

    public class AmountType
    {
        [XmlText]
        public double Value { get; set; }

        //enum type attribute (same works with an XmlElement)
        [XmlAttribute("currencyID")]
        public string CurrencyID_intern { get; set; }
        [XmlIgnore]
        public CurrencyCodeType? CurrencyID
        {
            get
            {
                return CurrencyID_intern.StringToEnum<CurrencyCodeType?>
                  (CurrencyCodeType.CustomCode, isNullable: true);
            }
            set { CurrencyID_intern = value.ToString(); }
        }
    }

    public enum CurrencyCodeType
    {
        CustomCode, // missing from list
        AUD,        // Australia dollar
        JPY,        // Japanese yen
        USD,        // US dollar
    }

    public static class EnumExtensions
    {
        public static T StringToEnum<T>(this string input, T defaultValue = default(T), bool isNullable = false)
        {
            T outType;
            if (string.IsNullOrEmpty(input) &&
                isNullable &&
                Nullable.GetUnderlyingType(typeof(T)) != null &&
                Nullable.GetUnderlyingType(typeof(T)).GetElementType() == null)
                return default(T);
            return input.EnumTryParse(out outType) ? outType : defaultValue;
        }

        public static bool EnumTryParse<T>(this string input, out T theEnum)
        {
            Type type = Nullable.GetUnderlyingType(typeof(T)) != null ? Nullable.GetUnderlyingType(typeof(T)) : typeof(T);

            foreach (string en in Enum.GetNames(type))
                if (en.Equals(input, StringComparison.CurrentCultureIgnoreCase))
                {
                    theEnum = (T)Enum.Parse(type, input, true);
                    return true;
                }
            theEnum = default(T);
            return false;
        }
    }

    public static class XmlConverter
    {
        public static string FromClass<T>(T data, XmlSerializerNamespaces ns = null)
        {
            string response = string.Empty;

            var ms = new MemoryStream();
            try
            {
                ms = FromClassToStream(data, ns);

                if (ms != null)
                {
                    ms.Position = 0;
                    using (var sr = new StreamReader(ms))
                        response = sr.ReadToEnd();
                }

            }
            finally
            {
                // don't want memory leaks...
                ms.Flush();
                ms.Dispose();
                ms = null;
            }

            return response;
        }

        public static MemoryStream FromClassToStream<T>(T data, XmlSerializerNamespaces ns = null)
        {
            var stream = default(MemoryStream);

            if (!EqualityComparer<T>.Default.Equals(data, default(T)))
            {
                var settings = new XmlWriterSettings()
                {
                    Encoding = Encoding.UTF8,
                    Indent = true,
                    ConformanceLevel = ConformanceLevel.Auto,
                    CheckCharacters = true,
                    OmitXmlDeclaration = false
                };

                XmlSerializer serializer = XmlSerializerFactoryNoThrow.Create(typeof(T));

                stream = new MemoryStream();
                using (XmlWriter writer = XmlWriter.Create(stream, settings))
                {
                    serializer.Serialize(writer, data, ns);
                    writer.Flush();
                }
                stream.Position = 0;
            }
            return stream;
        }

        public static T ToClass<T>(string data)
        {
            var response = default(T);

            if (!string.IsNullOrEmpty(data))
            {
                var settings = new XmlReaderSettings() { IgnoreWhitespace = true };

                XmlSerializer serializer = XmlSerializerFactoryNoThrow.Create(typeof(T));

                XmlReader reader = XmlReader.Create(new StringReader(data), settings);
                response = (T)Convert.ChangeType(serializer.Deserialize(reader), typeof(T));
            }
            return response;
        }
    }

    // ref: http://stackoverflow.com/questions/1127431/xmlserializer-giving-filenotfoundexception-at-constructor/39642834#39642834
    public static class XmlSerializerFactoryNoThrow
    {
        public static Dictionary<Type, XmlSerializer> cache = new Dictionary<Type, XmlSerializer>();

        private static object SyncRootCache = new object();

        public static XmlSerializer Create(Type type)
        {
            XmlSerializer serializer;

            lock (SyncRootCache)
                if (cache.TryGetValue(type, out serializer))
                    return serializer;

            lock (type) //multiple variable of type of one type is same instance
            {
                //constructor XmlSerializer.FromTypes does not throw the first chance exception           
                serializer = XmlSerializer.FromTypes(new[] { type })[0];
            }

            lock (SyncRootCache) cache[type] = serializer;
            return serializer;
        }
    }

    // ref: http://codercorner.blogspot.com.au/2006/11/serialization-and-cdata.html
    public class CData : IXmlSerializable
    {
        public CData()
        { }

        public CData(string text)
        {
            this.text = text;
        }

        private string text;
        public string Text => text;

        XmlSchema IXmlSerializable.GetSchema() => null;

        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            text = reader.ReadElementContentAsString();
            reader.Read(); // without this line, you will lose value of all other fields
        }

        void IXmlSerializable.WriteXml(XmlWriter writer)
        {
            writer.WriteCData(text);
        }

        public override string ToString() => text;
    }
}

Start up a new Console app, paste in ande run to see what it does.

Hope it helps! :)
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900