Contents

使用XmlSerializer,序列化與反序列化

使用XmlSerializer,XML序列化(建立)與反序列化(讀取)

雖然現在大多數是使用JSON作為資料傳輸格式,但偶爾還是會遇到操作XML狀況,特別是遇到使用SOAP情形下,不得不說,XML與JSON在轉換物件的便利性還是有些許差距,久不用實在容易忘記,最近剛好又碰到,就順勢整理一下筆記吧

環境

  • XmlSerializer
  • LinqPad 5
Note
XmlSerializer 在LinqPad 6 .NET Core 3.1,可能會出現 NotSupportedException: A non-collectible assembly may not reference a collectible assembly. 錯誤,或許是下列問題 請參考 https://github.com/dotnet/runtime/issues/1388

XML常使用Stream作為輸出入格式,這邊為了方便,直接使用LinqPad中的Console.Out功能呈現結果

各種屬性設置後XML檔案呈現結果

這是下列實作產生出來的結果,也是大致的對照表,我通常會先草擬一份XML檔,然後再使用Visual Studio 的「貼上XML做為類別」功能,對照下表,整理一份比較常見的類別檔

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class XMLObject
{
	// <Element1>Element1</Element1>
	public string Element1 { get; set; }

	// <Element2>Element2</Element2>
	[XmlElement]
	public string Element2 { get; set; }

	// <NewElement>Element3</NewElement>
	[XmlElement("NewElement")]
	public string Element3 { get; set; }

	// 節點上的Attribute
	// <XMLObject Attribute1="Attribute1"></XMLObject>
	[XmlAttribute]
	public string Attribute1 { get; set; }

	//<SubItem1>
	// <ItemName>Name1</ItemName>
	//</SubItem1>
	public SubItem SubItem1 { get; set; }

	// <SubItems2>
	//   <SubItem>
	//     <ItemName>Name2</ItemName>
	//   </SubItem>
	// </SubItems2>
	public List<SubItem> SubItems2 { get; set; }

	// <Items>
	//   <SubItem>
	//      <ItemName>Name3</ItemName>
	//	 </SubItem>
	// </Items>
	[XmlArray("Items")]
	public List<SubItem> SubItems3 { get; set; }

	// <SubItems4>
	//   <ItemName>Name4</ItemName>
	// </SubItems4>
	[XmlElement]
	public List<SubItem> SubItems4 { get; set; }
}

public class SubItem
{
	public string ItemName { get;set; }
}

實作

序列化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
XMLObject xml = new XMLObject()
{
	Element1 = "Element1",
	Element2 = "Element2",
	Element3 = "Element3",
	Attribute1 = "Attribute1",
	SubItem1 = new SubItem() { ItemName = "Name1" },
	SubItems2 = new List<SubItem>()
	{
		new SubItem { ItemName = "Name2" }
	},
	SubItems3 = new List<SubItem>()
	{
		new SubItem { ItemName = "Name3" }
	},
	SubItems4 = new List<SubItem>()
	{
		new SubItem { ItemName = "Name4" }
	},
};
// using System.Xml.Serialization
XmlSerializer mySerializer = new XmlSerializer(typeof(XMLObject));
mySerializer.Serialize(Console.Out, xml);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-16"?>
<XMLObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Attribute1="Attribute1">
  <Element1>Element1</Element1>
  <Element2>Element2</Element2>
  <NewElement>Element3</NewElement>
  <SubItem1>
    <ItemName>Name1</ItemName>
  </SubItem1>
  <SubItems2>
    <SubItem>
      <ItemName>Name2</ItemName>
    </SubItem>
  </SubItems2>
  <Items>
    <SubItem>
      <ItemName>Name3</ItemName>
    </SubItem>
  </Items>
  <SubItems4>
    <ItemName>Name4</ItemName>
  </SubItems4>
</XMLObject>

反序列

1
2
3
4
5
6
7
8
// 請留意是否有Encoding問題
XmlSerializer mySerializer = new XmlSerializer(typeof(XMLObject));
using (var fileStream = new FileStream(@"C:\Data\myXML.xml", FileMode.Open))
{
	// 或是接收API的Stream資料進行轉換
	var xmlObject = mySerializer.Deserialize(fileStream) as XMLObject;
	xmlObject.Dump();
}
/static/XML序列化與反序列化_c38737558bee476985d7947962ff7e25/_2020-07-21_161755.png

參考

XML 序列化的範例

檔案

XML.linq