#include <iostream> #include "tinyxml2.h" #include <fstream> #include <string> using namespace tinyxml2; using namespace std; std::ofstream file("readProto.lua",std::ios::ate|std::ios::binary); void read_S_ElementChild(XMLElement *surface) { while (surface) { const XMLAttribute *attr = surface->FirstAttribute();//获取第一个属性值 string strType; bool isArray = false; while(attr) { if (strcmp(attr->Name(),"name")==0) { string name = attr->Value(); string dataStr = "data."; string temp1 = "\t" + dataStr + name + " = "; string temp; if(strcmp(strType.c_str(),"String")==0){ temp = "is:readUTF8()"; }else if(strcmp(strType.c_str(),"long")==0){ temp = "is:readLong()"; }else if(strcmp(strType.c_str(),"int")==0){ temp = "is:readInt()"; }else if(strcmp(strType.c_str(),"short")==0){ temp = "is:readShort()"; }else if(strcmp(strType.c_str(),"byte")==0){ temp = "is:readByte()"; }else if(strcmp(strType.c_str(),"boolean")==0){ temp = "is:readBool()"; }else if(strcmp(strType.c_str(),"float")==0){ temp = "is:readJavaFloat()"; }else{ size_t len = strType.size(); string lastStr = strType.substr(len-2,2); if(strcmp(lastStr.c_str(),"[]")==0){ //代表是数组 isArray = true; file << "\tlocal cnt = is:readShort()" << endl; file << "\tlocal temps = {}" << endl; file << "\tfor i=1,cnt do" << endl; string preStr = strType.substr(0,len-2); string preStrTemp; if(strcmp(preStr.c_str(),"String")==0){ preStrTemp = "is:readUTF8()"; }else if(strcmp(preStr.c_str(),"long")==0){ preStrTemp = "is:readLong()"; }else if(strcmp(preStr.c_str(),"int")==0){ preStrTemp = "is:readInt()"; }else if(strcmp(preStr.c_str(),"short")==0){ preStrTemp = "is:readShort()"; }else if(strcmp(preStr.c_str(),"byte")==0){ preStrTemp = "is:readByte()"; }else if(strcmp(preStr.c_str(),"boolean")==0){ preStrTemp = "is:readBool()"; }else if(strcmp(preStr.c_str(),"float")==0){ preStrTemp = "is:readJavaFloat()"; }else { preStrTemp = "read_" + preStr + "(is)"; } file << "\t\ttemps[i] = " << preStrTemp << endl; file << "\tend" << endl; }else{ temp = "read_" + strType + "(is)"; } } if(!isArray){ file << temp1 + temp; }else{ //是数组 file << temp1 + "temps" ; } }else if(strcmp(attr->Name(),"type")==0) { strType = attr->Value(); }else if(strcmp(attr->Name(),"description")==0) { string desc = attr->Value(); string temp = " --" + desc; file << temp << endl; if(isArray) { file << endl; } } attr = attr->Next(); //获取下一个属性值 } surface = surface->NextSiblingElement();//当前对象的下一个节点 } } void read_C_ElementChild(XMLElement *surface) { int i = 0; while (surface) { string strType; const XMLAttribute *attr = surface->FirstAttribute();//获取第一个属性值 while(attr) { if (strcmp(attr->Name(),"name")==0) { string temp; bool isNum = false; string param = "param"; char num[4]=""; sprintf_s(num,"%d",i); if(strcmp(strType.c_str(),"String")==0){ temp = "sendData:writeUTF8("; }else if(strcmp(strType.c_str(),"long")==0){ isNum = true; temp = "sendData:writeLong("; }else if(strcmp(strType.c_str(),"int")==0){ isNum = true; temp = "sendData:writeInt("; }else if(strcmp(strType.c_str(),"short")==0){ isNum = true; temp = "sendData:writeShort("; }else if(strcmp(strType.c_str(),"byte")==0){ isNum = true; temp = "sendData:writeByte("; }else if(strcmp(strType.c_str(),"boolean")==0){ temp = "sendData:writeBool("; }else if(strcmp(strType.c_str(),"float")==0){ isNum = true; temp = "sendData:writeJavaFloat("; }else{ temp = "error ############ "; } if (isNum) { file << "\tlocal " + param + num + " = tonumber(" + "self:getExtraValue(" + num + "))" << endl; }else{ file << "\tlocal " + param + num + " = " + "self:getExtraValue(" + num + ")" << endl; } file << "\t" + temp + param + num + ")" ; }else if(strcmp(attr->Name(),"type")==0){ strType = attr->Value(); }else if(strcmp(attr->Name(),"description")==0){ file << " --" << attr->Value() << endl; } attr = attr->Next(); //获取下一个属性值 } i = i + 1; surface = surface->NextSiblingElement();//当前对象的下一个节点 } } void read_xml(XMLElement *surface) { while (surface) { string id; string name; bool isRead = true; const XMLAttribute *attr = surface->FirstAttribute();//获取第一个属性值 while(attr) { if(strcmp(attr->Name(),"id")==0) { id = attr->Value(); }else if(strcmp(attr->Name(),"name")==0) { name = attr->Value(); string fristStr = name.substr(0,1); string wirteStr = "function read_" + name + "(is)"; if(strcmp(fristStr.c_str(),"C")== 0 ) { isRead = false; wirteStr = "function send_" + name + "(self)"; } file << wirteStr ; }else if(strcmp(attr->Name(),"description")==0) { file << " --" << attr->Value() << endl; if (!isRead) { file << "\tlocal " + name + " = " + id + " --" + attr->Value() << endl; file << "\tlocal sendData = ByteArrayOutputStream()" << endl; file << "\tsendData:writeInt(" + id + ")" << endl; } } attr = attr->Next(); //获取下一个属性值 } XMLElement *surface1 = surface->FirstChildElement(); //查看当前对象是否有子节点 if(surface1) { if(isRead) { file << "\tlocal data = {}" << endl; read_S_ElementChild(surface1);//递归调用 }else { read_C_ElementChild(surface1); } } if (isRead) { file << "\treturn data" << endl; }else { file << "\tsendDataStream(sendData)" << endl; } file << "end" << endl; file << endl; surface = surface->NextSiblingElement();//当前对象的下一个节点 } } int main() { if(!file) { std::cout<<"文件打开失败!"; abort();//等同于exit } tinyxml2::XMLDocument mydocument; //声明xml对象 mydocument.LoadFile("protocol.xml"); //载入xml文件 XMLElement *rootElement = mydocument.RootElement(); //获取跟节点 XMLElement *surface = rootElement->FirstChildElement("message");//获取第一个值为value的子节点 默认为空则返回第一个节点 read_xml(surface); file.close(); cin.get(); }
xml
<message id="0x09001017" name="S_ITEM_ADD_TASK" description="向背包添加一种任务道具"> <field type="int" name="task_max" description="任务道具包裹的当前长度(可能有空格)"/> <field type="S_ITEM_TASKPROPS[]" name="items" description="数据"/> </message>
<message id="0x02000006" name="C_MAP_NODE_ARRIVE" description="角色到达结点"> <field type="int" name="id" description="关卡结点id"/> <field type="boolean" name="isEnd" description="是否到达终点"/> </message>lua
function read_S_ITEM_ADD_TASK(is) --向背包添加一种任务道具 local data = {} data.task_max = is:readInt() --任务道具包裹的当前长度(可能有空格) local cnt = is:readShort() local temps = {} for i=1,cnt do temps[i] = read_S_ITEM_TASKPROPS(is) end data.items = temps --数据 return data end
function send_C_MAP_NODE_ARRIVE(self) --角色到达结点 local C_MAP_NODE_ARRIVE = 0x02000006 --角色到达结点 local sendData = ByteArrayOutputStream() sendData:writeInt(0x02000006) local param0 = tonumber(self:getExtraValue(0)) sendData:writeInt(param0) --关卡结点id local param1 = self:getExtraValue(1) sendData:writeBool(param1) --是否到达终点 sendDataStream(sendData) end