问题描述
我有一个从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();
推荐答案
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中添加元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!