转载unity编辑器xml数据库插件
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; } }