可以使用XmlSerializer直接序列化和反序列化xml
反序列化如以下程式碼
private T? XmlDeseriallize<T>(string filePath)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
var xmlReader = System.Xml.XmlReader.Create(fileStream);
var deserializedObject = (T?)serializer.Deserialize(xmlReader);
return deserializedObject;
}
}
呼叫方法
var udidEntity = XmlDeseriallize<udid>(filePath)
其中,xml檔案內容示例:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<udid version="1.0">
<header frequency="daily" id="20240520235039" type="DELTA_INCREMENTAL">
<downloadFilePart>1</downloadFilePart>
<downloadFileTotalParts>1</downloadFileTotalParts>
<numberRkeyecordXML>3480</numberRkeyecordXML>
<numberRecordsDatabase>3480</numberRecordsDatabase>
<creationDate>2024-05-20 23:50:39</creationDate>
</header>
<devices>
<device>
<zxxsdycpbs>06974652782710</zxxsdycpbs>
<cpbsbmtxmc>GS1</cpbsbmtxmc>
<cpbsfbrq>2024-05-20</cpbsfbrq>
<zxxsdyzsydydsl>1</zxxsdyzsydydsl>
<sydycpbs></sydycpbs>
<bszt>一維碼</bszt>
<sfyzcbayz>是</sfyzcbayz>
<zcbacpbs></zcbacpbs>
<sfybtzjbs>否</sfybtzjbs>
<btcpbsyzxxsdycpbssfyz></btcpbsyzxxsdycpbssfyz>
<btcpbs></btcpbs>
<cpmctymc>一次性使用吸引活檢針及附件</cpmctymc>
<spmc></spmc>
<ggxh>CLA2505</ggxh>
<sfwblztlcp>否</sfwblztlcp>
<cpms>吸引活檢針25G×50mm</cpms>
<cphhhbh>202710</cphhhbh>
<yflbm></yflbm>
<qxlb>器械</qxlb>
<flbm>14-01-09</flbm>
<tyshxydm>91430300MA4RGKD89R</tyshxydm>
<zczbhhzbapzbh>湘械注準20222141907</zczbhhzbapzbh>
<ylqxzcrbarmc>湖南省拓川醫療科技有限公司</ylqxzcrbarmc>
<ylqxzcrbarywmc></ylqxzcrbarywmc>
<ybbm>C01060200700003149010000032</ybbm>
<cplb>耗材</cplb>
<cgzmraqxgxx>說明書或標籤上面不包含MR安全性資訊</cgzmraqxgxx>
<sfbjwycxsy>是</sfbjwycxsy>
<zdcfsycs></zdcfsycs>
<sfwwjbz>是</sfwwjbz>
<syqsfxyjxmj>否</syqsfxyjxmj>
<mjfs></mjfs>
<qtxxdwzlj></qtxxdwzlj>
<tsrq></tsrq>
<scbssfbhph>是</scbssfbhph>
<scbssfbhxlh>否</scbssfbhxlh>
<scbssfbhscrq>是</scbssfbhscrq>
<scbssfbhsxrq>是</scbssfbhsxrq>
<tscchcztj>本產品應貯存在通風良好、無腐蝕性氣體、清潔的環境內。儲存溫度範圍為0℃至30℃,相對溼度不超過85%。本產品應使用無腐蝕性氣體、對產品無汙染的運輸工具運輸,嚴禁日曬雨淋,搬運時應注意防止包裝破損。</tscchcztj>
<tsccsm></tsccsm>
<deviceRecordKey>069746527827102024042904331816</deviceRecordKey>
<versionNumber>1</versionNumber>
<versionTime>2024-05-20</versionTime>
<versionStauts>新增</versionStauts>
<correctionNumber>0</correctionNumber>
<correctionRemark></correctionRemark>
<correctionTime></correctionTime>
</device>
<device>
<zxxsdycpbs>06931450103406</zxxsdycpbs>
<cpbsbmtxmc>GS1</cpbsbmtxmc>
<cpbsfbrq>2024-05-20</cpbsfbrq>
<zxxsdyzsydydsl>1</zxxsdyzsydydsl>
<sydycpbs></sydycpbs>
<bszt>一維碼,二維碼,RFID</bszt>
<sfyzcbayz>是</sfyzcbayz>
<zcbacpbs></zcbacpbs>
<sfybtzjbs>否</sfybtzjbs>
<btcpbsyzxxsdycpbssfyz></btcpbsyzxxsdycpbssfyz>
<btcpbs></btcpbs>
<cpmctymc>定製式活動義齒</cpmctymc>
<spmc></spmc>
<ggxh>鈷鉻鉬支架可摘全口義齒 1402040900</ggxh>
<sfwblztlcp>否</sfwblztlcp>
<cpms>由合成樹脂牙、卡環、樹脂基託及連線體組成</cpms>
<cphhhbh></cphhhbh>
<yflbm></yflbm>
<qxlb>器械</qxlb>
<flbm>17-06-04</flbm>
<tyshxydm>91441900675189913A</tyshxydm>
<zczbhhzbapzbh>粵械注準20152171212</zczbhhzbapzbh>
<ylqxzcrbarmc>東莞市帕菲克義齒科技有限公司</ylqxzcrbarmc>
<ylqxzcrbarywmc></ylqxzcrbarywmc>
<ybbm></ybbm>
<cplb>耗材</cplb>
<cgzmraqxgxx>說明書或標籤上面不包含MR安全性資訊</cgzmraqxgxx>
<sfbjwycxsy>否</sfbjwycxsy>
<zdcfsycs></zdcfsycs>
<sfwwjbz>否</sfwwjbz>
<syqsfxyjxmj>否</syqsfxyjxmj>
<mjfs></mjfs>
<qtxxdwzlj></qtxxdwzlj>
<tsrq></tsrq>
<scbssfbhph>是</scbssfbhph>
<scbssfbhxlh>是</scbssfbhxlh>
<scbssfbhscrq>是</scbssfbhscrq>
<scbssfbhsxrq>否</scbssfbhsxrq>
<tscchcztj></tscchcztj>
<tsccsm></tsccsm>
<deviceRecordKey>0693145010340620240518045505448</deviceRecordKey>
<versionNumber>1</versionNumber>
<versionTime>2024-05-20</versionTime>
<versionStauts>新增</versionStauts>
<correctionNumber>0</correctionNumber>
<correctionRemark></correctionRemark>
<correctionTime></correctionTime>
<contactList>
<contact>
<qylxrcz></qylxrcz>
<qylxryx>2074662804@qq.com</qylxryx>
<qylxrdh>0769-85160532</qylxrdh>
</contact>
</contactList>
</device>
</devices>
</udid>
C# 型別示例:
//為從XML反序列化來而做準備
public class udid
{
public header header { get; set; } = new();
[XmlArrayItem("device")]//序列化反序列化時,當DeviceInfoDto對應的xml中元素的名字不是DeviceInfoDto而是device時,用該特性指定型別DeviceInfoDto對應的在xml中的元素的名字device。如果不這麼做,則需要變能,改以下程式碼中List<DeviceInfoDto>為List<device>其中device為一個繼承自DeviceInfoDto型別的子類
public List<DeviceInfoDto> devices { get; set; } = new();
}
public class header
{
[XmlAttribute("frequency")]
public string Frequency { get; set; } = string.Empty;
[XmlAttribute("id")]
public string Id { get; set; } = string.Empty;
[XmlAttribute("type")]
public string Type { get; set; } = string.Empty;
public int downloadFilePart { get; set; }
public int downloadFileTotalParts { get; set; }
public int numberRkeyecordXML { get; set; }
public int numberRecordsDatabase { get; set; }
#region 當直接使用一個型別為Datetime屬性名為creationDate來在反序列化xml檔案中的日期時間型別的接收者時,反序列化會報錯:【字串“2020-07-31 09:29:16”不是有效的AllXsd值】。於是採入引入一箇中間屬性stringCreationDate(型別為string)和儲存其值的欄位_creationDate(型別為DateTime)的方式,執行過程1.當反序列化時從xml檔案讀取元素名為creationDate的元素值並透過stringCreationDate的set訪問器將其值在轉值為DateTime型別後存放於欄位_creationDate中 2.當C#程式碼中其他地方要訪問這個值時,就從creationDate屬性的get訪問器傳遞出_creationDate欄位的值。缺點:需引入不必要的屬性和欄位,而且屬性名還必須是public的,這會讓外部訪問者對這個中間屬性感到疑惑。
private DateTime _creationDate;
[XmlElement(ElementName = "creationDate")]
public string stringCreationDate { get => _creationDate.ToString("yyyy-MM-dd HH:mm:ss"); set => _creationDate = Convert.ToDateTime(value); }
[XmlIgnore]
public DateTime creationDate { get => _creationDate; }
#endregion
}
public class DeviceInfoDto
{
[XmlElement("cpmctymc")]//用來在做xml反序列化時,指定本屬性對應到xml檔案中的標籤的名字。(注意還有一個是XmlAttribute它是指對應到xml標籤的屬性名字)
public string CPMCTYMC { get; set; }
[XmlElement("spmc")]
public string SPMC { get; set; }
[XmlElement("ggxh")]
public string GGXH { get; set; }
[XmlElement("cpms")]
public string CPMS { get; set; }
[XmlElement("tyshxydm")]
public string TYSHXYDM { get; set; }
[XmlElement("flbm")]
public string CategoryCode { get; set; }
[XmlElement("deviceRecordKey")]
public string deviceRecordKey { get; set; }
[XmlElement("versionTime")]
public DateTime versionTime { get; set; }
[XmlElement("zxxsdycpbs")]
public string DI { get; set; }
[XmlElement("cpbsbmtxmc")]
public string DeviceCodeType { get; set; }
[XmlElement("ylqxzcrbarmc")]
public string Manufacturer { get; set; }
[XmlElement("ylqxzcrbarywmc")]
public string EnManufacturer { get; set; }
[XmlElement("zczbhhzbapzbh")]
public string RegistrationCertificateNo { get; set; }
[XmlElement("versionStauts")]
public string versionStauts { get; set; }
}
注意其中幾個關鍵點
- 讀取xml檔案時,以獨佔方式,這樣可以避免檔案被別的程式開啟時無法獨取的問題。
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {}
- 在序列化反序列化時,當型別
DeviceInfoDto
對應的xml中元素的名字不是DeviceInfoDto
而是device
時,用該特性指定型別DeviceInfoDto
對應的在xml中的元素的名字device。如果不這麼做,則需要變通,改以下程式碼中List<DeviceInfoDto>
為List<device>
其中device
為一個繼承自DeviceInfoDto
型別的子類
[XmlArrayItem("device")]
public List<DeviceInfoDto> devices { get; set; } = new();
- 反序列化時對應C#型別DateTime時的報錯處理
當直接使用一個型別為Datetime屬性名為creationDate來在反序列化xml檔案中的日期時間型別的接收者時,反序列化會報錯:【字串“2020-07-31 09:29:16”不是有效的AllXsd值】。於是採入引入一箇中間屬性stringCreationDate(型別為string)和儲存其值的欄位_creationDate(型別為DateTime)的方式,執行過程1.當反序列化時從xml檔案讀取元素名為creationDate的元素值並透過stringCreationDate的set訪問器將其值在轉值為DateTime型別後存放於欄位_creationDate中 2.當C#程式碼中其他地方要訪問這個值時,就從creationDate屬性的get訪問器傳遞出_creationDate欄位的值。缺點:需引入不必要的屬性和欄位,而且屬性名還必須是public的,這會讓外部訪問者對這個中間屬性感到疑惑。
private DateTime _creationDate;
[XmlElement(ElementName = "creationDate")]
public string stringCreationDate { get => _creationDate.ToString("yyyy-MM-dd HH:mm:ss"); set => _creationDate = Convert.ToDateTime(value); }
[XmlIgnore]
public DateTime creationDate { get => _creationDate; }
- 序列化反序列化時,XmlSerializer可識別的常用的C#特性標籤 Attribute
a.[XmlRoot("udid")]
用於C#類名上,用於指明根型別對應的xml中的元素名
b.[XmlElement("creationDate")]
用於C#屬性或欄位上,用於指明屬性對應的xml元素名或者叫標籤名為 creationDate
c.[XmlAttribute("frequency")]
用於C#屬性或欄位上,用於指明屬性或欄位對應的XML元素的屬性名為 frequency
d.[XmlIgnore]
用於C#屬性或欄位上,用來標記該欄位在序列化反序列化XML文件時是要忽略的C#屬性或欄位
e.[XmlArrayItem("device")]
用於C#List<T>
集合型別的屬性或欄位上,用來標記集合中的元素型別T
在XML文件中對應的元素名稱
更多參考:
https://www.cnblogs.com/guogangj/p/7489218.html