C#本身也带有读取XML文件的类,但是许久未曾接触C#了,为了练练手,自己写了一个具有简单功能的类,实现了读取xml文件,查找元素,插入结点等功能。实现如下:
XmlDoc类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace ConsoleCSharp { class XmlDoc { internal static string xmlStr = string.Empty; private XmlNode root = new XmlNode(); private string remark = string.Empty; public static List<XmlNode> AllNodes = new List<XmlNode>(); internal List<XmlNode> nodes = new List<XmlNode>(); public XmlNode Root { get { return root; } set { root = value; } } public string Remark { get { return remark; } set { remark = value; } } public XmlDoc(string path) { StreamReader sr = new StreamReader(path, Encoding.Default); xmlStr = InitialXmlStr(sr.ReadToEnd()); sr.Close(); if (!VerifyXml()) { throw new XmlInvalidException(); } int begin = xmlStr.IndexOf("?>"); int end = xmlStr.LastIndexOf(">"); root.InitialXmlNode(begin, end); AllNodes.Add(root); if (!root.hasChildren()) { AllNodes[0].setContent(); } else { root.ExtractAllNode(); } } //初始化XML字符串 private string InitialXmlStr(string str) { while(str.IndexOf("< ") != -1) { str = str.Replace("< ","<"); //"< " --> "<" } //while (str.IndexOf(" <") != -1) //{ // str = str.Replace(" <", "<"); //" <" --> "<" //} while(str.IndexOf(" >") != -1) { str = str.Replace(" >",">"); //" >" --> ">" } //while (str.IndexOf("> ") != -1) //{ // str = str.Replace("> ", ">"); //"> " --> ">" //} while (str.IndexOf("/ ") != -1) { str = str.Replace("/ ", "/"); //"/ " --> "/" } return str; } //将XML写入到文本文件中 public static void WriteToFile(string path) { StreamWriter sw = new StreamWriter(path); sw.Write(XmlDoc.xmlStr); sw.Flush(); sw.Close(); } //验证XML文件的有效性 private bool VerifyXml() { int i = xmlStr.IndexOf("<?"); int j = -1; if (i != -1) { j = xmlStr.IndexOf("?>"); if (j == -1) { return false; } } if (i != -1 && j != -1) { int v = xmlStr.IndexOf("version"); int m = -1, n = -1; if (v != -1) { m = xmlStr.IndexOf("\"", i, j - i + 1); n = xmlStr.IndexOf("\"", m + 1, j - m); if (m == -1 || n == -1) { return false; } string version = xmlStr.Substring(m + 1, n - m - 1); remark += "version:" + version; } int e = xmlStr.IndexOf("encoding"); if (e != -1) { if (n != -1) { m = xmlStr.IndexOf("\"", n + 1, j - n); n = xmlStr.IndexOf("\"", m + 1, j - m); if (m == -1 || n == -1) { return false; } string encoding = xmlStr.Substring(m + 1, n - m - 1); remark += " encoding:" + encoding; } else { m = xmlStr.IndexOf("\"", e, j - n - 1); n = xmlStr.IndexOf("\"", e, j - m - 1); if (m == -1 || n == -1) { return false; } string encoding = xmlStr.Substring(m + 1, n - m - 1); remark += " encoding:" + encoding; } } } return true; } //将文档转化为字符串 public override string ToString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < XmlDoc.AllNodes.Count; i++) { if (XmlDoc.AllNodes[i].Depth() == 2) { sb.Append(XmlDoc.AllNodes[i].ToString()); sb.Append("\n"); } } return sb.ToString(); } //根据元素名称查找元素 public List<XmlNode> GetElementsByTagName(string name) { nodes.Clear(); foreach(XmlNode node in AllNodes) { if (String.Compare(node.Name,name) == 0) { nodes.Add(node); } } return nodes; } } class XmlInvalidException : Exception { private string message; public override string Message { get { return message; } } public XmlInvalidException() { this.message = "XML FILE INVALID!"; } public XmlInvalidException(string str) { this.message = str; } } }
XMLNode类
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleCSharp { public class NodeAttribute { public string Name = string.Empty; public string Content = string.Empty; public NodeAttribute() { } public NodeAttribute(string name, string content) { this.Name = name; this.Content = content; } } class XmlNode { private string name = string.Empty; private string content = string.Empty; private NodeAttribute attribute = new NodeAttribute(); internal int startindex1 = -1; internal int startindex2 = -1; internal int endindex1 = -1; internal int endindex2 = -1; internal string startMarker = string.Empty; internal string endMarker = string.Empty; internal bool hasChild = false; //是否有子元素 private bool hasNext = false; //是否有兄弟元素 private List<XmlNode> nodes = new List<XmlNode>(); internal XmlNode father; public string Name { get { return name; } set { this.name = value; this.startMarker = "<" + this.name + ">"; this.endMarker = "</" + this.name + ">"; } } public NodeAttribute Attribute { get { return attribute; } set { attribute = value; } } //获取元素的内容 public string Content { get { return content; } set { content = value; } } //获取元素的子元素 public List<XmlNode> Nodes { get { return nodes; } set { nodes = value; } } //提取该元素的所有子元素 internal void ExtractAllNode() { XmlNode node = this; if (node.hasChildren()) { node.GetChildren(); for (int i = 0; i < node.Nodes.Count; i++ ) { node.Nodes[i].ExtractAllNode(); } } else { node.setContent(); } } //提取元素的下一层元素 private void GetChildren() { XmlNode node = this; int begin = node.startindex2 + 1; int end = node.endindex1 - 1; XmlNode newnode = new XmlNode(); newnode.father = node; newnode.InitialXmlNode(begin, end); node.nodes.Add(newnode); XmlDoc.AllNodes.Add(newnode); newnode.GetBrothers(); } //提取该元素之后的所有兄弟元素 private void GetBrothers() { XmlNode node = this; while (node.hasNextBrother()) { int begin = node.endindex2 + 1; int end = node.father.endindex1 - 1; XmlNode newnode = new XmlNode(); newnode.father = node.father; newnode.InitialXmlNode(begin, end); node.father.nodes.Add(newnode); XmlDoc.AllNodes.Add(newnode); node = newnode; } } //判断元素是否有子元素 internal bool hasChildren() { int begin = this.startindex2 + 1; int end = this.endindex1 - 1; int index = XmlDoc.xmlStr.IndexOf("<", begin, end - begin + 1); if (index != -1) { this.hasChild = true; return true; } return false; } //判断元素是否还有下一个兄弟元素 internal bool hasNextBrother() { int begin = this.endindex2 + 1; if (this.father == null) { return false; } int end = this.father.endindex1 - 1; int index = XmlDoc.xmlStr.IndexOf("<", begin, end - begin + 1); if (index != -1) { this.hasNext = true; return true; } return false; } //设置元素的内容 internal void setContent() { if (this.hasChildren()) { return; } this.Content = XmlDoc.xmlStr.Substring(this.startindex2 + 1, this.endindex1 - this.startindex2 - 1).Trim(); } /// <summary> /// 根据元素在字符串中的起始索引和结束索引设置元素的字段信息 /// </summary> /// <param name="begin">初始索引</param> /// <param name="end">结束索引</param> internal void InitialXmlNode(int begin, int end) { this.startindex1 = XmlDoc.xmlStr.IndexOf("<", begin, end - begin + 1); this.startindex2 = XmlDoc.xmlStr.IndexOf(">", this.startindex1 + 1, end - startindex1); if (this.startindex1 == -1 || this.startindex2 == -1) { throw new XmlInvalidException(); } int temp = XmlDoc.xmlStr.IndexOf(" ", this.startindex1, this.startindex2 - this.startindex1 + 1); if (temp != -1) { this.startMarker = XmlDoc.xmlStr.Substring(this.startindex1, temp - this.startindex1 + 1).Trim() + ">"; this.InitialNodeAttribute(this.startindex1, this.startindex2); } else { this.startMarker = XmlDoc.xmlStr.Substring(this.startindex1, this.startindex2 - this.startindex1 + 1); } this.name = this.startMarker.Substring(1, this.startMarker.Length - 2).Trim(); //this.endMarker = this.startMarker.Replace("<", "</"); this.endMarker = "</" + this.name + ">"; this.endindex1 = XmlDoc.xmlStr.IndexOf(this.endMarker, this.startindex2 + 1); if (this.endindex1 == -1) { throw new XmlInvalidException(string.Format("没有匹配的元素尾:{0}", this.endMarker)); } this.endindex2 = this.endindex1 + this.endMarker.Length - 1; } /// <summary> /// 根据元素头在字符串中的起始索引和终止索引设置元素的属性 /// </summary> /// <param name="begin"></param> /// <param name="end"></param> private void InitialNodeAttribute(int begin, int end) { int cbegin = XmlDoc.xmlStr.IndexOf("\"", begin, end - begin + 1) + 1; int cend = XmlDoc.xmlStr.IndexOf("\"", cbegin, end - cbegin + 1) - 1; int equal = XmlDoc.xmlStr.LastIndexOf("=", end, end - begin + 1); int nbegin = XmlDoc.xmlStr.IndexOf(" ", begin, equal - begin + 1); int nend = XmlDoc.xmlStr.IndexOf(" ", nbegin + 1, equal - nbegin); nend = nend == -1 ? equal - 1 : nend; //属性等号之前无空格 this.attribute.Name = XmlDoc.xmlStr.Substring(nbegin, nend - nbegin + 1).Trim(); this.attribute.Content = XmlDoc.xmlStr.Substring(cbegin, cend - cbegin + 1).Trim(); } //用于输出格式化结点 public override string ToString() { string str = ""; int deep = this.Depth(); //深度大于2的元素,只显示子元素名称,不显示具体内容 if (deep > 2) { for (int i = 0; i < this.Nodes.Count; i++) { str += "{" + this.Nodes[i].Name + "}"; } } else if (deep == 2) //深度等于2的元素,显示所有子元素的名称及其内容 { for (int i = 0; i < this.Nodes.Count; i++) { str += this.Nodes[i].Name + ":" + this.Nodes[i].Content + "\t"; } if (this.Attribute.Name != "") { str += this.Attribute.Name + ":" + this.Attribute.Content; } } else //深度等于1的元素,显元素的名称及其内容 { return this.Name + ":" + this.Content; } return str; } //获取元素的深度,没有子元素的深度为1 internal int Depth() { if (!this.hasChild) { return 1; } else { int max = 1; for (int i = 0; i < this.Nodes.Count; i++ ) { int deep = this.Nodes[i].Depth() + 1; max = max > deep ? max : deep; } return max; } } //添加子元素 public void AppendChild(XmlNode node) { string str = node.StringXML(); node.father = this; this.Nodes.Add(node); XmlDoc.xmlStr = XmlDoc.xmlStr.Insert(this.startindex2 + 1, "\r\n" + str); } //获取结点的字符串表示形式 private string StringXML() { StringBuilder sb = new StringBuilder(); sb.Append(this.startMarker + this.Content + this.endMarker); if (this.Attribute.Name != "") { string temp = string.Format("{0} {1}=\"{2}\">", this.startMarker.Substring(0, this.startMarker.Length - 1), this.Attribute.Name, this.Attribute.Content); sb.Replace(this.startMarker, temp); } return sb.ToString(); } } }
主函数
static void Main(string[] args) { try { XmlDoc xml = new XmlDoc(@"C:\Users\Administrator\Desktop\testdata.txt"); Console.WriteLine("XML声明信息:"); Console.WriteLine(xml.Remark); Console.WriteLine("\n输出单个结点的信息:"); Console.WriteLine(xml.Root.Nodes[0].Nodes[0].Content); Console.WriteLine(xml.Root.Nodes[0].ToString()); Console.WriteLine(xml.Root.Nodes[1].ToString()); Console.WriteLine(xml.Root.Nodes[2].ToString()); Console.WriteLine("\n输出XML文档所有(深度为2)结点的信息:"); Console.Write(xml.ToString()); Console.WriteLine("\n输出根据名字查找到的元素:"); List<XmlNode> nodes = xml.GetElementsByTagName("author"); foreach (XmlNode node in nodes) { Console.WriteLine(node.ToString()); } string path = @"C:\Users\Administrator\Desktop\tt.txt"; XmlNode newnode = new XmlNode(); newnode.Name = "XXX"; newnode.Content = "YYY"; newnode.Attribute = new NodeAttribute("attributeName", "attributeValue"); xml.Root.AppendChild(newnode); XmlDoc.WriteToFile(path); Console.ReadKey(); } catch (Exception e) { Console.WriteLine(e.Message); } }
测试结果:
输入:
输出: