Xml序列化未在XML中添加元素 [英] Xml serialize not adding elements in XML

查看:102
本文介绍了Xml序列化未在XML中添加元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个从XSD生成的类,正在对它进行序列化,我有一些情况会在特定条件下添加一些元素,这是我的类


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


[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;
        }
    }

}




属性FromDate和ToDate将在特定条件下添加,问题是当我为这两个属性提供值时,它没有在XML中添加这些值,也没有出现错误,其他元素也在添加.
其次,我在两种不同的情况下对此类进行序列化,一种情况下MOBNO应该以XML出现,而另一种情况下则不应出现,那么该怎么做才能实现此功能?

我尝试过的事情:

我也尝试添加XMLelement属性





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


<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();

推荐答案

这是一个详细的答案,涵盖了您和您自己身上的许多问题问题,但是您将来可能会遇到它们:
*元素与属性
*元素/属性名称与属性名称不同
*自定义元素&属性序列化:Enums& CData类型
*可选的节点序列化
*如何避免找不到文件"序列化异常

我已经发表了一些评论,这些评论有望有助于解释&为什么.
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.
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! :)


这篇关于Xml序列化未在XML中添加元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