C# XmlHelper

目录

一、需求

二、XmlHelper

三、使用方法

1.创建XML文件

2.插入节点

1)插入节点和属性值

2)插入没有属性值的节点

3.读取节点

1)读取节点的属性值

2)读取指定的节点值

4.更新节点

1)更新没有属性的节点值

2)更新节点值

5.删除节点

结束


一、需求

对于小量数据在本地存储,可能会用到 xml 文件,下面的 xmlhelper.cs 代码出处好像是微软的,不太清楚,百度搜的很多帖子只是贴出了 xmlhelper 代码,千篇一律,全是贴了代码就什么都没有了,在此我将 xmlhelper 常用的 增、删、改、查 做一个教程。

二、XmlHelper

  1. using System;
  2. using System.Collections;
  3. using System.Data;
  4. using System.IO;
  5. using System.Text;
  6. using System.Xml;
  7. using System.Xml.Serialization;
  8. namespace Utils
  9. {
  10. public class XmlHelper
  11. {
  12. public XmlHelper()
  13. {
  14. }
  15. public enum XmlType
  16. {
  17. File,
  18. String
  19. };
  20. /// <summary>
  21. /// 创建XML文档
  22. /// </summary>
  23. /// <param name="name">根节点名称</param>
  24. /// <param name="type">根节点的一个属性值</param>
  25. /// <returns></returns>
  26. /// .net中调用方法:写入文件中,则:
  27. /// document = XmlOperate.CreateXmlDocument("sex", "sexy");
  28. /// document.Save("c:/bookstore.xml");
  29. public static XmlDocument CreateXmlDocument(string name, string type)
  30. {
  31. XmlDocument doc = null;
  32. XmlElement rootEle = null;
  33. try
  34. {
  35. doc = new XmlDocument();
  36. doc.LoadXml("<" + name + "/>");
  37. rootEle = doc.DocumentElement;
  38. rootEle.SetAttribute("type", type);
  39. }
  40. catch (Exception er)
  41. {
  42. throw er;
  43. }
  44. return doc;
  45. }
  46. /// <summary>
  47. /// 读取数据
  48. /// </summary>
  49. /// <param name="path">路径</param>
  50. /// <param name="node">节点</param>
  51. /// <param name="attribute">属性名,非空时返回该属性值,否则返回串联值</param>
  52. /// <returns>string</returns>
  53. /**************************************************
  54. * 使用示列:
  55. * XmlHelper.Read(path, "/Node", "")
  56. * XmlHelper.Read(path, "/Node/Element[@Attribute='Name']", "Attribute")
  57. ************************************************/
  58. public static string Read(string path, string node, string attribute)
  59. {
  60. string value = "";
  61. try
  62. {
  63. XmlDocument doc = new XmlDocument();
  64. doc.Load(path);
  65. XmlNode xn = doc.SelectSingleNode(node);
  66. value = (attribute.Equals("") ? xn.InnerText : xn.Attributes[attribute].Value);
  67. }
  68. catch { }
  69. return value;
  70. }
  71. /// <summary>
  72. /// 插入数据
  73. /// </summary>
  74. /// <param name="path">路径</param>
  75. /// <param name="node">节点</param>
  76. /// <param name="element">元素名,非空时插入新元素,否则在该元素中插入属性</param>
  77. /// <param name="attribute">属性名,非空时插入该元素属性值,否则插入元素值</param>
  78. /// <param name="value"></param>
  79. /// <returns></returns>
  80. /**************************************************
  81. * 使用示列:
  82. * XmlHelper.Insert(path, "/Node", "Element", "", "Value")
  83. * XmlHelper.Insert(path, "/Node", "Element", "Attribute", "Value")
  84. * XmlHelper.Insert(path, "/Node", "", "Attribute", "Value")
  85. ************************************************/
  86. public static void Insert(string path, string node, string element, string attribute, string value)
  87. {
  88. try
  89. {
  90. XmlDocument doc = new XmlDocument();
  91. doc.Load(path);
  92. XmlNode xn = doc.SelectSingleNode(node);
  93. if (element.Equals(""))
  94. {
  95. if (!attribute.Equals(""))
  96. {
  97. XmlElement xe = (XmlElement)xn;
  98. xe.SetAttribute(attribute, value);
  99. }
  100. }
  101. else
  102. {
  103. XmlElement xe = doc.CreateElement(element);
  104. if (attribute.Equals(""))
  105. xe.InnerText = value;
  106. else
  107. xe.SetAttribute(attribute, value);
  108. xn.AppendChild(xe);
  109. }
  110. doc.Save(path);
  111. }
  112. catch { }
  113. }
  114. /// <summary>
  115. /// 修改数据
  116. /// </summary>
  117. /// <param name="path">路径</param>
  118. /// <param name="node">节点</param>
  119. /// <param name="attribute">属性名,非空时修改该节点属性值,否则修改节点值</param>
  120. /// <param name="value"></param>
  121. /// <returns></returns>
  122. /**************************************************
  123. * 使用示列:
  124. * XmlHelper.Update(path, "/Node", "", "Value")
  125. * XmlHelper.Update(path, "/Node", "Attribute", "Value")
  126. ************************************************/
  127. public static void Update(string path, string node, string attribute, string value)
  128. {
  129. try
  130. {
  131. XmlDocument doc = new XmlDocument();
  132. doc.Load(path);
  133. XmlNode xn = doc.SelectSingleNode(node);
  134. XmlElement xe = (XmlElement)xn;
  135. if (attribute.Equals(""))
  136. xe.InnerText = value;
  137. else
  138. xe.SetAttribute(attribute, value);
  139. doc.Save(path);
  140. }
  141. catch { }
  142. }
  143. /// <summary>
  144. /// 删除数据
  145. /// </summary>
  146. /// <param name="path">路径</param>
  147. /// <param name="node">节点</param>
  148. /// <param name="attribute">属性名,非空时删除该节点属性值,否则删除节点值</param>
  149. /// <param name="value"></param>
  150. /// <returns></returns>
  151. /**************************************************
  152. * 使用示列:
  153. * XmlHelper.Delete(path, "/Node", "")
  154. * XmlHelper.Delete(path, "/Node", "Attribute")
  155. ************************************************/
  156. public static void Delete(string path, string node, string attribute)
  157. {
  158. try
  159. {
  160. XmlDocument doc = new XmlDocument();
  161. doc.Load(path);
  162. XmlNode xn = doc.SelectSingleNode(node);
  163. XmlElement xe = (XmlElement)xn;
  164. if (attribute.Equals(""))
  165. xn.ParentNode.RemoveChild(xn);
  166. else
  167. xe.RemoveAttribute(attribute);
  168. doc.Save(path);
  169. }
  170. catch { }
  171. }
  172. #region 读取XML资源到DataSet中
  173. /// <summary>
  174. /// 读取XML资源到DataSet中
  175. /// </summary>
  176. /// <param name="source">XML资源,文件为路径,否则为XML字符串</param>
  177. /// <param name="xmlType">XML资源类型</param>
  178. /// <returns>DataSet</returns>
  179. public static DataSet GetDataSet(string source, XmlType xmlType)
  180. {
  181. DataSet ds = new DataSet();
  182. if (xmlType == XmlType.File)
  183. {
  184. ds.ReadXml(source);
  185. }
  186. else
  187. {
  188. XmlDocument xd = new XmlDocument();
  189. xd.LoadXml(source);
  190. XmlNodeReader xnr = new XmlNodeReader(xd);
  191. ds.ReadXml(xnr);
  192. }
  193. return ds;
  194. }
  195. #endregion
  196. #region 操作xml文件中指定节点的数据
  197. /// <summary>
  198. /// 获得xml文件中指定节点的节点数据
  199. /// </summary>
  200. /// <param name="TableName"></param>
  201. /// <returns></returns>
  202. public static string GetNodeInfoByNodeName(string path, string nodeName)
  203. {
  204. string XmlString = "";
  205. XmlDocument xml = new XmlDocument();
  206. xml.Load(path);
  207. System.Xml.XmlElement root = xml.DocumentElement;
  208. System.Xml.XmlNode node = root.SelectSingleNode("//" + nodeName);
  209. if (node != null)
  210. {
  211. XmlString = node.InnerText;
  212. }
  213. return XmlString;
  214. }
  215. #endregion
  216. #region 获取一个字符串xml文档中的ds
  217. /// <summary>
  218. /// 获取一个字符串xml文档中的ds
  219. /// </summary>
  220. /// <param name="xml_string">含有xml信息的字符串</param>
  221. public static void get_XmlValue_ds(string xml_string, ref DataSet ds)
  222. {
  223. System.Xml.XmlDocument xd = new XmlDocument();
  224. xd.LoadXml(xml_string);
  225. XmlNodeReader xnr = new XmlNodeReader(xd);
  226. ds.ReadXml(xnr);
  227. xnr.Close();
  228. int a = ds.Tables.Count;
  229. }
  230. #endregion
  231. #region 读取XML资源到DataTable中
  232. /// <summary>
  233. /// 读取XML资源到DataTable中
  234. /// </summary>
  235. /// <param name="source">XML资源,文件为路径,否则为XML字符串</param>
  236. /// <param name="xmlType">XML资源类型:文件,字符串</param>
  237. /// <param name="tableName">表名称</param>
  238. /// <returns>DataTable</returns>
  239. public static DataTable GetTable(string source, XmlType xmlType, string tableName)
  240. {
  241. DataSet ds = new DataSet();
  242. if (xmlType == XmlType.File)
  243. {
  244. ds.ReadXml(source);
  245. }
  246. else
  247. {
  248. XmlDocument xd = new XmlDocument();
  249. xd.LoadXml(source);
  250. XmlNodeReader xnr = new XmlNodeReader(xd);
  251. ds.ReadXml(xnr);
  252. }
  253. return ds.Tables[tableName];
  254. }
  255. #endregion
  256. #region 读取XML资源中指定的DataTable的指定行指定列的值
  257. /// <summary>
  258. /// 读取XML资源中指定的DataTable的指定行指定列的值
  259. /// </summary>
  260. /// <param name="source">XML资源</param>
  261. /// <param name="xmlType">XML资源类型:文件,字符串</param>
  262. /// <param name="tableName">表名</param>
  263. /// <param name="rowIndex">行号</param>
  264. /// <param name="colName">列名</param>
  265. /// <returns>值,不存在时返回Null</returns>
  266. public static object GetTableCell(string source, XmlType xmlType, string tableName, int rowIndex, string colName)
  267. {
  268. DataSet ds = new DataSet();
  269. if (xmlType == XmlType.File)
  270. {
  271. ds.ReadXml(source);
  272. }
  273. else
  274. {
  275. XmlDocument xd = new XmlDocument();
  276. xd.LoadXml(source);
  277. XmlNodeReader xnr = new XmlNodeReader(xd);
  278. ds.ReadXml(xnr);
  279. }
  280. return ds.Tables[tableName].Rows[rowIndex][colName];
  281. }
  282. #endregion
  283. #region 读取XML资源中指定的DataTable的指定行指定列的值
  284. /// <summary>
  285. /// 读取XML资源中指定的DataTable的指定行指定列的值
  286. /// </summary>
  287. /// <param name="source">XML资源</param>
  288. /// <param name="xmlType">XML资源类型:文件,字符串</param>
  289. /// <param name="tableName">表名</param>
  290. /// <param name="rowIndex">行号</param>
  291. /// <param name="colIndex">列号</param>
  292. /// <returns>值,不存在时返回Null</returns>
  293. public static object GetTableCell(string source, XmlType xmlType, string tableName, int rowIndex, int colIndex)
  294. {
  295. DataSet ds = new DataSet();
  296. if (xmlType == XmlType.File)
  297. {
  298. ds.ReadXml(source);
  299. }
  300. else
  301. {
  302. XmlDocument xd = new XmlDocument();
  303. xd.LoadXml(source);
  304. XmlNodeReader xnr = new XmlNodeReader(xd);
  305. ds.ReadXml(xnr);
  306. }
  307. return ds.Tables[tableName].Rows[rowIndex][colIndex];
  308. }
  309. #endregion
  310. #region 将DataTable写入XML文件中
  311. /// <summary>
  312. /// 将DataTable写入XML文件中
  313. /// </summary>
  314. /// <param name="dt">含有数据的DataTable</param>
  315. /// <param name="filePath">文件路径</param>
  316. public static void SaveTableToFile(DataTable dt, string filePath)
  317. {
  318. DataSet ds = new DataSet("Config");
  319. ds.Tables.Add(dt.Copy());
  320. ds.WriteXml(filePath);
  321. }
  322. #endregion
  323. #region 将DataTable以指定的根结点名称写入文件
  324. /// <summary>
  325. /// 将DataTable以指定的根结点名称写入文件
  326. /// </summary>
  327. /// <param name="dt">含有数据的DataTable</param>
  328. /// <param name="rootName">根结点名称</param>
  329. /// <param name="filePath">文件路径</param>
  330. public static void SaveTableToFile(DataTable dt, string rootName, string filePath)
  331. {
  332. DataSet ds = new DataSet(rootName);
  333. ds.Tables.Add(dt.Copy());
  334. ds.WriteXml(filePath);
  335. }
  336. #endregion
  337. #region 使用DataSet方式更新XML文件节点
  338. /// <summary>
  339. /// 使用DataSet方式更新XML文件节点
  340. /// </summary>
  341. /// <param name="filePath">XML文件路径</param>
  342. /// <param name="tableName">表名称</param>
  343. /// <param name="rowIndex">行号</param>
  344. /// <param name="colName">列名</param>
  345. /// <param name="content">更新值</param>
  346. /// <returns>更新是否成功</returns>
  347. public static bool UpdateTableCell(string filePath, string tableName, int rowIndex, string colName, string content)
  348. {
  349. bool flag = false;
  350. DataSet ds = new DataSet();
  351. ds.ReadXml(filePath);
  352. DataTable dt = ds.Tables[tableName];
  353. if (dt.Rows[rowIndex][colName] != null)
  354. {
  355. dt.Rows[rowIndex][colName] = content;
  356. ds.WriteXml(filePath);
  357. flag = true;
  358. }
  359. else
  360. {
  361. flag = false;
  362. }
  363. return flag;
  364. }
  365. #endregion
  366. #region 使用DataSet方式更新XML文件节点
  367. /// <summary>
  368. /// 使用DataSet方式更新XML文件节点
  369. /// </summary>
  370. /// <param name="filePath">XML文件路径</param>
  371. /// <param name="tableName">表名称</param>
  372. /// <param name="rowIndex">行号</param>
  373. /// <param name="colIndex">列号</param>
  374. /// <param name="content">更新值</param>
  375. /// <returns>更新是否成功</returns>
  376. public static bool UpdateTableCell(string filePath, string tableName, int rowIndex, int colIndex, string content)
  377. {
  378. bool flag = false;
  379. DataSet ds = new DataSet();
  380. ds.ReadXml(filePath);
  381. DataTable dt = ds.Tables[tableName];
  382. if (dt.Rows[rowIndex][colIndex] != null)
  383. {
  384. dt.Rows[rowIndex][colIndex] = content;
  385. ds.WriteXml(filePath);
  386. flag = true;
  387. }
  388. else
  389. {
  390. flag = false;
  391. }
  392. return flag;
  393. }
  394. #endregion
  395. #region 读取XML资源中的指定节点内容
  396. /// <summary>
  397. /// 读取XML资源中的指定节点内容
  398. /// </summary>
  399. /// <param name="source">XML资源</param>
  400. /// <param name="xmlType">XML资源类型:文件,字符串</param>
  401. /// <param name="nodeName">节点名称</param>
  402. /// <returns>节点内容</returns>
  403. public static object GetNodeValue(string source, XmlType xmlType, string nodeName)
  404. {
  405. XmlDocument xd = new XmlDocument();
  406. if (xmlType == XmlType.File)
  407. {
  408. xd.Load(source);
  409. }
  410. else
  411. {
  412. xd.LoadXml(source);
  413. }
  414. XmlElement xe = xd.DocumentElement;
  415. XmlNode xn = xe.SelectSingleNode("//" + nodeName);
  416. if (xn != null)
  417. {
  418. return xn.InnerText;
  419. }
  420. else
  421. {
  422. return null;
  423. }
  424. }
  425. /// <summary>
  426. /// 读取XML资源中的指定节点内容
  427. /// </summary>
  428. /// <param name="source">XML资源</param>
  429. /// <param name="nodeName">节点名称</param>
  430. /// <returns>节点内容</returns>
  431. public static object GetNodeValue(string source, string nodeName)
  432. {
  433. if (source == null || nodeName == null || source == "" || nodeName == "" || source.Length < nodeName.Length * 2)
  434. {
  435. return null;
  436. }
  437. else
  438. {
  439. int start = source.IndexOf("<" + nodeName + ">") + nodeName.Length + 2;
  440. int end = source.IndexOf("</" + nodeName + ">");
  441. if (start == -1 || end == -1)
  442. {
  443. return null;
  444. }
  445. else if (start >= end)
  446. {
  447. return null;
  448. }
  449. else
  450. {
  451. return source.Substring(start, end - start);
  452. }
  453. }
  454. }
  455. #endregion
  456. #region 更新XML文件中的指定节点内容
  457. /// <summary>
  458. /// 更新XML文件中的指定节点内容
  459. /// </summary>
  460. /// <param name="filePath">文件路径</param>
  461. /// <param name="nodeName">节点名称</param>
  462. /// <param name="nodeValue">更新内容</param>
  463. /// <returns>更新是否成功</returns>
  464. public static bool UpdateNode(string filePath, string nodeName, string nodeValue)
  465. {
  466. bool flag = false;
  467. XmlDocument xd = new XmlDocument();
  468. xd.Load(filePath);
  469. XmlElement xe = xd.DocumentElement;
  470. XmlNode xn = xe.SelectSingleNode("//" + nodeName);
  471. if (xn != null)
  472. {
  473. xn.InnerText = nodeValue;
  474. flag = true;
  475. }
  476. else
  477. {
  478. flag = false;
  479. }
  480. return flag;
  481. }
  482. #endregion
  483. #region 读取xml文件,并将文件序列化为类
  484. /// <summary>
  485. /// 读取xml文件,并将文件序列化为类
  486. /// </summary>
  487. /// <typeparam name="T"></typeparam>
  488. /// <param name="path"></param>
  489. /// <returns></returns>
  490. public static T ReadXML<T>(string path)
  491. {
  492. XmlSerializer reader = new XmlSerializer(typeof(T));//TODO
  493. StreamReader file = new StreamReader(@path);
  494. return (T)reader.Deserialize(file);
  495. }
  496. #endregion
  497. #region 将对象写入XML文件
  498. /// <summary>
  499. /// 将对象写入XML文件
  500. /// </summary>
  501. /// <typeparam name="T">C#对象名</typeparam>
  502. /// <param name="item">对象实例</param>
  503. /// <param name="path">路径</param>
  504. /// <param name="jjdbh">标号</param>
  505. /// <param name="ends">结束符号(整个xml的路径类似如下:C:\xmltest\201111send.xml,其中path=C:\xmltest,jjdbh=201111,ends=send)</param>
  506. /// <returns></returns>
  507. public static string WriteXML<T>(T item, string path, string jjdbh, string ends)
  508. {
  509. if (string.IsNullOrEmpty(ends))
  510. {
  511. //默认为发送
  512. ends = "send";
  513. }
  514. int i = 0;//控制写入文件的次数,
  515. XmlSerializer serializer = new XmlSerializer(item.GetType());
  516. object[] obj = new object[] { path, "\\", jjdbh, ends, ".xml" };
  517. string xmlPath = String.Concat(obj);
  518. while (true)
  519. {
  520. try
  521. {
  522. //用filestream方式创建文件不会出现“文件正在占用中,用File.create”则不行
  523. FileStream fs;
  524. fs = File.Create(xmlPath);
  525. fs.Close();
  526. TextWriter writer = new StreamWriter(xmlPath, false, Encoding.UTF8);
  527. XmlSerializerNamespaces xml = new XmlSerializerNamespaces();
  528. xml.Add(string.Empty, string.Empty);
  529. serializer.Serialize(writer, item, xml);
  530. writer.Flush();
  531. writer.Close();
  532. break;
  533. }
  534. catch (Exception)
  535. {
  536. if (i < 5)
  537. {
  538. i++;
  539. continue;
  540. }
  541. else
  542. {
  543. break;
  544. }
  545. }
  546. }
  547. return SerializeToXmlStr<T>(item, true);
  548. }
  549. #endregion
  550. #region 静态扩展
  551. /// <summary>
  552. /// 静态扩展
  553. /// </summary>
  554. /// <typeparam name="T">需要序列化的对象类型,必须声明[Serializable]特征</typeparam>
  555. /// <param name="obj">需要序列化的对象</param>
  556. /// <param name="omitXmlDeclaration">true:省略XML声明;否则为false.默认false,即编写 XML 声明。</param>
  557. /// <returns></returns>
  558. public static string SerializeToXmlStr<T>(T obj, bool omitXmlDeclaration)
  559. {
  560. return XmlSerialize<T>(obj, omitXmlDeclaration);
  561. }
  562. #endregion
  563. #region XML序列化反序列化相关的静态方法
  564. /// <summary>
  565. /// 使用XmlSerializer序列化对象
  566. /// </summary>
  567. /// <typeparam name="T">需要序列化的对象类型,必须声明[Serializable]特征</typeparam>
  568. /// <param name="obj">需要序列化的对象</param>
  569. /// <param name="omitXmlDeclaration">true:省略XML声明;否则为false.默认false,即编写 XML 声明。</param>
  570. /// <returns>序列化后的字符串</returns>
  571. public static string XmlSerialize<T>(T obj, bool omitXmlDeclaration)
  572. {
  573. /* This property only applies to XmlWriter instances that output text content to a stream; otherwise, this setting is ignored.
  574. 可能很多朋友遇见过 不能转换成Xml不能反序列化成为UTF8XML声明的情况,就是这个原因。
  575. */
  576. XmlWriterSettings xmlSettings = new XmlWriterSettings();
  577. xmlSettings.OmitXmlDeclaration = omitXmlDeclaration;
  578. xmlSettings.Encoding = new System.Text.UTF8Encoding(false);
  579. MemoryStream stream = new MemoryStream();//var writer = new StringWriter();
  580. //这里如果直接写成:Encoding = Encoding.UTF8 会在生成的xml中加入BOM(Byte-order Mark) 信息(Unicode 字节顺序标记) ,
  581. //所以new System.Text.UTF8Encoding(false)是最佳方式,省得再做替换的麻烦
  582. XmlWriter xmlwriter = XmlWriter.Create(stream/*writer*/, xmlSettings);
  583. XmlSerializerNamespaces xmlns = new XmlSerializerNamespaces();
  584. xmlns.Add(String.Empty, String.Empty); //在XML序列化时去除默认命名空间xmlns:xsd和xmlns:xsi
  585. XmlSerializer ser = new XmlSerializer(typeof(T));
  586. ser.Serialize(xmlwriter, obj, xmlns);
  587. return Encoding.UTF8.GetString(stream.ToArray());//writer.ToString();
  588. }
  589. /// <summary>
  590. /// 使用XmlSerializer序列化对象
  591. /// </summary>
  592. /// <typeparam name="T"></typeparam>
  593. /// <param name="path">文件路径</param>
  594. /// <param name="obj">需要序列化的对象</param>
  595. /// <param name="omitXmlDeclaration">true:省略XML声明;否则为false.默认false,即编写 XML 声明。</param>
  596. /// <param name="removeDefaultNamespace">是否移除默认名称空间(如果对象定义时指定了:XmlRoot(Namespace = "http://www.xxx.com/xsd")则需要传false值进来)</param>
  597. /// <returns>序列化后的字符串</returns>
  598. public static void XmlSerialize<T>(string path, T obj, bool omitXmlDeclaration, bool removeDefaultNamespace)
  599. {
  600. XmlWriterSettings xmlSetings = new XmlWriterSettings();
  601. xmlSetings.OmitXmlDeclaration = omitXmlDeclaration;
  602. using (XmlWriter xmlwriter = XmlWriter.Create(path, xmlSetings))
  603. {
  604. XmlSerializerNamespaces xmlns = new XmlSerializerNamespaces();
  605. if (removeDefaultNamespace)
  606. xmlns.Add(String.Empty, String.Empty); //在XML序列化时去除默认命名空间xmlns:xsd和xmlns:xsi
  607. XmlSerializer ser = new XmlSerializer(typeof(T));
  608. ser.Serialize(xmlwriter, obj, xmlns);
  609. }
  610. }
  611. private static byte[] ShareReadFile(string filePath)
  612. {
  613. byte[] bytes;
  614. //避免"正由另一进程使用,因此该进程无法访问此文件"造成异常 共享锁 flieShare必须为ReadWrite,
  615. //但是如果文件不存在的话,还是会出现异常,所以这里不能吃掉任何异常,但是需要考虑到这些问题
  616. using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
  617. {
  618. bytes = new byte[fs.Length];
  619. int numBytesToRead = (int)fs.Length;
  620. int numBytesRead = 0;
  621. while (numBytesToRead > 0)
  622. {
  623. int n = fs.Read(bytes, numBytesRead, numBytesToRead);
  624. if (n == 0)
  625. break;
  626. numBytesRead += n;
  627. numBytesToRead -= n;
  628. }
  629. }
  630. return bytes;
  631. }
  632. /// <summary>
  633. /// 从文件读取并反序列化为对象 (解决: 多线程或多进程下读写并发问题)
  634. /// </summary>
  635. /// <typeparam name="T">返回的对象类型</typeparam>
  636. /// <param name="path">文件地址</param>
  637. /// <returns></returns>
  638. public static T XmlFileDeserialize<T>(string path)
  639. {
  640. byte[] bytes = ShareReadFile(path);
  641. //当文件正在被写入数据时,可能读出为0
  642. if (bytes.Length < 1)
  643. {
  644. //5次机会
  645. for (int i = 0; i < 5; i++)
  646. {
  647. // 采用这样诡异的做法避免独占文件和文件正在被写入时读出来的数据为0字节的问题。
  648. bytes = ShareReadFile(path);
  649. if (bytes.Length > 0) break;
  650. //悲观情况下总共最多消耗1/4秒,读取文件
  651. System.Threading.Thread.Sleep(50);
  652. }
  653. }
  654. XmlDocument doc = new XmlDocument();
  655. doc.Load(new MemoryStream(bytes));
  656. if (doc.DocumentElement != null)
  657. return (T)new XmlSerializer(typeof(T)).Deserialize(new XmlNodeReader(doc.DocumentElement));
  658. return default(T);
  659. //XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
  660. //xmlReaderSettings.CloseInput = true;
  661. //using (XmlReader xmlReader = XmlReader.Create(path, xmlReaderSettings))
  662. //{
  663. // T obj = (T)new XmlSerializer(typeof(T)).Deserialize(xmlReader);
  664. // return obj;
  665. //}
  666. }
  667. /// <summary>
  668. /// 使用XmlSerializer反序列化对象
  669. /// </summary>
  670. /// <param name="xmlOfObject">需要反序列化的xml字符串</param>
  671. /// <returns>反序列化后的对象</returns>
  672. public static T XmlDeserialize<T>(string xmlOfObject) where T : class
  673. {
  674. XmlReader xmlReader = XmlReader.Create(new StringReader(xmlOfObject), new XmlReaderSettings());
  675. return (T)new XmlSerializer(typeof(T)).Deserialize(xmlReader);
  676. }
  677. #endregion
  678. }
  679. }

