Skip to content

Commit

Permalink
xml库完善
Browse files Browse the repository at this point in the history
  • Loading branch information
xiyoo0812 committed May 6, 2024
1 parent 120d917 commit 4bb66a3
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 24 deletions.
118 changes: 97 additions & 21 deletions extend/luaxml/src/luaxml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,67 +6,143 @@
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());
}
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) {
lua_pushnil(L);
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;
}
}
Expand Down
11 changes: 8 additions & 3 deletions server/test/xml_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,12 @@ local cxml = [[
</XperiML>
]]

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)

0 comments on commit 4bb66a3

Please sign in to comment.