c#操作xml
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; }