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. 【0731 | Day 5】Python基础(三)

    Part 10 格式化输出的三种方式 一.占位符 #一般字符串连接/普通形式 ​ name = 'Adela' age = str(22) print('My name is '+ name+ ',' ...

  2. LayDate使用

    layDate非常愿意和您成为工作伙伴.她致力于成为全球最用心的web日期支撑,为国内外所有从事web应用开发的同仁提供力所能及的动力.她基于原生JavaScript精心雕琢,兼容了包括IE6在内的所 ...

  3. 【转】linux tar.gz zip 解压缩 压缩命令

    http://apps.hi.baidu.com/share/detail/37384818 download ADT link http://dl.google.com/android/ADT-0. ...

  4. .net core 实现 api网关 进行 api版本控制

    场景: 由一次大的项目改动引起的app端api不兼容问题,这时候就需要对api做版本控制了,权衡之后因为用户不多,选择了强更,没人想在已经写了8000行代码的单个svc文件中维护好几个版本的接口或者继 ...

  5. go 学习笔记之是否支持以及如何实现继承

    熟悉面向对象的小伙伴们可能会知道封装,继承和多态是最主要的特性,为什么前辈们会如此看重这三种特性,真的那么重要吗? 什么是封装 什么是封装,封装有什么好处以及怎么实现封装? 相信大多数小伙伴们都有自己 ...

  6. MyBatis的parameterType传入参数类型

    在mybatis映射接口的配置中,有select,insert,update,delete等元素都提到了parameterType的用法,parameterType为输入参数,在配置的时候,配置相应的 ...

  7. 简析 Golang net/http 包

    net/http 包涵盖了与 HTTP 请求发送和处理的相关代码.虽然包中定义了大量类型.函数,但最重要.最基础的概念只有两个:ServeMux 和 Handler. ServeMux 是 HTTP ...

  8. python相关性算法解决方案(rest/数据库/json/下载)

    1. 场景描述 一直做java,因项目原因,需要封装一些经典的算法到平台上去,就一边学习python,一边网上寻找经典算法代码,今天介绍下经典的相关性算法,算法原理就不介绍了,只从代码层面进行介绍,包 ...

  9. .NET平台下,钉钉微应用开发之:获取userid

    工作需求,开发钉钉微应用和小程序,之前有接触过支付宝小程序和生活号的开发,流程没有很大的差别,这里记录下我用ASP.NET MVC实现钉钉微应用的开发,并实现获取用户的userid.小弟我技术有限,本 ...

  10. Nacos高可用集群解决方案-Docker版本

    文章主旨 本文目的是配置高可用的Nacos集群 架构图 整体架构为:Nginx + 3 x Nacos +高可用MySQL 高可用MySQL使用主从复制结构的可以参考Docker搭建MySQL主从集群 ...