自己根据网上资料和自己的项目实践整理了一个比较实用的操作xml文件的帮助类,代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading; using System.Xml; using System.Xml.Linq; namespace DotNet.Common.Util { /// <summary> /// xml文件操作帮助类 /// </summary> public static class XmlHelper<T> where T : class, new() { #region 查询 /// <summary> /// 一次性取出所有记录 /// </summary> /// <param name="xmlPath">xml路径</param> /// <param name="rootName">根节点名</param> /// <param name="eleName">元素名</param> /// <returns></returns> public static List<T> GetObject(string xmlPath, string rootName, string eleName) { if (string.IsNullOrEmpty(xmlPath)) { throw new Exception("xml文件路径为空"); } try { XDocument xmlDoc = XDocument.Load(xmlPath); List<XElement> listElements = null; var query = from list in xmlDoc.Element(rootName).Elements(eleName) select list; listElements = query.ToList<XElement>(); List<T> listT = new List<T>(); if (listElements != null && listElements.Count > 0) { foreach (XElement item in listElements) { T objT = new T(); BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;//反射标示 Type objTType = objT.GetType(); //通过反射绑定属性 foreach (PropertyInfo pi in objTType.GetProperties(bf)) { foreach (XAttribute att in item.Attributes()) { if (pi.Name.ToUpper() == att.Name.ToString().ToUpper()) { object value = att.Value; try { object realValue = null; if (pi.PropertyType.Equals(typeof(Nullable<Int32>))) //泛型可空类型 { if (value != null) { if (string.IsNullOrEmpty(value.ToString())) { realValue = null; } else { realValue = int.Parse(value.ToString()); } } } else if (pi.PropertyType.Equals(typeof(Nullable<Int64>))) //泛型可空类型 { if (value != null) { if (string.IsNullOrEmpty(value.ToString())) { realValue = null; } else { realValue = int.Parse(value.ToString()); } } } else if (pi.PropertyType.Equals(typeof(Nullable<DateTime>))) //泛型可空类型 { if (value != null) { if (string.IsNullOrEmpty(value.ToString())) { realValue = null; } else { realValue = DateTime.Parse(value.ToString()); } } } else if (pi.PropertyType.Equals(typeof(Nullable<Boolean>))) //泛型可空类型 { if (value != null) { if (string.IsNullOrEmpty(value.ToString())) { realValue = null; } else { realValue = Boolean.Parse(value.ToString()); } } } else if (pi.PropertyType.Equals(typeof(Nullable))) //可空类型 { realValue = value; } else { try { realValue = Convert.ChangeType(value, pi.PropertyType); } catch { realValue = null; } } pi.SetValue(objT, realValue, null); } catch (FormatException fex) { throw fex; } catch (Exception ex) { throw ex; } break; } } } listT.Add(objT); } } return listT; } catch (Exception ex) { throw ex; } } /// <summary> /// 根据查询条件取得匹配所有条件的结果集 /// </summary> /// <param name="xmlPath"></param> /// <param name="rootName"></param> /// <param name="eleName"></param> /// <param name="searchCondition">查询条件对象</param> /// <returns></returns> public static List<T> GetObject(string xmlPath, string rootName, string eleName, T searchCondition) { List<T> listT = GetObject(xmlPath, rootName, eleName); List<T> listTResult = new List<T>(); foreach (T item in listT) { CompareTByCondition(item, searchCondition, listTResult); } return listTResult; } /// <summary> /// 匹配比较查询条件(没有iBATIS方便 ,通过反射) /// </summary> /// <param name="item"></param> /// <param name="searchCondition"></param> /// <param name="listT"></param> public static void CompareTByCondition(T item, T searchCondition, List<T> listT) { bool flag = true; BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;//反射标示 Type objTSearchType = searchCondition.GetType(); Type objTSourceType = item.GetType(); //通过反射绑定父级属性 foreach (PropertyInfo pi in objTSearchType.GetProperties(bf)) { object searchValue = pi.GetValue(searchCondition, null); if (searchValue == null) { continue; } if (string.IsNullOrEmpty(searchValue.ToString())) { continue; } foreach (PropertyInfo piSource in objTSourceType.GetProperties(bf)) { if (string.Compare(pi.Name, piSource.Name) == 0) { object sourceValue = piSource.GetValue(item, null); string strSearch = searchValue.ToString(); string strSource = (sourceValue == null) ? string.Empty : sourceValue.ToString(); if (string.Compare(strSearch, strSource) != 0) //有一个属性不等,就说明不匹配 { flag = false; break; } } } if (!flag) { break; } } if (flag) { listT.Add(item); } } /// <summary> /// 判断是否已经存在一条id相同的记录 /// </summary> /// <param name="xmlPath"></param> /// <param name="rootName"></param> /// <param name="eleName"></param> /// <param name="IDName">主键名称</param> /// <param name="Id">主键值</param> /// <returns></returns> public static bool IsAlreadyExistsObj(string xmlPath, string rootName, string eleName, string IDName, string ID) { BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;//反射标示 bool flag = false; List<T> listT = GetObject(xmlPath, rootName, eleName); foreach (T item in listT) { //通过反射绑定父级属性 Type itemType = item.GetType(); foreach (PropertyInfo itemProp in itemType.GetProperties(bf)) { //如果属性名和ID名称相同 比较是否已经存在一条相同id的记录 if (string.Compare(itemProp.Name.ToUpper(), IDName.ToUpper()) == 0) { object searchValue = itemProp.GetValue(item, null); if (searchValue != null) { if (string.Compare(searchValue.ToString(), ID) == 0) { flag = true; break; } } } } } return flag; } #endregion #region 删除 /// <summary> /// 删除节点 /// </summary> /// <param name="xmlPath"></param> /// <param name="rootName"></param> /// <param name="eleName"></param> /// <param name="idName">主键名称</param> /// <param name="id">主键值</param> /// <returns></returns> public static bool DeleteOneT(string xmlPath, string rootName, string eleName, string idName, string id) { bool flag = false; if (string.IsNullOrEmpty(xmlPath)) { throw new Exception("xml文件路径为空"); } try { bool isExists = IsAlreadyExistsObj(xmlPath, rootName, eleName, idName, id); if (!isExists) //删除的那条记录已经不存在了 { flag = true; } else { XDocument xmlDoc = XDocument.Load(xmlPath); List<XElement> listElements = null; var query = from list in xmlDoc.Element(rootName).Elements(eleName) select list; listElements = query.ToList<XElement>(); if (listElements != null && listElements.Count > 0) { foreach (XElement item in listElements) { if (string.Compare((string)item.Attribute(idName), id) == 0) { item.Remove(); xmlDoc.Save(xmlPath); flag = true; break; } } } } } catch { flag = false; } return flag; } #endregion #region 修改 /// <summary> /// 修改 /// </summary> /// <param name="xmlPath"></param> /// <param name="rootName"></param> /// <param name="eleName"></param> /// <param name="idName"></param> /// <param name="id"></param> /// <param name="objT"></param> /// <returns></returns> public static bool ModifyOneT(string xmlPath, string rootName, string eleName, string idName, string id, T objT) { bool flag = false; if (string.IsNullOrEmpty(xmlPath)) { throw new Exception("xml文件路径为空"); } try { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(xmlPath); XmlNode root = xmlDoc.SelectSingleNode(rootName); XmlNodeList nodeList = root.ChildNodes; BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;//反射标示 Type objTType = objT.GetType(); //通过反射绑定属性 PropertyInfo[] propInfos = objTType.GetProperties(bf); if (nodeList != null && nodeList.Count > 0) { foreach (XmlNode item in nodeList) { if (item is XmlElement) { XmlElement ele = (XmlElement)item; if (string.Compare(ele.GetAttribute(idName), id) == 0) { //修改这条记录 foreach (PropertyInfo pi in propInfos) { string attName = pi.Name; string attValue = string.Empty; object obj = pi.GetValue(objT, null); if (obj != null) { attValue = obj.ToString(); } //设置该节点属性 ele.SetAttribute(attName, attValue); } xmlDoc.Save(xmlPath); flag = true; break; } } } } } catch { flag = false; } return flag; } #endregion #region 添加 /// <summary> /// 添加 /// </summary> /// <param name="xmlPath"></param> /// <param name="rootName"></param> /// <param name="eleName"></param> /// <param name="idName"></param> /// <param name="id"></param> /// <param name="objT"></param> /// <returns></returns> public static bool InsertOneT(string xmlPath, string rootName, string eleName, string idName, string id, T objT) { bool flag = false; if (string.IsNullOrEmpty(xmlPath)) { throw new Exception("xml文件路径为空"); } XmlDocument xmlDoc = new XmlDocument(); try { Monitor.Enter(xmlDoc); if (IsAlreadyExistsObj(xmlPath, rootName, eleName, idName, id)) //如果xml文件中已经存在,不允许添加 { flag = false; } else { xmlDoc.Load(xmlPath); XmlNode root = xmlDoc.SelectSingleNode(rootName); XmlElement xeFather = xmlDoc.CreateElement(eleName);//创建一个节点 BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;//反射标示 Type objTType = objT.GetType(); //通过反射绑定属性 PropertyInfo[] propInfos = objTType.GetProperties(bf); foreach (PropertyInfo pi in propInfos) { string attName = pi.Name; string attValue = string.Empty; object obj = pi.GetValue(objT, null); if (obj != null) { attValue = obj.ToString(); } xeFather.SetAttribute(attName, attValue);//设置该节点属性 } root.AppendChild(xeFather); xmlDoc.Save(xmlPath); flag = true; } } catch { flag = false; } finally { Monitor.Exit(xmlDoc); } return flag; } #endregion } }
在表现层调用如下:
Code
//存到xml文件中去
XmlHelper<Employee>.InsertOneT(WebTestHelper.xmlEmployeePath, WebTestHelper.rootName, typeof(Employee).Name, "ID", employee.ID.ToString(), employee);
//存到xml文件中去
XmlHelper<Employee>.InsertOneT(WebTestHelper.xmlEmployeePath, WebTestHelper.rootName, typeof(Employee).Name, "ID", employee.ID.ToString(), employee);
ps,分层结构可能不合理,但是简单的小数据量的增删改查没有问题,读者可以下载demo试试。
ps2,如果xml文件结构有多层的子节点,只要递归调用这个类里的方法就可以了。
ps3,在插入时,xml文件的特殊字符没有处理,可能导致xml文件不符合语法规范,希望你能够留意。
demo下载:Demo