unity編輯器xml數據庫插件

unity編輯器xml數據庫插件

注:9月9日更新,其中MyXML.cs中有一句代碼寫錯,查找功能失誤,文中已經修改!html

注:9月1日更新說明:xml存儲結構,由於在用xml以前不知道正規的xml數據結構,因此是自創的結構。雖然也能完成功能,可是聽說策劃配置時不方便,因此爲了統一,不使用節點的方式存儲數據,數據庫

而是經過添加屬性,設置屬性的方式來存取數據。數組

直接上圖看的清楚些:緩存

我以前設計的格式:數據結構

如今的格式:編輯器

關於這部分的代碼我會貼在最後。ide

程序和數據分離的意義我就很少說了,你們本身腦補或者百度。在使用unity開發時,數據的調試是很是頻繁和重要的。咱們能夠製做一個簡單的編輯器插件,將數據顯示在Inspector面板上,並進行編輯操做。這樣測試人員就能夠很是方便的管理測試數據了。性能

需求很簡單,具體的效果是,能讀取資源內的類,將其屬性顯示在面板上,能夠對此進行增刪改查的操做。以下圖所示(對象組,至關於數據庫全部的表。對象,至關於表的全部記錄)。測試

 

 

 

 

當須要建立一條新記錄的時候,先填上主鍵,而後點擊建立按鈕。編輯完成後點擊插入便可。this

 

 

 

 

 

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

相關文章
相關標籤/搜索