C#讀取XML
關於C#讀取XML的方法,一直以來都是查資料然后忘記,反復如此,從來沒有記住過.今天寫這篇為了總結一下.當然,時間長了一定也會忘,因為根本不想記住
一.目標是這樣的XML文件 1.使用情況 : 為了將一些少量的數據免去存入數據庫的麻煩,所以使用了XML,所以這個XML的結構和數據庫表字段一對應 例如有一個表page:有四個字段 page (table) id (主鍵編號) name (名字) url (地址) count (計數) 那么自然對應的XML是這樣 <page id="1" name="nnn" url="uuu" count="100"></page> xml元素的名稱是這個表的名稱,屬性對應字段名.沒有INNERXML.非常清晰 整個XML文件內容可能如此 <?xml version="1.0" encoding="utf-8" ?> <rootxml> <page id="1" name="n1" url="u1" count="100"></page> <page id="2" name="n2" url="u2" count="200"></page> .....更多的記錄(略) </rootxml> 看起來這個文檔就對應這個表,如果有其它表,在根節點下增加元素,以表名為元素名. 2.上面的結構好像也不合理,有一個方案如下.用數據庫名字作為根元素名,用表名作子節點名,用item作記錄名. 依然例如這個page表,它處在數據庫mydata中.那么如下: <?xml version="1.0" encoding="utf-8" ?> <mydata> <page> <item id="1" name="n1" url="u1" count="100"></item> <item id="2" name="n2" url="u2" count="200"></item> </page> .....更多的表(略) </mydata> 看起來結構更好些,能反應數據庫和表的結構.如果有多個表,可以再增加節點 3.以上兩種結構其實都能達到目的,只是節點層級多少不同. 我使用第一種結構,因為不喜歡復雜層級.根節點下就是記錄節點狠好.而且我希望一個XML文檔就 只包含這一個表,如果有多個表就再建多個XML文檔.不希望多表混在一個文檔里. 當然,當數據量少時,使用第二種結構更好.清晰明白.
二.讀取XML // 建立XMLDOCUMENT對象 XmlDocument xmldoc = new XmlDocument(); // 載入文檔 xmldoc.Load(路徑或流); /* 讀取節點集合 第一個/,表示根目錄,第二個/page,表示根目錄下的page元素節點.這樣和目錄層級類似, 不知道目錄的名字,可以直接用/,如根目錄,沒有指定名字. */ xmldoc.SelectNodes("//page") /* 還可以找一個符合條件的元素,比如要id屬性等於1.那么就是這樣.在page之后的方括號加條件 ,那么就會找到一個id=1的page元素.這非常有用.類似於查詢page表,where id=1 */ xmldoc.SelectNodes("//page[@@id='1']") // 讀取XML元素的屬性,找到元素節點之后,讀取path屬性 node.Attributes["path"].Value;
三.需要了解的知識點:關於XMLELEMENT和XMLNODE 這兩個類的關系是,XmlElement是子,XmlNode是父.表現出來就是XmlElement是XmlNode的一種. 即:Xml節點類型很多:屬性節點、注釋節點、文本節點、元素節點等,都叫XmlNode.而XmlElement指的是元素節點.
四.將XML元素轉換成一個對象 C#中有序列化和反序列化可以將XML文檔轉為對象,或者將對象轉為XML.功能強大.但是: 我目前的任務較簡單,找到page元素之后,將它的屬性數據轉到page對象上. // page元素 <page id="1" name="nnn" url="uuu" count="100"></page> // 要轉成page對象 class Page { public string Id{get;set;} public string Name{get;set;} public string Url{get;set;} public string Count{get;set;} } // 使用反射做到.前提條件是字段名和屬性名對應. /* T:表示XML元素對應的類型,就是Page對象 XmlElement表示一個XML元素,就是page元素 */ public T XmlElementToT(XmlElement xmlelement) { // 創建一個實例 T tmp = System.Activator.CreateInstance(); // 循環當行數據行的所有字段 for (int i = 0; i < xmlelement.Attributes.Count; i++) { XmlAttribute currattr = xmlelement.Attributes[i]; // 使用反射找到出該字段名稱相同的對象的屬性 System.Reflection.PropertyInfo prop = tmp.GetType().GetProperty(currattr.Name, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.IgnoreCase); // 如果找到了屬性,則設置值.沒找到則不動作(此處可能轉換類型失敗,請盡量保證屬性類型為string) if (prop != null) { prop.SetValue(tmp, Convert.ChangeType(currattr.Value, prop.PropertyType)); } } return tmp; }
