Python解析xml配置文件,生成cs代码

最近项目用的配置表是xml文件,每次要手动添加两个cs代码文件,很浪费时间,所以写了一个代码生成工具,以下是代码

XmlGenTool.py

# -*- coding: utf-8 -*-
import wx
import xml.etree.ElementTree as et
import os

config_name = 'AssetsPath.txt'
assetsTextPath = os.getcwd() + "/" + config_name

class App(wx.App):
    def OnInit(self):
        frame = wx.Frame(parent=None, title='Xml代码生成器2.0', pos=(1000, 200), size=(650, 130))
        xmlNameTitle = wx.StaticText(frame, label="表名称", pos=(5,8), size=(100, 24))
        xmlNameInput = wx.TextCtrl(frame, pos=(105, 5), size=(400, 24))
        assetsPathTitle = wx.StaticText(frame, label="Assets文件目录", pos=(5, 40), size=(150, 30))
        assetsInput = wx.TextCtrl(frame, pos=(105, 40), size=(400, 24))
        checkButton = wx.Button(frame, label="生成代码", pos=(505, 5), size=(100, 24))

        #读取配置的Assets路径
        file = open(assetsTextPath, encoding='utf-8')
        if file:
            fileLineArr = file.readlines()
            for line in fileLineArr:
                strArr = line.replace('\n', '').split(',')
                if strArr[0] == "AssetsPath":
                    assetsInput.SetValue(strArr[1])

        def onClickCheckButton(event):
            xmlName = xmlNameInput.GetValue()
            assetsPath = assetsInput.GetValue()

            pathStr = assetsPath + '/Resources/XML/' + xmlName + ".xml"
            path = pathStr.replace('\\', '/')
            tree = et.parse(path)
            root = tree.getroot()
            node = root.find('item')
            numList = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
            typeDict = {}

            for k, v in node.items():
                if v == "":
                    typeDict[k] = "string"
                    continue

                char1 = v[0]
                if char1 in numList:
                    typeDict[k] = "int"  # int类型
                    if "." in v:
                        typeDict[k] = "float"  # float类型
                elif char1 == '-':
                    char2 = v[1]
                    if char2 in numList and "." in v:
                        typeDict[k] = "float"  # float类型
                    if char2 in numList and ("." not in v):
                        typeDict[k] = "int"  # int类型
                elif char1 == '[':
                    char2 = v[1]
                    if char2 in numList:
                        typeDict[k] = "numList"
                    elif char2 == "'":
                        typeDict[k] = "strList"
                    else:
                        typeDict[k] = "string"
                elif char1 == '{' and v[1] == "'":
                    isNum = False
                    for i in range(len(v)):
                        if v[i] == ':':
                            if i + 1 < len(v):
                                isNum = v[i + 1] in numList
                    typeDict[k] = "numDict" if isNum else "strDict"
                else:
                    typeDict[k] = "string"

            # print(typeDict)

            xFileDataPath = assetsPath + '/Scripts/Data/xml/'
            #写入x表文件
            file = open(xFileDataPath + 'X' + xmlName + ".cs", 'w+')
            writeStr = "using System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n\n"

            # Init val
            writeStr += "public class X" + xmlName + " : XSuper\n{\n\tpublic override string _id { get; protected set; }\n"
            writeStr += "\tpublic int id { get; private set; }\n"
            for k, v in typeDict.items():
                if k == '_id':
                    continue
                if v == "int":
                    writeStr += "\tpublic int " + k + " { get; private set; }\n"
                elif v == "float":
                    writeStr += "\tpublic float " + k + " { get; private set; }\n"
                elif v == "string":
                    writeStr += "\tpublic string " + k + " { get; private set; }\n"
                elif v == "numList":
                    writeStr += "\n\tpublic string " + k + " = string.Empty;\n"
                    writeStr += "\tpublic List<int> " + k + "List { get; private set; }\n"
                elif v == "strList":
                    writeStr += "\n\tpublic string " + k + " = string.Empty;\n"
                    writeStr += "\tpublic List<string> " + k + "List { get; private set; }\n"
                elif v == "numDict":
                    writeStr += "\n\tpublic string " + k + " { get; private set; }\n"
                    writeStr += "\tpublic Dictionary<string, int> " + k + "Dict { get; private set; }\n"
                elif v == "strDict":
                    writeStr += "\n\tpublic string " + k + " { get; private set; }\n"
                    writeStr += "\tpublic Dictionary<string, string> " + k + "Dict { get; private set; }\n"

            # Init From Xml
            writeStr += '\n\tpublic override void InitFromXml(XmlReadTool tool, int iCount)\n\t{\n\t\t_id = tool.GetAttribute("_id", "", iCount);\n'
            for k, v in typeDict.items():
                if k == '_id':
                    continue
                if v == "int":
                    writeStr += "\t\t" + k + ' = tool.GetAttribute("' + k + '", 0, iCount);\n'
                else:
                    writeStr += "\t\t" + k + ' = tool.GetAttribute("' + k + '", "", iCount);\n'

            # Init Property
            writeStr += "\t}\n\n\tpublic override void InitProperty()\n\t{\n"
            for k, v in typeDict.items():
                if k == '_id':
                    writeStr += "\t\tid = int.Parse(_id);\n"
                if v == "numDict":
                    writeStr += "\t\t" + k + 'Dict = JReadTool.Instance.ParseJsonToObject<Dictionary<string, int>>(' + k + ');\n'
                elif v == "strDict":
                    writeStr += "\t\t" + k + 'Dict = JReadTool.Instance.ParseJsonToObject<Dictionary<string, string>>(' + k + ');\n'
                elif v == "numList":
                    writeStr += "\t\tif (!string.IsNullOrEmpty(" + k + "))\n\t\t{\n\t\t\t" + k + "List = JReadTool.Instance.ParseJsonToObject<List<int>>(" + k + ");\n\t\t}\n"
                elif v == "strList":
                    writeStr += "\t\tif (!string.IsNullOrEmpty(" + k + "))\n\t\t{\n\t\t\t" + k + "List = JReadTool.Instance.ParseJsonToObject<List<string>>(" + k + ");\n\t\t}\n"

            # Parse Asset Xml
            writeStr += "\t}\n\n\tpublic void ParseAssetXml(AssetItem_X" + xmlName + " vAssetData)\n\t{\n"
            for k, v in typeDict.items():
                if v == "numDict" or v == "strDict":
                    writeStr += "\t\t" + k + "Dict = vAssetData.Deserialize_" + k + "Dict();\n"
                elif v == "numList" or v == "strList":
                    writeStr += "\t\t" + k + "List = vAssetData." + k + "List;\n"
                else:
                    writeStr += "\t\t" + k + " = vAssetData." + k + ";\n"
                    if k == "_id":
                        writeStr += "\t\t" + "id = vAssetData.id;\n"
            writeStr += "\t}\n\n}"

            file.write(writeStr)
            file.close()

            assetsRootDataPath = assetsPath + '/Scripts/Data/xml/XMLSObjct/'
            #写入AssetsRoot文件
            file = open(assetsRootDataPath + 'AssetRoot_X' + xmlName + ".cs", 'w+')
            writeStr = "using UnityEngine;\nusing System.Collections;\nusing System;\nusing System.Collections.Generic;\n\n"

            writeStr += "public class AssetRoot_X" + xmlName + " : IAssetRoot_Base\n{\n\t[HideInInspector]\n"
            writeStr += "\tpublic List<AssetItem_X" + xmlName + "> Itemlist = new List<AssetItem_X" + xmlName + ">();\n}\n\n"
            writeStr += "[Serializable]\npublic class AssetItem_X" + xmlName + '\n{\n\t[XObject("_id")]\n\tpublic string _id;\n\tpublic int id;\n\n'

            # Init Val
            for k, v in typeDict.items():
                if k == '_id':
                    continue
                if v == "int":
                    writeStr += '\t[XObject("' + k + '")]\n\tpublic int ' + k + ';\n\n'
                elif v == "float":
                    writeStr += '\t[XObject("' + k + '")]\n\tpublic float ' + k + ';\n\n'
                elif v == "string":
                    writeStr += '\t[XObject("' + k + '")]\n\tpublic string ' + k + ';\n\n'
                else:
                    writeStr += '\t[XObject("' + k + '")]\n\tpublic string ' + k + ';\n'
                    if v == "numList":
                        writeStr += "\tpublic List<int> " + k + "List = null;\n\n"
                    elif v == "strList":
                        writeStr += "\tpublic List<string> " + k + "List = null;\n\n"
                    elif v == "numDict":
                        writeStr += "\tpublic List<string> " + k + "Dict_Key = null;\n\tpublic List<int> " + k + "Dict_Value = null;\n\n"
                    elif v == "strDict":
                        writeStr += "\tpublic List<string> " + k + "Dict_Key = null;\n\tpublic List<string> " + k + "Dict_Value = null;\n\n"

            # Serializable Dict && Deserialize Dict
            for k, v in typeDict.items():
                dictType = ""
                if v == "numDict":
                    dictType = "int"
                elif v == "strDict":
                    dictType = "string"

                if dictType != "":
                    # Serializable
                    writeStr += "\tprivate void Serializable_" + k + "Dict(Dictionary<string, " + dictType + "> vDict)\n\t{\n\t\tif (vDict == null) return;\n"
                    writeStr += "\t\tif (" + k + "Dict_Key == null) " + k + "Dict_Key = new List<string>(vDict.Keys);\n"
                    writeStr += "\t\tif (" + k + "Dict_Value == null) " + k + "Dict_Value = new List<" + dictType + ">(vDict.Values);\n\t}\n\n"
                    # Deserialize
                    writeStr += "\tpublic Dictionary<string, " + dictType + "> Deserialize_" + k + "Dict()\n\t{\n"
                    writeStr += "\t\tif (" + k + "Dict_Key == null) return null;\n\t\tif (" + k + "Dict_Key.Count <= 0) return new Dictionary<string, " + dictType + ">();\n"
                    writeStr += "\t\tDictionary<string, " + dictType + "> vReData = new Dictionary<string, " + dictType + ">();\n"
                    writeStr += "\t\tfor (int iCount = 0; iCount < " + k + "Dict_Key.Count; iCount++)\n\t\t{\n"
                    writeStr += "\t\t\tvReData.Add(" + k + "Dict_Key[iCount], " + k + "Dict_Value[iCount]);\n\t\t}\n\t\treturn vReData;\n\t}\n\n"

            # Run Parse
            writeStr += "\tpublic void RunParse()\n\t{\n\t\tid = int.Parse(_id);\n\n"
            for k, v in typeDict.items():
                dictType = ""
                listType = ""
                if v == "numDict":
                    dictType = "int"
                elif v == "strDict":
                    dictType = "string"
                elif v == "numList":
                    listType = "int"
                elif v == "strList":
                    listType = "string"

                if dictType != "":
                    writeStr += "\t\tif (!string.IsNullOrEmpty(" + k + "))\n\t\t{\n\t\t\t"
                    writeStr += "Serializable_" + k + "Dict" + "(JReadTool.Instance.ParseJsonToObject<Dictionary<string, " + dictType + ">>(" + k + "));\n"
                    writeStr += "\t\t\t" + k + " = string.Empty;\n\t\t}\n\n"
                elif listType != "":
                    writeStr += "\t\tif (!string.IsNullOrEmpty(" + k + "))\n\t\t{\n\t\t\t"
                    writeStr += k + "List = JReadTool.Instance.ParseJsonToObject<List<" + listType + ">>(" + k + ");\n"
                    writeStr += "\t\t\t" + k + " = string.Empty;\n\t\t}\n\n"
            writeStr += "\t}\n\n}"

            file.write(writeStr)
            file.close()

            #写入XmlDataManager
            xmlDataManagerPath = assetsPath + '/Scripts/Manager/XmlDataManager.cs'
            file = open(xmlDataManagerPath, encoding='utf-8')
            fileArr = file.readlines()
            lineIndex = 0
            flag1 = 200
            flag2 = -1
            flag3 = -1
            writeStr = ""
            for line in fileArr:
                lineIndex += 1
                writeStr += line
                #插入一行
                if lineIndex == flag1:
                    writeStr += "\tprivate List<X" + xmlName + ">m" + xmlName + "List = null;\n"
                #插入第二行
                if "private void InitPath()" in line:
                    if flag2 == -1:
                        flag2 = lineIndex + 50
                if lineIndex == flag2:
                    writeStr += "\t\tpathDic.Add(typeof(X" + xmlName + '), @"XML/' + xmlName + '.xml");\n'
                #开始写方法
                if lineIndex > 15000 and "endregion" in line:
                    if flag3 == -1:
                        flag3 = lineIndex + 1
                if lineIndex == flag3:
                    #Init方法
                    writeStr += "#region " + xmlName + "\n\n\tpublic void Init" + xmlName + "()\n\t{\n\t\t"
                    writeStr += "if (m" + xmlName + "List == null)\n\t\t{\n\t\t\tDictionary<string, X" + xmlName
                    writeStr += "> vDict = new Dictionary<string, X" + xmlName + ">();\n\t\t\tInitDataFromXml(ref m"
                    writeStr += xmlName + "List, ref vDict);\n\t\t\tvDict.Clear();\n\t\t}\n\t}\n\n"
                    #GetId方法
                    writeStr += "\tpublic X" + xmlName + " Get" + xmlName + "(int vId)\n\t{\n#if !UsingAssetXml\n\t\t"
                    writeStr += "Init" + xmlName + "();\n\t\tif (m" + xmlName + "List == null) return null;\n\t\t"
                    writeStr += "if (m" + xmlName + "List.Count <= 0) return null;\n\t\t"
                    writeStr += "int len = m" + xmlName + "List.Count;\n\t\tfor (int i = 0; i < len; i++)\n\t\t{\n\t\t\t"
                    writeStr += "if (vId == m" + xmlName + "List[i].id)\n\t\t\t{\n\t\t\t\treturn m" + xmlName + "List[i];\n"
                    writeStr += "\t\t\t}\n\t\t}\n\t\treturn null;\n#else\n\t\t"
                    writeStr += "var vData = ConfigDataLoader.instance.Get" + xmlName + "(vId);\n\t\t"
                    writeStr += "if (vData == null) return null;\n\t\tX" + xmlName + " reData = new X" + xmlName + "();\n\t\t"
                    writeStr += "reData.ParseAssetXml(vData);\n\t\treturn reData;\n#endif\n\t}\n\n"
                    #GetAll方法
                    writeStr += "\tpublic List<X" + xmlName + "> Get" + xmlName + "All()\n\t{\n#if !UsingAssetXml\n\t\t"
                    writeStr += "Init" + xmlName + "();\n\t\tif (m" + xmlName + "List == null) return null;\n\t\t"
                    writeStr += "if (m" + xmlName + "List.Count <= 0) return m" + xmlName + "List;\n\t\t"
                    writeStr += "return m" + xmlName + "List;\n#else\n\t\tvar vData = ConfigDataLoader.instance.Get"
                    writeStr += xmlName + "All();\n\t\tif (vData == null) return null;\n\t\tList<X" + xmlName;
                    writeStr += "> reDataList = new List<X" + xmlName + ">();\n\t\tfor (int i = 0; i < vData.Count; i++)"
                    writeStr += "\n\t\t{\n\t\t\tX" + xmlName + " reData = new X" + xmlName + "();\n\t\t\t"
                    writeStr += "reData.ParseAssetXml(vData[i]);\n\t\t\treDataList.Add(reData);\n\t\t}\n\t\t"
                    writeStr += "return reDataList;\n#endif\n\t}\n\n#endregion\n\n"
                #print(writeStr)
            file = open(xmlDataManagerPath, "w+")
            file.write(writeStr)
            file.close()

            # 写入ConfigDataLoader
            configDataLoaderPath = assetsPath + '/Scripts/DataLoader/Loader/ConfigDataLoader.cs'
            file = open(configDataLoaderPath, encoding='utf-8')
            fileArr = file.readlines()
            lineIndex = 0
            flag1 = 101
            flag2 = -1
            flag3 = -1
            flag4 = -1
            flag5 = -1
            writeStr = ""
            for line in fileArr:
                lineIndex += 1
                writeStr += line
                # 插入一行
                if lineIndex == flag1:
                    writeStr += "\tprivate const string mXmlName_" + xmlName + ' = "' + xmlName+ '";\n'
                #Init
                if "public IEnumerator YieldInit()" in line:
                    if flag2 == -1:
                        flag2 = lineIndex + 100
                if lineIndex == flag2:
                    writeStr += "\t\tInitConfigData(mXmlName_" + xmlName + ");\n"
                #Parse
                if "public IEnumerator YieldParseConfigData()" in line:
                    if flag3 == -1:
                        flag3 = lineIndex + 100
                if lineIndex == flag3:
                    writeStr += "\t\tParseConfigData(mXmlName_" + xmlName + ");\n"
                #Release
                if "private IEnumerator ReleaseAll()" in line:
                    if flag4 == -1:
                        flag4 = lineIndex + 100
                if lineIndex == flag4:
                    writeStr += "\t\tReleaseConfigData(mXmlName_" + xmlName + ");\n"
                #开始写方法
                if lineIndex > 5000 and "endregion" in line:
                    if flag5 == -1:
                        flag5 = lineIndex + 1
                if lineIndex == flag5:
                    #GetId方法
                    writeStr += "#region " + xmlName + "\n\n\tpublic AssetItem_X" + xmlName + " Get" + xmlName + "(int vId)\n\t{\n\t\t"
                    writeStr += "Object vDataObj = DataLoaderCtrl.Instance.GetAssetData(mXmlName_" + xmlName + ");\n\t\t"
                    writeStr += "if (vDataObj == null) return null;\n\t\tvar vAssetData = (AssetRoot_X" + xmlName + ")vDataObj;\n\t\t"
                    writeStr += "if (vAssetData == null) return null;\n\t\tif (vAssetData.Itemlist == null) return null;\n\t\t"
                    writeStr += "if (vAssetData.Itemlist.Count <= 0) return new AssetItem_X" + xmlName + "();\n\t\t"
                    writeStr += "for (int i = 0; i < vAssetData.Itemlist.Count; i++)\n\t\t{\n\t\t\t"
                    writeStr += "if (vAssetData.Itemlist[i].id == vId)\n\t\t\t\treturn vAssetData.Itemlist[i];\n\t\t"
                    writeStr += "}\n\t\treturn null;\n\t}\n\n"
                    #GetAll方法
                    writeStr += "\tpublic List<AssetItem_X" + xmlName + "> Get" + xmlName + "All()\n\t{\n\t\t"
                    writeStr += "Object vDataObj = DataLoaderCtrl.Instance.GetAssetData(mXmlName_" + xmlName + ");\n\t\t"
                    writeStr += "if (vDataObj == null) return null;\n\t\tvar vAssetData = (AssetRoot_X" + xmlName + ")vDataObj;\n\t\t"
                    writeStr += "if (vAssetData == null) return null;\n\t\tif (vAssetData.Itemlist == null) return null;\n\t\t"
                    writeStr += "return vAssetData.Itemlist;\n\t}\n\n#endregion\n\n"
                # print(writeStr)
            file = open(configDataLoaderPath, "w+")
            file.write(writeStr)
            file.close()

            msgWindow = wx.MessageDialog(None, "代码生成完毕!", "提示", wx.YES_DEFAULT | wx.ICON_QUESTION)
            if msgWindow.ShowModal() == wx.ID_YES:  # 如果点击了提示框的确定按钮
                msgWindow.Destroy()  # 则关闭提示框

        checkButton.Bind(wx.EVT_BUTTON, onClickCheckButton)
        frame.Show()
        return True

app = App()
app.MainLoop()

需要配合一个配置文件使用

AssetsPath.txt

AssetsPath,E:\Work\Trunk\Assets
# 注意:XmlDataManager和ConfigDataLoader编码格式需要为utf-8,不然会解析错误

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值