From 4bb66a3a7aa521ff2f35c891016db3dfb369ac16 Mon Sep 17 00:00:00 2001 From: xiyoo0812 Date: Tue, 7 May 2024 00:26:44 +0800 Subject: [PATCH] =?UTF-8?q?xml=E5=BA=93=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extend/luaxml/src/luaxml.cpp | 118 ++++++++++++++++++++++++++++------- server/test/xml_test.lua | 11 +++- 2 files changed, 105 insertions(+), 24 deletions(-) diff --git a/extend/luaxml/src/luaxml.cpp b/extend/luaxml/src/luaxml.cpp index e30d75f9..75ac602d 100644 --- a/extend/luaxml/src/luaxml.cpp +++ b/extend/luaxml/src/luaxml.cpp @@ -6,20 +6,21 @@ using namespace tinyxml2; namespace luaxml { + void push_elems2lua(lua_State* L, const XMLElement* elem); static void push_elem2lua(lua_State* L, const XMLElement* elem) { - int index = 1; - while (elem) { - lua_createtable(L, 0, 4); - lua_pushstring(L, elem->Name()); - lua_setfield(L, -2, "_tag"); - if (elem->GetText()) { - if (lua_stringtonumber(L, elem->GetText()) == 0) { - lua_pushstring(L, elem->GetText()); - } - lua_setfield(L, -2, "_val"); + lua_createtable(L, 0, 4); + lua_pushstring(L, elem->Name()); + lua_setfield(L, -2, "tag"); + if (elem->GetText()) { + if (lua_stringtonumber(L, elem->GetText()) == 0) { + lua_pushstring(L, elem->GetText()); } - const XMLAttribute* attr = elem->FirstAttribute(); + lua_setfield(L, -2, "text"); + } + const XMLAttribute* attr = elem->FirstAttribute(); + if (attr) { + lua_createtable(L, 0, 4); while (attr) { if (lua_stringtonumber(L, attr->Value()) == 0) { lua_pushstring(L, attr->Value()); @@ -27,29 +28,77 @@ namespace luaxml { lua_setfield(L, -2, attr->Name()); attr = attr->Next(); } - const XMLElement* child = elem->FirstChildElement(); - if (child) { - lua_newtable(L); - push_elem2lua(L, child); - lua_setfield(L, -2, "_elems"); - } + lua_setfield(L, -2, "attrs"); + } + const XMLElement* child = elem->FirstChildElement(); + if (child) { + push_elems2lua(L, child); + lua_setfield(L, -2, "elems"); + } + } + + static void push_elems2lua(lua_State* L, const XMLElement* elem) { + int index = 1; + lua_createtable(L, 0, 4); + while (elem) { + push_elem2lua(L, elem); lua_seti(L, -2, index++); elem = elem->NextSiblingElement(); } } - static int load_xml(lua_State* L, const char* xml) { + static void load_elem4lua(lua_State* L, XMLPrinter* printer) { + luakit::lua_guard g(L); + if (lua_getfield(L, -1, "tag") == LUA_TSTRING) { + printer->OpenElement(lua_tostring(L, -1)); + if (lua_getfield(L, -2, "attrs") == LUA_TTABLE) { + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + const char* key = lua_tostring(L, -2); + switch (lua_type(L, -1)) { + case LUA_TBOOLEAN: printer->PushAttribute(key, lua_toboolean(L, -1)); break; + case LUA_TSTRING: printer->PushAttribute(key, lua_tostring(L, -1)); break; + case LUA_TNUMBER: lua_isinteger(L, -1) ? printer->PushAttribute(key, lua_tointeger(L, -1)) : printer->PushAttribute(key, lua_tonumber(L, -1)); break; + } + lua_pop(L, 1); + } + } + switch (lua_getfield(L, -3, "text")) { + case LUA_TBOOLEAN: printer->PushText(lua_toboolean(L, -1)); break; + case LUA_TSTRING: printer->PushText(lua_tostring(L, -1)); break; + case LUA_TNUMBER: lua_isinteger(L, -1) ? printer->PushText(lua_tointeger(L, -1)) : printer->PushText(lua_tonumber(L, -1)); break; + } + if (lua_getfield(L, -4, "elems") == LUA_TTABLE) { + size_t raw_len = lua_rawlen(L, -1); + for (int i = 1; i <= raw_len; ++i) { + lua_rawgeti(L, -1, i); + load_elem4lua(L, printer); + lua_pop(L, 1); + } + } + printer->CloseElement(); + } + } + + static int decode_xml(lua_State* L, const char* xml) { XMLDocument doc; if (doc.Parse(xml) != XML_SUCCESS) { lua_pushnil(L); lua_pushstring(L, "parse xml doc failed!"); return 2; } - lua_newtable(L); push_elem2lua(L, doc.RootElement()); return 1; } + static int encode_xml(lua_State* L) { + XMLPrinter printer; + printer.PushHeader(false, true); + load_elem4lua(L, &printer); + lua_pushlstring(L, printer.CStr(), printer.CStrSize()); + return 1; + } + static int open_xml(lua_State* L, const char* xmlfile) { XMLDocument doc; if (doc.LoadFile(xmlfile) != XML_SUCCESS) { @@ -57,16 +106,43 @@ namespace luaxml { lua_pushstring(L, "parse xml doc failed!"); return 2; } - lua_newtable(L); push_elem2lua(L, doc.RootElement()); return 1; } + static FILE* fopenxml(const char* filepath, const char* mode) { +#if defined(_MSC_VER) + FILE* fp = 0; + const errno_t err = fopen_s(&fp, filepath, mode); + if (err) return 0; +#else + FILE* fp = fopen(filepath, mode); +#endif + return fp; + } + + static int save_xml(lua_State* L, const char* xmlfile) { + FILE* fp = fopenxml(xmlfile, "w"); + if (fp == nullptr) { + lua_pushboolean(L, false); + lua_pushstring(L, "file dont open, save xml failed!"); + return 2; + } + XMLPrinter printer(fp); + printer.PushHeader(false, true); + load_elem4lua(L, &printer); + lua_pushboolean(L, true); + fclose(fp); + return 1; + } + luakit::lua_table open_luaxml(lua_State* L) { luakit::kit_state kit_state(L); luakit::lua_table lxml = kit_state.new_table("xml"); - lxml.set_function("load", load_xml); + lxml.set_function("decode", decode_xml); + lxml.set_function("encode", encode_xml); lxml.set_function("open", open_xml); + lxml.set_function("save", save_xml); return lxml; } } diff --git a/server/test/xml_test.lua b/server/test/xml_test.lua index 5de461f3..01d3c8df 100644 --- a/server/test/xml_test.lua +++ b/server/test/xml_test.lua @@ -100,7 +100,12 @@ local cxml = [[ ]] -local xlua, err = xml.load(cxml) - -log_dump("luaxml load err: {}, xml:{}", err, xlua) +local xlua, err = xml.decode(cxml) +log_dump("luaxml decode err: {}, xml:{}", err, xlua) +local exml = xml.encode(xlua) +log_dump("luaxml encode xml:{}", exml) +local ok = xml.save("./bb.xml", xlua) +log_dump("luaxml save xml:{}", ok) +local flua, ferr = xml.open("./bb.xml") +log_dump("luaxml open err: {}, xml:{}", ferr, flua)