三、使用方法

新建一个项目,winfrom和控制台都可以,在写代码之前,使用一个默认路径,用来读写xml文件,放在项目的生成目录,在项目中写一个全局变量,如下:

private static string path = Application.StartupPath + "\\MyXML.xml";

1.创建XML文件

C#代码:

  1. //创建XML文件
  2. XmlDocument xmlDocument = XmlHelper.CreateXmlDocument("Root", "root");
  3. xmlDocument.Save(path);

运行后,生成的xml文件:

XML:

<Root type="root" />

这里只有一个Root节点,没其他内容

2.插入节点

操作前的 xml 内容:

<Root type="root" />

1)插入节点和属性值

这里需要注意的是,第二个参数 ”/Root“  这里不可以加入不存在的节点,否则会报错,比如:"/Root/Dog" ,意思是要插入到Root / Dog 节点下,而此时并没有创建Dog节点。下面是参数字符串的解释:

"path" -------------xml文件路径
"/Root" -----------要插入到xml文件中的那个节点中
"Dog" -------------元素名
"Attribute" -------属性名,不用就传 ""
"狗" ---------------值,如果属性名不为空,这里就是属性值,否则就是节点值

C#代码:

XmlHelper.Insert(path, "/Root", "Dog", "Attribute", "狗");

