unity编辑器xml数据库插件

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

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

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

直接上图看的清楚些:

我之前设计的格式:

现在的格式:

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

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

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

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

xml数据库文件如下图

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

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

下面是代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
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;
} }

转载unity编辑器xml数据库插件的更多相关文章

  1. 【Unity优化】如何实现Unity编辑器中的协程

    Unity编辑器中何时需要协程 当我们定制Unity编辑器的时候,往往需要启动额外的协程或者线程进行处理.比如当执行一些界面更新的时候,需要大量计算,如果用户在不断修正一个参数,比如从1变化到2,这种 ...

  2. 【Unity编辑器】UnityEditor多重弹出窗体与编辑器窗口层级管理

    一.简介 最近马三为公司开发了一款触发器编辑器,对于这个编辑器策划所要求的质量很高,是模仿暴雪的那个触发器编辑器来做的,而且之后这款编辑器要作为公司内部的一个通用工具链使用.其实,在这款触发器编辑器之 ...

  3. 自定义Kettle数据库插件

    项目需要实现使用Kettle向神通数据库中写入数据,Kettle官方标准的数据库插件里面并没有对神通数据库的支持,因此需要自己写一个数据库插件.下面我们开始写一个数据库插件 1.在eclipse中创建 ...

  4. Eclipse的数据库插件

    今天上午升级 Eclipse 到 3.1.2 版本,完了之后就想找个数据库的插件,但花了近 2 个小时后得出的结论是:还没有支持 3.1.x 版本的数据库插件,郁闷的不行.看看 eclipse3.1. ...

  5. Unity编辑器扩展 Chapter7--使用ScriptableObject持久化存储数据

    Unity编辑器扩展 Chapter7--使用ScriptableObject持久化存储数据 unity unity Editor ScirptableObject  Unity编辑器扩展 Chapt ...

  6. Unity编辑器扩展chapter1

    Unity编辑器扩展chapter1 unity通过提供EditorScript API 的方式为我们提供了方便强大的编辑器扩展途径.学好这一部分可以使我们学会编写一些工具来提高效率,甚至可以自制一些 ...

  7. Android Studio如何导出可供Unity使用的aar插件详解

    http://www.cnblogs.com/xtqqkss/p/6387271.html 前言 项目之前使用Eclipse导出的jar文件来做与Android交互,最近因为工作需要需使用Androi ...

  8. notepad++ 编辑xml的插件和使用方法

    notepad++ 编辑xml的插件和使用方法.mark http://blog.csdn.net/wangnan537/article/details/48712233

  9. 提高生产性工具(四) - XML数据库的尝试

    首先祝大家新年快乐.身体健康,平安就是福气. 对于一般的个人迷你项目,数据量不大的时候,完全没有必要使用数据库,管理数据使用XML就可以了. 自己尝试写了一个XML数据库,插入1w条小记录,大概3M大 ...

随机推荐

  1. java8(二)方法引用

    方法引用让你可以重复使用现有的方法定义,并像 Lambda 一样进行传递. 方法引用可以被看作仅仅调用特定方法的 Lambda 的一种快捷写法. 事实上,方法引用就是让你根据已有的方法实现来创建 La ...

  2. (十九)c#Winform自定义控件-停靠窗体

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  3. AutoCAD C#二次开发

    https://www.cnblogs.com/gisoracle/archive/2012/02/19/2357925.html using System; using System.Collect ...

  4. 获取n月后的当前时间

    例如用户计算会员的到期日期时间 public static Date getMonthNextOrBeforeDate(int monthNum) { Date dNow = new Date(); ...

  5. spring-boot-plus更新日志 CHANGELOG(九)

    spring-boot-plus更新日志 CHANGELOG [V1.2.0-RELEASE] 2019.08.06

  6. linux环境部署,docker如何安装redis

    安装步骤 1. 安装Redis 通过docker search redis和docker pull redis下载redis镜像 2. 新建挂载配置文件夹 新建data和conf两个文件夹,位置随意. ...

  7. 关于selenium自动化对窗口句柄的处理

    首先什么是句柄?句柄就是你点击一个页面,跳转了一个新的窗口.你要操作的元素可能在原窗口上,也有可能在新窗口上. 看下图句柄1 句柄2 由这2张图可知,url不一样,证明他们是处于不同的界面,我要操作的 ...

  8. SpringBoot读取配置文件源码探究

    1. SpringBoot读取配置文件源码探究 1.1. 概览 springboot的源码是再原来的Spring源码上又包了一层,看过spring源码都知道,当我们从入口debug进去的时候,原来的S ...

  9. Setup Factory 9 简单打包

    由于项目资源太大,使用VS自带打包工具无法实现需求,所以Setup Factory 9进行打包生成多个文件的方案,下面记录使用方法: 一:这里点击下载:下载,提取码:tt7a 二:下载完安装需要注册码 ...

  10. Kubernetes 入门必备云原生发展简史

    作者|张磊 阿里云容器平台高级技术专家,CNCF 官方大使 "未来的软件一定是生长于云上的"这是云原生理念的最核心假设.而所谓"云原生",实际上就是在定义一条能 ...