先來看xml
<?xml version="1.0"?> <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Person> <Name>小莫</Name> <Age>20</Age> <Books> <Book> <Title>馬列主義</Title> <ISBN>SOD1323DS</ISBN> </Book> </Books> </Person> <Person> <Name>小紅</Name> <Age>20</Age> <Books> <Book> <Title>思想</Title> <ISBN>SID1323DSD</ISBN> </Book> </Books> </Person> </root>
這個xml包含多個Person對象,每個Person對象又包含一個Books對象和多個book對象,反序列化XML時關鍵是看怎么理解xml的結構,理解正確了就很好構造對應的類,理解錯了可能就陷入坑里。
首先root是整個文件的根節點,它是由多個Person組成的。
[System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] [System.Xml.Serialization.XmlRootAttribute("root", IsNullable = false)] public class BaseInfo { [System.Xml.Serialization.XmlElementAttribute("Person")] public List<Person> PersonList { get; set; } }
再看Person對象,Person是由name和age兩個屬性和一個Books對象組成,Person可以定義成
[System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] [System.Xml.Serialization.XmlRootAttribute("Person", IsNullable = false)] public class Person { public string Name { get; set; } public int Age { get; set; } [System.Xml.Serialization.XmlElementAttribute("Books")] public Books Books { get; set; } }
這里理解的關鍵是把下面這小段xml理解成一個包含多個Book的對象,而不是把它理解成book的數組
<Books> <Book> <Title>毛澤思想</Title> <ISBN>SID1323DSD</ISBN> </Book> </Books>
如果把她理解成一個數據就容易把Person定義成
[System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] [System.Xml.Serialization.XmlRootAttribute("Person", IsNullable = false)] public class Person { public string Name { get; set; } public int Age { get; set; } [System.Xml.Serialization.XmlElementAttribute("Books")] public List<Book> Books { get; set; } }
而book的定義如下
[System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] [System.Xml.Serialization.XmlRootAttribute("Book", IsNullable = false)] public class Book { public string Title { get; set; } public string ISBN { get; set; } }
序列化生成的xml不包含Book節點
,生成的xml如下
<?xml version="1.0"?> <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Person> <Name>小莫</Name> <Age>20</Age> <Books> <Title>馬列主義</Title> <ISBN>SOD1323DS</ISBN> </Books> </Person> <Person> <Name>小紅</Name> <Age>20</Age> <Books> <Title>毛澤思想</Title> <ISBN>SID1323DSD</ISBN> </Books> </Person> </root>
之所以出現上面的情況是因為:
public List<Book> Books { get; set; }
和Book同屬一個節點層次,在List<Book> Books上顯式指定了屬性名稱Books,那么這個節點就是Books,跟Book上定義指定的[System.Xml.Serialization.XmlRootAttribute("Book", IsNullable = false)]
沒有關系,它是用來指示Book是跟節點時的名稱。
或者可以這樣理解xml是由多個節點組成的,而Book類定義不是一個節點,它只是一個定義,要想xml中出現book,就需要再加一個節點,我們把Person節點加到Books對象中
[System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public class Books { [System.Xml.Serialization.XmlElementAttribute("Book")] public List<Book> BookList { get; set; } }
這樣就多出了一個節點,再結合剛開始的person定義就能序列化出正確的xml了
完整的代碼
[System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] [System.Xml.Serialization.XmlRootAttribute("root", IsNullable = false)] public class BaseInfo { [System.Xml.Serialization.XmlElementAttribute("Person")] public List<Person> PersonList { get; set; } } [System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] [System.Xml.Serialization.XmlRootAttribute("Person", IsNullable = false)] public class Person { public string Name { get; set; } public int Age { get; set; } [System.Xml.Serialization.XmlElementAttribute("Books")] public Books Books { get; set; } } [System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public class Books { [System.Xml.Serialization.XmlElementAttribute("Book")] public List<Book> BookList { get; set; } } [System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] [System.Xml.Serialization.XmlRootAttribute("Book", IsNullable = false)] public class Book { public string Title { get; set; } public string ISBN { get; set; } }
static void Main(string[] args) { BaseInfo baseInfo = new BaseInfo(); List<Person> personList = new List<Person>(); Person p1 = new Person(); p1.Name = "小莫"; p1.Age = 20; List<Book> books = new List<Book>(); Book book = new Book(); book.Title = "馬列主義"; book.ISBN = "SOD1323DS"; books.Add(book); p1.Books = new Books(); p1.Books.BookList = books; Person p2 = new Person(); p2.Name = "小紅"; p2.Age = 20; List<Book> books2 = new List<Book>(); Book book2 = new Book(); book2.Title = "毛澤思想"; book2.ISBN = "SID1323DSD"; books2.Add(book2); p2.Books =new Books(); p2.Books.BookList = books2; personList.Add(p1); personList.Add(p2); baseInfo.PersonList = personList; string postXml2 = SerializeHelper.Serialize(typeof(BaseInfo), baseInfo); Console.ReadLine(); } }
序列化用到的類
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml.Serialization; using System.IO; using System.Xml; namespace ConsoleApplication1 { public class SerializeHelper { public static string Serialize(Type type, object o) { string result = string.Empty; try { XmlSerializer xs = new XmlSerializer(type); MemoryStream ms = new MemoryStream(); xs.Serialize(ms, o); ms.Seek(0, SeekOrigin.Begin); StreamReader sr = new StreamReader(ms); result = sr.ReadToEnd(); ms.Close(); } catch (Exception ex) { throw new Exception("對象序列化成xml時發生錯誤:" + ex.Message); } return result; } /// <summary> /// 序列化XML時不帶默認的命名空間xmlns /// </summary> /// <param name="type"></param> /// <param name="o"></param> /// <returns></returns> public static string SerializeNoneNamespaces(Type type, object o) { string result = string.Empty; try { XmlSerializer xs = new XmlSerializer(type); MemoryStream ms = new MemoryStream(); XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", "");//Add an empty namespace and empty value xs.Serialize(ms, o, ns); ms.Seek(0, SeekOrigin.Begin); StreamReader sr = new StreamReader(ms); result = sr.ReadToEnd(); ms.Close(); } catch (Exception ex) { throw new Exception("對象序列化成xml時發生錯誤:" + ex.Message); } return result; } /// <summary> /// 序列化時不生成XML聲明和XML命名空間 /// </summary> /// <param name="type"></param> /// <param name="o"></param> /// <returns></returns> public static string SerializeNoNamespacesNoXmlDeclaration(Type type, object o) { string result = string.Empty; try { XmlSerializer xs = new XmlSerializer(type); MemoryStream ms = new MemoryStream(); XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); XmlWriterSettings settings = new XmlWriterSettings(); settings.OmitXmlDeclaration = true;//不編寫XML聲明 XmlWriter xmlWriter = XmlWriter.Create(ms, settings); ns.Add("", "");//Add an empty namespace and empty value xs.Serialize(xmlWriter, o, ns); ms.Seek(0, SeekOrigin.Begin); StreamReader sr = new StreamReader(ms); result = sr.ReadToEnd(); ms.Close(); } catch (Exception ex) { throw new Exception("對象序列化成xml時發生錯誤:" + ex.Message); } return result; } public static object Deserialize(Type type, string xml) { object root = new object(); try { XmlSerializer xs = new XmlSerializer(type); MemoryStream ms = new MemoryStream(); StreamWriter sw = new StreamWriter(ms); sw.Write(xml); sw.Flush(); ms.Seek(0, SeekOrigin.Begin); root = xs.Deserialize(ms); ms.Close(); } catch (Exception ex) { throw new Exception("xml轉換成對象時發生錯誤:" + ex.Message); } return root; } } }
再看一個例子,簡單數組類型的序列化
<?xml version="1.0"?> <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <barcodes> <barcode>AAA</barcode> <barcode>BBB</barcode> </barcodes> </root>
我們經常搞半天不知道要怎么書寫上面xml對應的類,總是容易出現上面說過的錯誤,關鍵還是看怎么理解barcodes,和上面的例子類似,這里只寫類怎么創建
[System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] [System.Xml.Serialization.XmlRootAttribute("root", IsNullable = false)] public class DownLoadPDFRequest { [System.Xml.Serialization.XmlElementAttribute("barcodes")] public barcoders barcodes { get; set; } } [System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] //[System.Xml.Serialization.XmlRootAttribute("barcoders", IsNullable = false)] public class barcoders { private List<string> _barcode; [System.Xml.Serialization.XmlElementAttribute("barcode")] public List<string> BarCode { get { return _barcode; } set { _barcode = value; } } }
static void Main(string[] args) { DownLoadPDFRequest request = new DownLoadPDFRequest(); List<barcoders> barcodes = new List<barcoders>(); List<string> bars=new List<string>(); bars.Add("AAA"); bars.Add("BBB"); request.barcodes = new barcoders();; request.barcodes.BarCode = bars; string postXml = SerializeHelper.Serialize(typeof(DownLoadPDFRequest), request); }