C#读取XML文件——自定义类

简介: C#本身也带有读取XML文件的类,但是许久未曾接触C#了,为了练练手,自己写了一个具有简单功能的类,实现了读取xml文件,查找元素,插入结点等功能。实现如下: XmlDoc类 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.IO;na

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);
            }
        }

测试结果:

输入:


输出:



目录
相关文章
|
2月前
|
XML 前端开发 Java
讲解SSM的xml文件
本文详细介绍了SSM框架中的xml配置文件,包括springMVC.xml和applicationContext.xml,涉及组件扫描、数据源配置、事务管理、MyBatis集成以及Spring MVC的视图解析器配置。
60 1
|
4月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
18天前
|
Java Maven
maven项目的pom.xml文件常用标签使用介绍
第四届人文,智慧教育与服务管理国际学术会议(HWESM 2025) 2025 4th International Conference on Humanities, Wisdom Education and Service Management
74 8
|
2月前
|
XML JavaScript Java
java与XML文件的读写
java与XML文件的读写
26 3
|
6月前
|
XML Java 数据格式
java创建xml文件内容
java创建xml文件内容
|
6月前
|
XML Java 数据格式
java解析xml文件内容
java解析xml文件内容
|
2月前
|
XML 存储 缓存
C#使用XML文件的详解及示例
C#使用XML文件的详解及示例
96 0
|
2月前
|
XML 存储 Web App开发
查看 XML 文件
查看 XML 文件
|
3月前
|
SQL XML Java
mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
53 1
|
6月前
|
XML Java 数据库
配置applicationContext.xml文件
配置applicationContext.xml文件