运行后的XML:

  1. <Root type="root">
  2. <Dog Attribute="狗" />
  3. </Root>

2)插入没有属性值的节点

C#代码:

  1. XmlHelper.Insert(path, "/Root/Dog", "Husky", "Attribute", "哈士奇");
  2. XmlHelper.Insert(path, "/Root/Dog/Husky", "Name", "", "傻狗二哈");
  3. XmlHelper.Insert(path, "/Root/Dog/Husky", "Name", "", "旺财");

运行后的XML:

  1. <Root type="root">
  2. <Dog Attribute="狗">
  3. <Husky Attribute="哈士奇">
  4. <Name>傻狗二哈</Name>
  5. <Name>旺财</Name>
  6. </Husky>
  7. </Dog>
  8. </Root>

第一条插入的是属性,哈士奇是属性的值。

第二条,第三条插入的节点值。

3.读取节点

操作前的 xml 内容:

  1. <Root type="root">
  2. <Dog Attribute="狗">
  3. <Husky Attribute="哈士奇">
  4. <Name>傻狗二哈</Name>
  5. <Name>旺财</Name>
  6. </Husky>
  7. </Dog>
  8. </Root>

1)读取节点的属性值

C#代码:

  1. string node = XmlHelper.Read(path, "/Root/Dog/Husky[@Attribute='哈士奇']", "");
  2. Console.WriteLine("节点名:" + node);

执行结果:

读取了哈士奇节点下面所有的节点值

2)读取指定的节点值

C#代码:

  1. string node = XmlHelper.Read(path, "/Root/Dog/Husky/Name", "");
  2. Console.WriteLine("节点名:" + node);

执行结果:

只读取了哈士奇节点下的一个节点

4.更新节点

操作前的 xml 内容:

  1. <Root type="root">
  2. <Dog Attribute="狗">
  3. <Husky Attribute="哈士奇">
  4. <Name>傻狗二哈</Name>
  5. <Name>旺财</Name>
  6. </Husky>
  7. </Dog>
  8. </Root>

1)更新没有属性的节点值

C#代码:

XmlHelper.Update(path, "/Root/Dog/Husky/Name", "", "傻狗");

运行后的XML:

  1. <Root type="root">
  2. <Dog Attribute="狗">
  3. <Husky Attribute="哈士奇">
  4. <Name>傻狗</Name>
  5. <Name>旺财</Name>
  6. </Husky>
  7. </Dog>
  8. </Root>

将傻狗二哈改了傻狗

2)更新节点值

C#代码:

XmlHelper.Update(path, "/Root/Dog/Husky", "Attribute", "ha-shi-qi");

运行后的XML:

  1. <Root type="root">
  2. <Dog Attribute="狗">
  3. <Husky Attribute="ha-shi-qi">
  4. <Name>傻狗</Name>
  5. <Name>旺财</Name>
  6. </Husky>
  7. </Dog>
  8. </Root>

5.删除节点

操作前的 xml 内容:

  1. <Root type="root">
  2. <Dog Attribute="狗">
  3. <Husky Attribute="ha-shi-qi">
  4. <Name>傻狗</Name>
  5. <Name>旺财</Name>
  6. </Husky>
  7. </Dog>
  8. </Root>

需求:删除 Husky 节点下的 Name 节点

C#代码:

XmlHelper.Delete(path, "/Root/Dog/Husky/Name", "");

运行后的XML:

  1. <Root type="root">
  2. <Dog Attribute="狗">
  3. <Husky Attribute="ha-shi-qi">
  4. <Name>旺财</Name>
  5. </Husky>
  6. </Dog>
  7. </Root>

可以看到,这里的Name节点原本有两个,删除的时候,只删除了第一行的节点。

不如我们删除多个节点试试:

C#代码:

XmlHelper.Delete(path, "/Root/Dog", "");

运行后的XML:

  1. <Root type="root">
  2. </Root>

子节点被一并删除了

结束

如果这个帖子对你有用,欢迎关注 + 点赞 + 留言,谢谢

end

posted @ 2022-09-26 17:41  mkmkbj  阅读(353)  评论(0编辑  收藏  举报