zoukankan      html  css  js  c++  java
  • unity编辑器xml数据库插件

    unity编辑器xml数据库插件

    注:9月9日更新,其中MyXML.cs中有一句代码写错,查找功能失误,文中已经修改!

    注:9月1日更新说明:xml存储结构,因为在用xml之前不知道正规的xml数据结构,所以是自创的结构。虽然也能完成功能,但是据说策划配置时不方便,所以为了统一,不使用节点的方式存储数据,

    而是通过添加属性,设置属性的方式来存取数据。

    直接上图看的清楚些:

    我之前设计的格式:

    现在的格式:

    关于这部分的代码我会贴在最后。

    程序和数据分离的意义我就不多说了,大家自己脑补或者百度。在使用unity开发时,数据的调试是非常频繁和重要的。我们可以制作一个简单的编辑器插件,将数据显示在Inspector面板上,并进行编辑操作。这样测试人员就可以非常方便的管理测试数据了。

    需求很简单,具体的效果是,能读取资源内的类,将其属性显示在面板上,可以对此进行增删改查的操作。如下图所示(对象组,相当于数据库所有的表。对象,相当于表的所有记录)。

     

     

    当需要创建一条新记录的时候,先填上主键,然后点击创建按钮。编辑完成后点击插入即可。

     

     

    xml数据库文件如下图

    要实现这个功能,需要的知识是,C#的反射类,unity的编辑器类,数据库。通过反射,自动解析对象,获取对象的成员变量名和值。Unity编辑器类没什么好说的,就是一些组件方法的使用。考虑到跨平台等问题,我选择xml作为存储数据库。编辑器内运行,存储量不大,所以性能方面的问题也就不说了。

    好,接下来说一说设计的事。首先是对象的反射。基本类型的存储没有问题,难点是数组的存取有点变态。我找了很多资料也不能自动创建某一类型的数组。既然不能自动,然后就使用半自动判断了,无非是if else之类的,看看这个属性是不是某一类型的数组。

    下面是代码。

    using System;
    using System.Reflection;
    using UnityEngine;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    public class ClassAnalyze<T>
    {
        private string[] cols;
    
        public string[] Cols
        {
            get { return cols; }
            set { cols = value; }
        }
        private string[] values;
    
        public string[] Values
        {
            get { return values; }
            set { values = value; }
        }
    
        public string ClazzName
        {
            get { return tempClazz.GetType().Name; }
    
        }
        private PropertyInfo[] property;
        private T tempClazz;
    
        public static System.Object CreateObject(string objName) {
            return Assembly.GetExecutingAssembly().CreateInstance(objName);
        }
        public T GetClazz(string[] values)
        {//将数值赋给对象,然后再获取
    
            SetClazz(values);
            this.Values = values;
            if (tempClazz == null)
            {
                return default(T);
            }
            return tempClazz;
        }
        public void SetClazz(string[] values)
        {//将数值赋给对象,然后再获取
    
            if (tempClazz != null && this.Values.Length == values.Length)
            {
                this.Values = values;
                for (int i = 0; i < property.Length; i++)
                {
                    if (tempClazz.GetType().GetProperty(Cols[i]).PropertyType.IsArray)
                    {
    
                        var tempArr = StringToArr(tempClazz.GetType().GetProperty(Cols
    [i]).GetValue(tempClazz, null), values[i].Split(new char[] { '|' }));
    
                        property[i].SetValue(tempClazz, tempArr, null);
                    }
                    else
                    {
                        property[i].SetValue(tempClazz, Convert.ChangeType(values[i], property[i].PropertyType), null);
                    }
                }
            }
        }
        private System.Object StringToArr(System.Object arr, string[] values)
        {
            if (arr is string[])
            {
                arr = new string[values.Length];
                for (int i = 0; i < values.Length; i++)
                {
                    (arr as string[])[i] = values[i];
                }
                return (string[])arr;
            }
            else if (arr is int[])
            {
                arr = new int[values.Length];
                for (int i = 0; i < values.Length; i++)
                {
                    (arr as int[])[i] = int.Parse(values[i]);
                }
                return (int[])arr;
            }
            else if (arr is Single[])
            {
                arr = new Single[values.Length];
                for (int i = 0; i < values.Length; i++)
                {
                    (arr as Single[])[i] = Single.Parse(values[i]);
                }
                return (Single[])arr;
            }
            else if (arr is float[])
            {
                arr = new float[values.Length];
                for (int i = 0; i < values.Length; i++)
                {
                    (arr as float[])[i] = float.Parse(values[i]);
                }
                return (float[])arr;
            }
            else if (arr is double[])
            {
                arr = new double[values.Length];
                for (int i = 0; i < values.Length; i++)
                {
                    (arr as double[])[i] = double.Parse(values[i]);
                }
                return (double[])arr;
            }
            else if (arr is long[])
            {
                arr = new long[values.Length];
                for (int i = 0; i < values.Length; i++)
                {
                    (arr as long[])[i] = long.Parse(values[i]);
                }
                return (long[])arr;
            }
            else if (arr is System.Object[])
            {
                arr = new System.Object[values.Length];
    
                for (int i = 0; i < values.Length; i++)
                {
    
                    (arr as System.Object[])[i] = values[i];
                }
                return (System.Object[])arr;
            }
    
    
            return arr;
        }
    
        private string ArrToString(System.Object arr)
        {
    
            string values = "";
    
    
            if (arr is System.Object[])
            {
                foreach (var value in arr as System.Object[])
                {
                    values += value + "|";
                }
            }
            else if (arr is string[])
            {
                foreach (var value in arr as string[])
                {
                    values += value + "|";
                }
            }
            else if (arr is int[])
            {
                foreach (var value in arr as int[])
                {
                    values += value + "|";
                }
            }
            else if (arr is Single[])
            {
                foreach (var value in arr as Single[])
                {
                    values += value + "|";
                }
            }
            else if (arr is float[])
            {
                foreach (var value in arr as float[])
                {
                    values += value + "|";
                }
            }
            else if (arr is double[])
            {
                foreach (var value in arr as double[])
                {
                    values += value + "|";
                }
            }
            else if (arr is long[])
            {
                foreach (var value in arr as long[])
                {
                    values += value + "|";
                }
            }
    
            values = values.TrimEnd(new char[] { '|' });
            return values;
        }
        public void AnalyzeClazz()
        {
            if (tempClazz != null)
            {
    
                property = tempClazz.GetType().GetProperties();
                Cols = new string[property.Length];
                Values = new string[property.Length];
                for (int i = 0; i < property.Length; i++)
                {
                    Cols[i] = property[i].Name;
                    string value = "";
                    if (tempClazz.GetType().GetProperty(Cols[i]).PropertyType.IsArray)
                    {
                        value = ArrToString(tempClazz.GetType().GetProperty(Cols[i]).GetValue(tempClazz, null));
                    }
                    else
                    {
                        value = Convert.ToString(tempClazz.GetType().GetProperty(Cols[i]).GetValue(tempClazz, null));
                    }
                    Values[i] = value;
                }
            }
        }
        private ClassAnalyze()
        {
    
        }
        public ClassAnalyze(T tempClazz)
        {
            this.tempClazz = tempClazz;
            AnalyzeClazz();
        }
    
        public void Close()
        {
            tempClazz = default(T);
            Cols = null;
            Values = null;
            property = null;
        }
        public System.Object GetValue(T t, string colName)
        {
            return tempClazz.GetType().GetProperty(colName).GetValue(tempClazz, null);
        }
        public void SetValue(T t, string colName,string value)
        {
            for (int i = 0; i < property.Length; i++) {
                if (property[i].Name == colName) {
                    if (property[i].PropertyType.IsArray)
                    {
                        var tempArr = StringToArr(property[i].GetValue(tempClazz, null), value.Split(new char[] { '|' }));
    
                        property[i].SetValue(tempClazz, tempArr, null);
                    }
                    else {
                        property[i].SetValue(tempClazz, Convert.ChangeType(value, property[i].PropertyType), null);
                    
                    }
                    break;
                }
            }
    
        }
    
        public override string ToString()
        {
            string values = "";
            for (int i = 0; i < Cols.Length; i++)
            {
                values += Cols[i] + ":{" + this.Values[i] + "} ";
            }
    
            return base.ToString() + ": " + values;
        }
    }
    

      

    反射搞定后就是设计xml数据库了,具体的功能看个人需求。关于操作xml还是很简单的。

     

    using System.Xml;
    using System.Collections.Generic;
    using System.IO;
    using System;
    
    using UnityEngine;
    public abstract class DB
    {
        /*public abstract bool CheckTable(string tableName);
        public abstract bool CheckDB(string dBName);
        public abstract void CreateTable(string tableName);
        public abstract void CreateDB(string dBName);*/
        public abstract bool Insert(string tableName, string[] cols, string[] values, string key);
        public abstract bool Update(string tableName, string[] cols, string[] values, string key);
        public abstract bool UpdateAll(string tableName);
        public abstract bool Delete(string tableName,  string key);
        public abstract bool DeleteAll(string tableName);
        public abstract string[] Select(string tableName, string key);
        public abstract List<string[]> SelectAll(string tableName);
        public abstract void Connect(string path);
        public abstract void Close();
        public abstract string[] SelectAllObjectsName(string tableName);
        
    }
    public class XmlSql : DB
    {
        //public static string values[0] = "values[0]";
        private XmlDocument xmlDoc;
        private string path;
        private string rootName;
        public XmlSql()
        {
            xmlDoc = new XmlDocument();
        }
        public XmlSql(string path)
        {
            xmlDoc = new XmlDocument();
            Connect(path);
        }
        public override void Connect(string path)
        {
            if (xmlDoc == null) xmlDoc = new XmlDocument();
            if (!CheckDB(path))
            {
                this.path = path;
                rootName = path.Substring(path.LastIndexOf("/")+1,path.LastIndexOf(".")- path.LastIndexOf("/")-1);
                CreateDB(rootName);
            }
            else {
                this.path = path;
                
                xmlDoc.Load(this.path);
                rootName = xmlDoc.LastChild.LocalName;
            }
        }
        public override void Close()
        {
            if (xmlDoc != null)
            xmlDoc.Save(path);
            GC.Collect();
        }
    
    
        public XmlNode CheckTable(string tableName)
        {
            XmlNode root = xmlDoc.SelectSingleNode(rootName);
            if (root.SelectSingleNode(tableName) != null) {
                return root.SelectSingleNode(tableName);
            }
    
            return CreateTable(root,tableName);
        }
        public bool CheckDB(string dBName)
        {
            return File.Exists(dBName);
        }
        public XmlNode CreateTable(XmlNode root,string tableName)
        {
            XmlNode table = xmlDoc.CreateElement(tableName);
            root.AppendChild(table);
            xmlDoc.Save(path);
            return table;
        }
        public XmlNode CreateDB(string dBName)
        {
            File.CreateText(path).Close();
            XmlDeclaration xmlDeclaration = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
            XmlNode root = xmlDoc.CreateElement(dBName);
            xmlDoc.AppendChild(xmlDeclaration);
            xmlDoc.AppendChild(root);
            xmlDoc.Save(path);
            return root;
        }
    
    
        public override bool Insert(string tableName, string[] cols, string[] values,string key)
        {
    
            if (key == null || key == "") key = values[0];
            key = key.Replace(" ","");
            XmlNode table = CheckTable(tableName);
    
            XmlNode obj = table.SelectSingleNode(key);//按照key值确定元素对象
    
            if (obj != null) {//待插入数据已经存在,插入失败
                return false;
            }
    
            XmlElement element = xmlDoc.CreateElement(key);
    
            for(int i=0;i<cols.Length;i++){
                XmlElement e = xmlDoc.CreateElement(cols[i]);
                e.InnerText = values[i].Replace(" ", "");
                element.AppendChild(e);
            }
            table.AppendChild(element);
            xmlDoc.Save(path);
            return true;
        }
        public override bool Update(string tableName, string[] cols, string[] values,string key)
        {
            if (key == null || key == "") key = values[0];
            key = key.Replace(" ", "");
            XmlNode table = CheckTable(tableName);
    
            XmlNode obj = table.SelectSingleNode(key);//按照key值确定元素对象
            if (obj == null)
            {//待更新数据不存在,更新失败
                return false;
            }
            for (int i = 0; i < cols.Length; i++)
            {
                obj.SelectSingleNode(cols[i]).InnerText = values[i].Replace(" ", "");
            }
            xmlDoc.Save(path);
            return true;
    
           
        }
    
        public override bool UpdateAll(string tableName)
        {
            return false;
        }
        public override string[] Select(string tableName, string key)
        {
            XmlNode table = CheckTable(tableName);
            if (key == null || key == "") {
                if (table.ChildNodes.Count < 1) { 
                return null;
                }
                key = table.ChildNodes[0].LocalName;
            } 
            key = key.Replace(" ", "");
            
            XmlNode obj = table.SelectSingleNode(key);//按照key值确定元素对象
    
            if (obj == null) {
                return null;
            }
    
            string[] values = new string[obj.ChildNodes.Count];
    
            for (int i = 0; i < values.Length; i++) {
                values[i] = obj.ChildNodes.Item(i).InnerText.Replace(" ", "");
            }
    
            return values;
        }
        public override string[] SelectAllObjectsName(string tableName)
        {
            XmlNode table = CheckTable(tableName);
            
            string[] values = new string[table.ChildNodes.Count];
    
            for (int i = 0; i < values.Length; i++) {
                values[i] = table.ChildNodes[i].LocalName;
            }
            return values;
        }
        public override List<string[]> SelectAll(string tableName)
        {
            XmlNode table = CheckTable(tableName);
            if (table.ChildNodes.Count == 0) {
                return null;
            }
            List<string[]> elements = new List<string[]>();
            for(int i=0;i<table.ChildNodes.Count;i++){
    
                string[] values = new string[table.ChildNodes[i].ChildNodes.Count];
                for (int j = 0; j < table.ChildNodes[i].ChildNodes.Count; j++) {
    
                    values[j] = table.ChildNodes[i].ChildNodes.Item(j).InnerText.Trim();
                }
                elements.Add(values);
            }
            return elements;
        }
        public override bool Delete(string tableName, string key)
        {
            XmlNode table = CheckTable(tableName);
            if (key == null || key == "") key = table.ChildNodes[0].LocalName;
            key = key.Replace(" ", "");
            
    
            XmlNode obj = table.SelectSingleNode(key);//按照key值确定元素对象
            if (obj == null)
                return false;
            obj.RemoveAll();
            table.RemoveChild(obj);
            xmlDoc.Save(path);
            return true;
        }
        public override bool DeleteAll(string tableName)
        {
            XmlNode table = CheckTable(tableName);
            table.RemoveAll();
            xmlDoc.Save(path);
            return true;
        }
    }

    接下来就是编辑器的设计。没什么高大上的东西,就是一些读写和调用的方法,以及一些逻辑上的处理。

     

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using System.Reflection;
    using System;
    public class MyInspector : MonoBehaviour {
    
        //这个类是一个编辑器类,作用是展示存储的xml数据
        //选择对象,然后进行编辑
        //如果数据库中有这个数值,将其读取并显示
        //如果没有,则按需求创建数据
        //public string path;
    
        public string defaultKey = "PriKey";
        public ObjectMessage objMessage;
        public string DataPath = "gameData.xml";
        public MySql mySql;
        public bool IsHave = false;
        public bool IsShow = false;
        //private System.Object tempObj;
        public void GetDataBase(string dataPath) {
            DB db = MyDataBase.GetDataBase().Connection(dataPath);
            mySql = new MySql(db);
        }
        
        public void SaveMessage(string objName)
        {
            if (mySql != null)
            {
                System.Object obj = Assembly.GetExecutingAssembly().CreateInstance(objName);
                ClassAnalyze<System.Object> tempAnalyze = new ClassAnalyze<System.Object>(obj);
                obj=tempAnalyze.GetClazz(objMessage.values);
    
                if (IsHave)
                {
                    mySql.Update(obj, defaultKey);
    
                }
                else {
                    mySql.Insert(obj, defaultKey);
                    ReadObj(objMessage.NamesOfModel[objMessage.indexOfModel]);
                }
                   
            }
        }
        public void RemoveMessage(string objName, string key)
        {
            if (mySql != null)
            {
                System.Object obj = Assembly.GetExecutingAssembly().CreateInstance(objName);
                ClassAnalyze<System.Object> tempAnalyze = new ClassAnalyze<System.Object>(obj);
                tempAnalyze.SetValue(obj, defaultKey, key);
    
                if (IsHave)
                {
                    mySql.Delete(obj, defaultKey);
                    IsHave = false;
                    ClearObjMessage();
                }
                
            }
        }
        
        public void ClearObjMessage()
        {
            for (int i = 0; i < objMessage.values.Length; i++) {
                objMessage.values[i] = "";
            }
        }
        
        public void ReadModel() {
            TextAsset[] tas = Resources.LoadAll<TextAsset>(objMessage.objectPath);
            objMessage. NamesOfModel = new string[tas.Length];
            for (int i = 0; i < tas.Length; i++) {
                objMessage.NamesOfModel[i] = tas[i].name;
            }
            
        }
        public void ReadObj(string tableName)
        {
            if(mySql!=null)
            objMessage.NamesOfObj = mySql.SelectAllObjectsName(tableName);
        }
        public void CheckData(string objName, string key)
        {
            System.Object obj = Assembly.GetExecutingAssembly().CreateInstance(objName);
            ClassAnalyze<System.Object> tempAnalyze = new ClassAnalyze<System.Object>(obj);
            tempAnalyze.SetValue(obj, defaultKey, key);
            objMessage.cols = tempAnalyze.Cols;
            obj = mySql.Select(obj, defaultKey);
            IsHave = (obj != null);
            if (IsHave)
            {
                tempAnalyze = new ClassAnalyze<System.Object>(obj);
    
    
                objMessage.values = tempAnalyze.Values;
            }
            else {
                objMessage.values = new string[objMessage.cols.Length];
            }
        }
    }
    [Serializable]
    public class ObjectMessage
    {
    
        public string objectPath = "Model";//对象所处的路径(基于Resources的相对路径)
        public string[] NamesOfModel;
        public string[] NamesOfObj;
        public int indexOfModel = 0;
        public int indexOfObj = 0;
        public string PriKey = "PriKey";
        public string[] cols;
        public string[] values;
        
    }

    下面这个脚本要放在Editor目录下面

    using UnityEngine;
    using System.Collections;
    using UnityEditor;
    
    [CustomEditor(typeof(MyInspector))]
    public class EditorInspector : Editor {
        //重写展示面板
    
    
        //用户选择要加载的对象
        //提供一个主键,用户填写主键的值
        //默认主键是游戏对象名称
        //判断此对象是否已经保存在数据库中
        //如果已经存在此主键,则,加载数据到面板
        //如果没有此主键,提示用户是否创建
        //
        private SerializedObject TargetObj;
        private MyInspector MyPlane;
        private string[] shows= new string[]{"创建","加载"};
        private void InitPlane() {
            TargetObj = new SerializedObject(target);//获取编辑对象目标
            MyPlane = target as MyInspector;//转化为编辑对象
            CheckData();//检测数据
        }
    
        private void CheckData() {
            if (MyPlane.objMessage == null)//检查信息对象是否为空
            {
                MyPlane.objMessage = new ObjectMessage();//对象信息
            }
            if (MyPlane.objMessage.NamesOfModel == null || MyPlane.objMessage.NamesOfModel.Length < 1)
            {//检查对象数组
                MyPlane.ReadModel();//读取对象
            }
            if (MyPlane.objMessage.NamesOfObj == null || MyPlane.objMessage.NamesOfObj.Length < 1)
            {//检查对象数组
                MyPlane.ReadObj(MyPlane.objMessage.NamesOfModel[MyPlane.objMessage.indexOfModel]);//读取对象
            }
            if (MyPlane.objMessage.PriKey == null || MyPlane.objMessage.PriKey == "")
            {//检查对象主键名称
                //设置主键信息
                MyPlane.objMessage.PriKey = MyPlane.gameObject.name.Replace(" ", "");
            }
            if (MyPlane.mySql == null)
            {//检查数据库的连接状态
                //获取数据库连接
                 MyPlane.GetDataBase(MyPlane.DataPath);
            }
    
        }
        void OnEnable() {
    
            InitPlane();
            
        }
        
        public override void OnInspectorGUI()
        {
            
            TargetObj.Update();//更新目标数据
            
            //主键值
            //CheckData();
            int lastModel = MyPlane.objMessage.indexOfModel;
            //对象选择列表
            MyPlane.objMessage.indexOfModel = EditorGUILayout.Popup("对象组", MyPlane.objMessage.indexOfModel, MyPlane.objMessage.NamesOfModel);
            
            if (lastModel != MyPlane.objMessage.indexOfModel) { //当改变对象时,更新主键值
                //更新主键值集合
                MyPlane.ReadObj(MyPlane.objMessage.NamesOfModel[MyPlane.objMessage.indexOfModel]);
    
            }
            int lastobj = MyPlane.objMessage.indexOfObj;
            if (MyPlane.objMessage.NamesOfObj.Length > 0)
            {
                MyPlane.objMessage.indexOfObj = EditorGUILayout.Popup("对象", MyPlane.objMessage.indexOfObj, MyPlane.objMessage.NamesOfObj);
            }
            if (lastobj != MyPlane.objMessage.indexOfObj || lastModel != MyPlane.objMessage.indexOfModel)
            { //主键值集合下标改变时
                //更新主键值
                if (MyPlane.objMessage.NamesOfObj.Length>0)
                MyPlane.objMessage.PriKey = MyPlane.objMessage.NamesOfObj[MyPlane.objMessage.indexOfObj];
            }
           
    
            string lastKey = MyPlane.objMessage.PriKey;
            //显示主键文本框
            MyPlane.objMessage.PriKey = EditorGUILayout.TextField("主键", MyPlane.objMessage.PriKey);
            //路径
    
    
            string lastPath = MyPlane.DataPath;
            MyPlane.DataPath = EditorGUILayout.TextField("数据路径",MyPlane.DataPath);
            
            //判断选择的对象列表
            //更新对象信息
    
            if (MyPlane.objMessage.indexOfModel != lastModel || lastKey != MyPlane.objMessage.PriKey || lastPath != MyPlane.DataPath || lastobj != MyPlane.objMessage.indexOfObj)//改变了一些数据时重新读取数据
            {
                MyPlane.IsHave = false;//标注数据改动
    
                CheckData();//读取数据前保证系统参数无误,以及各个对象正确加载
    
                MyPlane.CheckData(MyPlane.objMessage.NamesOfModel[MyPlane.objMessage.indexOfModel], MyPlane.objMessage.PriKey);
            }
            
            //当存在时直接加载
            //当不存在时,点击创建时加载
    
            
            bool _show = MyPlane.IsShow;//记录上一次的状态
            if (MyPlane.IsHave || (MyPlane.IsShow = EditorGUILayout.Foldout(MyPlane.IsShow, shows[MyPlane.IsShow ? 1 : 0])))
            {
                if (!_show && !MyPlane.IsHave)//数据不存在而且点击了创建的时候
                { //仅执行一次,保证数据不被一直刷新而导致的无法读写
                    //当数据不存在,而且点击创建时  清除信息
    
                    MyPlane.ClearObjMessage();//清除数据的缓存
                }
            }
            //也要只进行一次的读写,保证可以进行修改操作
            if (MyPlane.IsHave || MyPlane.IsShow)//当数据存在或者点击创建时加载数据
            {
                for (int i = 0; i < MyPlane.objMessage.cols.Length; i++)
                {
                    if (MyPlane.defaultKey == MyPlane.objMessage.cols[i]) {
                        MyPlane.objMessage.values[i] = MyPlane.objMessage.PriKey;
                        continue;
                    }
                    MyPlane.objMessage.values[i] = EditorGUILayout.TextField(MyPlane.objMessage.cols[i], MyPlane.objMessage.values[i]);
    
                }
                if (GUILayout.Button("Save"))
                {
                    MyPlane.SaveMessage(MyPlane.objMessage.NamesOfModel[MyPlane.objMessage.indexOfModel]);
                }
    
                if (MyPlane.IsHave&& GUILayout.Button("Remove"))
                {
                    MyPlane.RemoveMessage(MyPlane.objMessage.NamesOfModel[MyPlane.objMessage.indexOfModel], MyPlane.objMessage.PriKey);
                    MyPlane.ReadObj(MyPlane.objMessage.NamesOfModel[MyPlane.objMessage.indexOfModel]);
                    
                }
            }
    
            
            
            TargetObj.ApplyModifiedProperties();
            
        }
    
        void show(System.Object message) {
            Debug.Log(message);
        }
    }

    新的xml数据存储格式:新建脚本MyXmlSql,继承DB,然后实现具体的方法:

    using System.Xml;
    using System.Collections.Generic;
    using System.IO;
    using System;
    
    public class MyXmlSql : DB
    {
        private XmlDocument xmlDoc;
        private string path;
        private string rootName;
        public MyXmlSql()
        {
            xmlDoc = new XmlDocument();
        }
        public MyXmlSql(string path)
        {
            xmlDoc = new XmlDocument();
            Connect(path);
        }
        public override void Connect(string path)
        {
            if (xmlDoc == null) xmlDoc = new XmlDocument();
            if (!CheckDB(path))
            {
                this.path = path;
                rootName = path.Substring(path.LastIndexOf("/")+1,path.LastIndexOf(".")- path.LastIndexOf("/")-1);
                CreateDB(rootName);
            }
            else {
                this.path = path;
                
                xmlDoc.Load(this.path);
                rootName = xmlDoc.LastChild.LocalName;
            }
        }
        public override void Close()
        {
            if (xmlDoc != null)
            xmlDoc.Save(path);
            GC.Collect();
        }
    
    
        public XmlNode CheckTable(string tableName)
        {
            XmlNode root = xmlDoc.SelectSingleNode(rootName);
            if (root.SelectSingleNode(tableName) != null) {
                return root.SelectSingleNode(tableName);
            }
    
            return CreateTable(root,tableName);
        }
        public bool CheckDB(string dBName)
        {
            return File.Exists(dBName);
        }
        public XmlNode CreateTable(XmlNode root,string tableName)
        {
            XmlNode table = xmlDoc.CreateElement(tableName);
            root.AppendChild(table);
            xmlDoc.Save(path);
            return table;
        }
        public XmlNode CreateDB(string dBName)
        {
            File.CreateText(path).Close();
            XmlDeclaration xmlDeclaration = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
            XmlNode root = xmlDoc.CreateElement(dBName);
            xmlDoc.AppendChild(xmlDeclaration);
            xmlDoc.AppendChild(root);
            xmlDoc.Save(path);
            return root;
        }
    
    
        public override bool Insert(string tableName, string[] cols, string[] values,string key)
        {
    
            if (key == null || key == "") key = values[0];
            key = key.Replace(" ","");
            XmlNode table = CheckTable(tableName);
    
            XmlNode obj = table.SelectSingleNode(key);//按照key值确定元素对象
    
            if (obj != null) {//待插入数据已经存在,插入失败
                return false;
            }
    
            XmlElement element = xmlDoc.CreateElement(key);
    
            
            for (int i = 0; i < cols.Length; i++) {
                XmlAttribute xa = xmlDoc.CreateAttribute(cols[i]);
    
                xa.Value = values[i].Replace(" ", "");
                element.Attributes.Append(xa);
                
            }
    
            
            table.AppendChild(element);
            xmlDoc.Save(path);
            return true;
        }
        public override bool Update(string tableName, string[] cols, string[] values,string key)
        {
            if (key == null || key == "") key = values[0];
            key = key.Replace(" ", "");
            XmlNode table = CheckTable(tableName);
    
            XmlNode obj = table.SelectSingleNode(key);//按照key值确定元素对象
            if (obj == null)
            {//待更新数据不存在,更新失败
                return false;
            }
            for (int i = 0; i < cols.Length; i++)
            {
                obj.Attributes[cols[i]].Value = values[i].Replace(" ", "");
    
            }
            xmlDoc.Save(path);
            return true;
    
           
        }
    
        public override bool UpdateAll(string tableName)
        {
            return false;
        }
        public override string[] Select(string tableName, string key)
        {
            XmlNode table = CheckTable(tableName);
            if (key == null || key == "") {
                if (table.ChildNodes.Count < 1) { 
                return null;
                }
                key = table.ChildNodes[0].LocalName;
            } 
            key = key.Replace(" ", "");
            
            XmlNode obj = table.SelectSingleNode(key);//按照key值确定元素对象
    
            if (obj == null) {
                return null;
            }
    
            string[] values = new string[obj.Attributes.Count]; 
    for (int i = 0; i < values.Length; i++) {
                values[i] = obj.Attributes[i].Value.Replace(" ", "");
            }
    
            return values;
        }
        public override string[] SelectAllObjectsName(string tableName)
        {
            XmlNode table = CheckTable(tableName);
            
            string[] values = new string[table.ChildNodes.Count];
    
            for (int i = 0; i < values.Length; i++) {
                values[i] = table.ChildNodes[i].LocalName;
            }
            return values;
        }
        public override List<string[]> SelectAll(string tableName)
        {
            XmlNode table = CheckTable(tableName);
            if (table.ChildNodes.Count == 0) {
                return null;
            }
            List<string[]> elements = new List<string[]>();
            for(int i=0;i<table.ChildNodes.Count;i++){//遍历表的子节点
                string[] values = new string[table.ChildNodes[i].Attributes.Count];
                for (int j = 0; j < table.ChildNodes[i].Attributes.Count; j++)
                {
                    values[j] = table.ChildNodes[i].Attributes[j].Value.Trim();
                }
                elements.Add(values);
            }
            return elements;
        }
        public override bool Delete(string tableName, string key)
        {
            XmlNode table = CheckTable(tableName);
            if (key == null || key == "") key = table.ChildNodes[0].LocalName;
            key = key.Replace(" ", "");
            
    
            XmlNode obj = table.SelectSingleNode(key);//按照key值确定元素对象
            if (obj == null)
                return false;
            obj.RemoveAll();
            table.RemoveChild(obj);
            xmlDoc.Save(path);
            return true;
        }
        public override bool DeleteAll(string tableName)
        {
            XmlNode table = CheckTable(tableName);
            table.RemoveAll();
            xmlDoc.Save(path);
            return true;
        }
        
    }

     本文地址:http://www.cnblogs.com/jqg-aliang/p/4767026.html

  • 相关阅读:
    Python 爬虫 解决escape问题
    python 爬虫 重复下载 二次请求
    iOS开发-消息通知机制(NSNotification和NSNotificationCenter)
    iOS开发-UITableView自定义Cell
    iOS开发-自定义UIAlterView(iOS 7)
    iOS开发-CocoaPods实战
    iOS开发-UICollectionView实现瀑布流
    iOS开发-UITabBarController详解
    iOS 开发-Certificate、App ID和Provisioning Profile之间的关系
    iOS开发-View中frame和bounds区别
  • 原文地址:https://www.cnblogs.com/jqg-aliang/p/4767026.html
Copyright © 2011-2022 走看看