C#本身也带有读取XML文件的类,但是许久未曾接触C#了,为了练练手,自己写了一个具有简单功能的类,实现了读取xml文件,查找元素,插入结点等功能。实现如下:
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 AllNodes = new List();
internal List nodes = new List();
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 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;
}
}
}
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 nodes = new List();
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 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();
}
///
/// 根据元素在字符串中的起始索引和结束索引设置元素的字段信息
///
/// 初始索引
/// 结束索引
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;
}
///
/// 根据元素头在字符串中的起始索引和终止索引设置元素的属性
///
///
///
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 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);
}
}
测试结果:
输入:
输出: