();
另外,如果是只是想改一下之前的Employees标签的名字的话,用这样一个注解:[XmlArray("NewName")]。
7,序列化null值属性
默认情况下,null值的属性是不会被序列化的,想想看为什么?
因为生成<DeptName />这样的序列化结果的话,没办法知道DeptName到底是null还是空字符串,所以比较好的解决方法是在序列化之前,把null字符串填充为空字符串。可以考虑写一个帮助方法,利用反射遍历一个对象里的所有字符串属性,将null设置为空字符串,当然了,实际的情况要考虑得更全面点,比如对象里还有对象,而且还包含可枚举对象的情况,估计得使用递归。篇幅问题,代码我就不贴了。
另外还有一种比较地道的做法,不需要改变对象的值,那就是在对象上加上[XmlElement(IsNullable = true)]注解,但这样带来的问题就是会在序列化生成的tag中多出一个xsi:nil="true"这样的属性来。
8,手工反序列化
有些情况实在太特殊,没办法直接用简单的Deserialize方法来反序列化,例如这个XML:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:DeliveryAddressUpdate_S10 xmlns:ns0="urn:ABC:GAIA:CN:LoadSetNoAndChineseDelAddr:ISC0186">
<ASNNNB>95175154 </ASNNNB>
<CHDANR>00476</CHDANR>
<ASCUID>SHD3SHD3</ASCUID>
<IGAAUC>上海</IGAAUC>
<IGAAUC>闵行区</IGAAUC>
<IGAAUC>七莘路8888号</IGAAUC>
<IGAAUC>XXXX大楼XXXX室</IGAAUC>
</Line>
<ASNNNB>124321 </ASNNNB>
<CHDANR>4321</CHDANR>
<ASCUID>4312</ASCUID>
<IGAAUC>上海</IGAAUC>
<IGAAUC>浦东新区</IGAAUC>
<IGAAUC>浦东大道9999号</IGAAUC>
<IGAAUC>YYYY大楼YYYY室</IGAAUC>
</Line>
</ns0:DeliveryAddressUpdate_S10>
首先根节点很奇葩,默认反序列化器不认,另外就是IGAAUC,重复多次,它的意图是说重复的这几个IGAAUC拼接在一起,生成一个地址,这个默认的反序列化显然做不到,手工读吧,参考代码如下:
List<Address> addrList = new List<Address>();
Address currentAddress = new Address();
XmlTextReader reader = new XmlTextReader(new MemoryStream(File.ReadAllBytes("test.xml")));
while (reader.Read()) {
if (reader.IsStartElement()) {
switch (reader.Name) {
case "Line":
currentAddress = new Address();
addrList.Add(currentAddress);
break;
case "ASNNNB":
currentAddress.Asnnb = reader.ReadString();
break;
case "CHDANR":
currentAddress.Chdanr = reader.ReadString();
break;
case "ASCUID":
currentAddress.Ascuid = reader.ReadString();
break;
case "IGAAUC":
currentAddress.Igaauc += reader.ReadString().Trim() + "\r\n";
break;
//addrList便是结果
9,强制闭合标签
默认情况下,如果XML的标签中的内容为空的话,标签就“自闭合”(self-closing),如:
<?xml version="1.0" encoding="gb2312"?>
<HCHX_DATA>
<TRANSMIT>
<MESSAGE_ID />
<MESSAGE_TYPE />
<EMS_NO />
<ORDER_NO />
<FUNCTION_CODE />
<CHK_RESULT />
<MESSAGE_DATE>0001-01-01T00:00:00</MESSAGE_DATE>
<SENDER_ID />
<SEND_ADDRESS />
<RECEIVER_ID />
<RECEIVER_ADDRESS />
<MESSAGE_SIGN />
<SEND_TYPE />
</TRANSMIT>
</HCHX_DATA>
而我们想要这样的效果:
<?xml version="1.0" encoding="gb2312"?>
<HCHX_DATA>
<TRANSMIT>
<MESSAGE_ID></MESSAGE_ID>
<MESSAGE_TYPE></MESSAGE_TYPE>
<EMS_NO></EMS_NO>
<ORDER_NO></ORDER_NO>
<FUNCTION_CODE></FUNCTION_CODE>
<CHK_RESULT></CHK_RESULT>
<MESSAGE_DATE>0001-01-01T00:00:00</MESSAGE_DATE>
<SENDER_ID></SENDER_ID>
<SEND_ADDRESS></SEND_ADDRESS>
<RECEIVER_ID></RECEIVER_ID>
<RECEIVER_ADDRESS></RECEIVER_ADDRESS>
<MESSAGE_SIGN></MESSAGE_SIGN>
<SEND_TYPE></SEND_TYPE>
</TRANSMIT>
</HCHX_DATA>
那就需要自己对XmlWriter进行一些修改,用一个新的序列化的方法:
public static string SerializeXml(object data) {
XmlSerializer s = new XmlSerializer(data.GetType());
using (Utf8Writer sw = new Utf8Writer()) {
XmlWriterSettings settings = new XmlWriterSettings();
settings.NewLineChars = Environment.NewLine;
settings.Indent = true;
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
using (XmlWriter writer = XmlWriter.Create(sw, settings)) {
s.Serialize(new XmlWriterForceFullEnd(writer), data, ns);
return sw.ToString();
上面的代码中还包括了XmlWriterSettings,它可以指定缩进,换行等格式。对于XmlWriter,用XmlWriterForceFullEnd进行一下包装,XmlWriterForceFullEnd的代码如下:
public class XmlWriterForceFullEnd : XmlWriter {
private readonly XmlWriter _baseWriter;
public XmlWriterForceFullEnd(XmlWriter w) {
_baseWriter = w;
//Force WriteEndElement to use WriteFullEndElement
public override void WriteEndElement() { _baseWriter.WriteFullEndElement(); }
public override void WriteFullEndElement() {
_baseWriter.WriteFullEndElement();
public override void Close() {
_baseWriter.Close();
public override void Flush() {
_baseWriter.Flush();
public override string LookupPrefix(string ns) {
return (_baseWriter.LookupPrefix(ns));
public override void WriteBase64(byte[] buffer, int index, int count) {
_baseWriter.WriteBase64(buffer, index, count);
public override void WriteCData(string text) {
_baseWriter.WriteCData(text);
public override void WriteCharEntity(char ch) {
_baseWriter.WriteCharEntity(ch);
public override void WriteChars(char[] buffer, int index, int count) {
_baseWriter.WriteChars(buffer, index, count);
public override void WriteComment(string text) {
_baseWriter.WriteComment(text);
public override void WriteDocType(string name, string pubid, string sysid, string subset) {
_baseWriter.WriteDocType(name, pubid, sysid, subset);
public override void WriteEndAttribute() {
_baseWriter.WriteEndAttribute();
public override void WriteEndDocument() {
_baseWriter.WriteEndDocument();
public override void WriteEntityRef(string name) {
_baseWriter.WriteEntityRef(name);
public override void WriteProcessingInstruction(string name, string text) {
_baseWriter.WriteProcessingInstruction(name, text);
public override void WriteRaw(string data) {
_baseWriter.WriteRaw(data);
public override void WriteRaw(char[] buffer, int index, int count) {
_baseWriter.WriteRaw(buffer, index, count);
public override void WriteStartAttribute(string prefix, string localName, string ns) {
_baseWriter.WriteStartAttribute(prefix, localName, ns);
public override void WriteStartDocument(bool standalone) {
_baseWriter.WriteStartDocument(standalone);
public override void WriteStartDocument() {
_baseWriter.WriteStartDocument();
public override void WriteStartElement(string prefix, string localName, string ns) {
_baseWriter.WriteStartElement(prefix, localName, ns);
public override WriteState WriteState {
get { return _baseWriter.WriteState; }
public override void WriteString(string text) {
_baseWriter.WriteString(text);
public override void WriteSurrogateCharEntity(char lowChar, char highChar) {
_baseWriter.WriteSurrogateCharEntity(lowChar, highChar);
public override void WriteWhitespace(string ws) {
_baseWriter.WriteWhitespace(ws);
其实关键的就是WriteEndElement这个方法,一行代码而已,但由于XmlWriter 是抽象类,很多虚方法得这么转一下。