|
tinyxml是C++的XML解析器,能够在Windows或Linux中编译。这个解析库的模型通过解析XML文件,然后在内存中生成DOM模型,从而让我们很方便的遍历这棵XML树。 DOM模型即文档对象模型,是将整个文档分成多个元素(如书、章、节、段等),并利用树型结构表示这些元素之间的顺序关系以及嵌套包含关系。 下面这两个文件就是对tinyxml库中常用的接口在lua的注册封装,使用的是常规的lua注册方法
lua_xml.h
lua_xml.cp 1 #include <new> 2 #include <stdlib.h> 3 #include "luaxml.h" 4 5 extern "C"{ 6 #include <lauxlib.h> 7 #include <lualib.h> 8 }; 9 10 #include "tinyxml.h" 11 #include "log.h" 12 #include "packetcross.h" 13 #include "filepacket.h" 14 15 #define TINYXML_TABLE_NAME "TiXmlDocument_metatable" 16 #define XMLELEMENT_TABLE_NAME "TiXmlElement_metatable" 17 static int lua_tinyxml_new (lua_State *L) 18 { 19 TiXmlDocument *doc = (TiXmlDocument *)lua_newuserdata(L, sizeof(TiXmlDocument)); 20 if (!doc) 21 { 22 lua_pushnil(L); 23 return 1; 24 } 25 new(doc) TiXmlDocument(); 26 luaL_getmetatable(L, TINYXML_TABLE_NAME); 27 lua_setmetatable(L, -2); 28 return 1; 29 } 30 31 static TiXmlDocument *get_tixml (lua_State *L) 32 { 33 TiXmlDocument *doc = (TiXmlDocument *)luaL_checkudata(L, 1, TINYXML_TABLE_NAME); 34 luaL_argcheck(L, doc != NULL, 1, "TiXmlDocument expected"); 35 return doc; 36 } 37 38 static int destroy_tixmldocument (lua_State *L) 39 { 40 TiXmlDocument *doc = get_tixml(L); 41 doc->~TiXmlDocument(); 42 return 0; 43 } 44 45 static int luatixml_loadfile (lua_State *L) 46 { 47 TiXmlDocument *doc = get_tixml(L); 48 const char *filename = luaL_checkstring(L, 2); 49 luaL_argcheck(L, strcmp(filename, "") != 0, 2, "filename can't for empty"); 50 bool inpacket = luaL_opt(L, lua_toboolean, 3, true); 51 if (inpacket) 52 { 53 #ifdef USE_PACKET 54 struct packet *datapk = crosspacket_datapacket(); 55 int size = packet_openfile(datapk, filename); 56 if (size > 0) 57 { 58 int buflen = size + 1; 59 char *buf = (char *)malloc(buflen); 60 packet_readfile(datapk, buf, size); 61 buf[size] = 0; 62 lua_pushboolean(L, doc->LoadFileFromBuffer(buf, buflen)); 63 free(buf); 64 } 65 else 66 { 67 lua_pushboolean(L, false); 68 } 69 return 1; 70 #endif 71 } 72 73 lua_pushboolean(L, doc->LoadFile(filename)); 74 return 1; 75 } 76 77 static int lua_xmlelement_new (lua_State *L, TiXmlElement *el) 78 { 79 if (!el) 80 { 81 lua_pushnil(L); 82 return 1; 83 } 84 TiXmlElement **point = (TiXmlElement **)lua_newuserdata(L, sizeof(TiXmlElement*)); 85 if (!point) 86 { 87 log_error("lua newuserdata failed!"); 88 lua_pushnil(L); 89 return 1; 90 } 91 *point = el; 92 luaL_getmetatable(L, XMLELEMENT_TABLE_NAME); 93 lua_setmetatable(L, -2); 94 return 1; 95 } 96 97 static int luatixml_firstchildelement (lua_State *L) 98 { 99 TiXmlDocument *doc = get_tixml(L); 100 const char *elname = luaL_checkstring(L, 2); 101 TiXmlElement *el = doc->FirstChildElement(elname); 102 lua_xmlelement_new(L, el); 103 return 1; 104 } 105 106 static int luatixml_savefile (lua_State *L) 107 { 108 TiXmlDocument *doc = get_tixml(L); 109 lua_pushboolean(L, doc->SaveFile()); 110 return 1; 111 } 112 113 static TiXmlElement *get_xml_element (lua_State *L) 114 { 115 TiXmlElement **point = (TiXmlElement **)luaL_checkudata(L, 1, XMLELEMENT_TABLE_NAME); 116 luaL_argcheck(L, (*point) != NULL, 1, "TiXmlElement expected"); 117 return *point; 118 } 119 120 static int lua_xmlelement_firstchildelement (lua_State *L) 121 { 122 TiXmlElement *el = get_xml_element(L); 123 const char *cname = luaL_checkstring(L, 2); 124 TiXmlElement *res = el->FirstChildElement(cname); 125 lua_xmlelement_new(L, res); 126 return 1; 127 } 128 129 static int lua_xmlelement_nextsiblingelement (lua_State *L) 130 { 131 TiXmlElement *el = get_xml_element(L); 132 const char *nname = luaL_checkstring(L, 2); 133 TiXmlElement *res = el->NextSiblingElement(nname); 134 lua_xmlelement_new(L, res); 135 return 1; 136 } 137 138 static int lua_xmlelement_querystring (lua_State *L) 139 { 140 TiXmlElement *el = get_xml_element(L); 141 const char *elname = luaL_checkstring(L, 2); 142 const char *vl = el->Attribute(elname); 143 luaL_argcheck(L, vl != NULL, 2, "not find this xml element!"); 144 lua_pushstring(L, vl); 145 return 1; 146 } 147 148 static int lua_xmlelement_queryint (lua_State *L) 149 { 150 TiXmlElement *el = get_xml_element(L); 151 const char *elname = luaL_checkstring(L, 2); 152 int temp = 0; 153 int res = el->QueryIntAttribute(elname, &temp); 154 luaL_argcheck(L, res == TIXML_SUCCESS, 2, "not find this xml element!"); 155 lua_pushinteger(L, temp); 156 return 1; 157 } 158 159 static int lua_xmlelement_querydouble (lua_State *L) 160 { 161 TiXmlElement *el = get_xml_element(L); 162 const char *elname = luaL_checkstring(L, 2); 163 double temp = 0.0f; 164 int res = el->QueryDoubleAttribute(elname, &temp); 165 luaL_argcheck(L, res == TIXML_SUCCESS, 2, "not find this xml element!"); 166 lua_pushnumber(L, temp); 167 return 1; 168 } 169 170 static int lua_xmlelement_setstring (lua_State *L) 171 { 172 TiXmlElement *el = get_xml_element(L); 173 const char *name = luaL_checkstring(L ,2); 174 const char *vl = luaL_checkstring(L, 3); 175 el->SetAttribute(name, vl); 176 return 0; 177 } 178 179 static int lua_xmlelement_setint (lua_State *L) 180 { 181 TiXmlElement *el = get_xml_element(L); 182 const char *name = luaL_checkstring(L, 2); 183 int temp = luaL_checkinteger(L, 3); 184 el->SetAttribute(name, temp); 185 return 0; 186 } 187 188 static int lua_xmlelement_setdouble (lua_State *L) 189 { 190 TiXmlElement *el = get_xml_element(L); 191 const char *name = luaL_checkstring(L, 2); 192 double temp = luaL_checknumber(L, 3); 193 el->SetDoubleAttribute(name, temp); 194 return 0; 195 } 196 197 static const struct luaL_reg element_class_member_functin[] = { 198 {"FirstChildElement", lua_xmlelement_firstchildelement}, 199 {"NextSiblingElement", lua_xmlelement_nextsiblingelement}, 200 {"QueryString", lua_xmlelement_querystring}, 201 {"QueryInt", lua_xmlelement_queryint}, 202 {"QueryDouble", lua_xmlelement_querydouble}, 203 {"SetString", lua_xmlelement_setstring}, 204 {"SetInt", lua_xmlelement_setint}, 205 {"SetDouble", lua_xmlelement_setdouble}, 206 {0, 0} 207 }; 208 209 static const struct luaL_reg class_member_functin[] = { 210 {"LoadFile", luatixml_loadfile}, 211 {"FirstChildElement", luatixml_firstchildelement}, 212 {"SaveFile", luatixml_savefile}, 213 {0, 0} 214 }; 215 216 static const struct luaL_reg class_static_funciton[] = { 217 {"new", lua_tinyxml_new}, 218 {0, 0} 219 }; 220 221 static void lua_tixmlelement_register (lua_State *L) 222 { 223 /*创建元表*/ 224 luaL_newmetatable(L, XMLELEMENT_TABLE_NAME); 225 226 /*查找索引,把它指向metatable自身(因为稍后会在metatable里加入一些成员)*/ 227 lua_pushvalue(L, -1); 228 lua_setfield(L, -2, "__index"); 229 230 /* 231 注册此元表的成员(因为当前栈顶为此元表)---也就是成员函数。切记库名为NULL。 232 他等同于一个个设置方法: 233 lua_pushcfunction(L, function); 234 lua_setfield(L, -2, functionn_name_in_lua); 235 */ 236 luaL_register(L, NULL, element_class_member_functin); 237 238 /*弹1个*/ 239 lua_pop(L, 1); 240 } 241 242 static void lua_tixmldocument_register (lua_State *L) 243 { 244 /*创建元表*/ 245 luaL_newmetatable(L, TINYXML_TABLE_NAME); 246 247 /*查找索引,把它指向metatable自身(因为稍后会在metatable里加入一些成员)*/ 248 lua_pushvalue(L, -1); 249 lua_setfield(L, -2, "__index"); 250 251 /*元表的gc域*/ 252 lua_pushcfunction(L, destroy_tixmldocument); 253 lua_setfield(L, -2, "__gc"); 254 255 /* 256 注册此元表的成员(因为当前栈顶为此元表)---也就是成员函数。切记库名为NULL。 257 他等同于一个个设置方法: 258 lua_pushcfunction(L, function); 259 lua_setfield(L, -2, functionn_name_in_lua); 260 */ 261 luaL_register(L, NULL, class_member_functin); 262 263 /*注册库。切记库名非空,他会创建一个表,若不存在的话,然后把方法列表加入表中。*/ 264 luaL_register(L, "tinyxml", class_static_funciton); 265 266 /*弹2个*/ 267 lua_pop(L, 2); 268 } 269 270 void lua_xml_register (lua_State *L) 271 { 272 lua_tixmlelement_register(L); 273 lua_tixmldocument_register(L); 274 } 275 1 #ifndef _H_LUA_XML_H_ 2 #define _H_LUA_XML_H_ 3 4 #ifdef __cplusplus 5 extern "C"{ 6 #endif 7 8 #include <lua.h> 9 10 #ifdef __cplusplus 11 }; 12 #endif 13 14 void lua_xml_register (lua_State *L); 15 16 #endif 17 示例(lua文件):
function testxml()
xml = tinyxml();
filename = "./data/logiclist.xml";
if not xml:LoadFile(filename) then
print("open ", filename, " failed!");
return;
end
firstelename = "logicinfo";
element = xml:FirstChildElement(firstelename);
if not element then
print("not find element, element:", firstelename);
return;
end
print("servergroupid:", element:QueryString("servergroupid"));
firstelename = "logicserver";
otel = element:FirstChildElement(firstelename);
while otel do
print("ip:", otel:QueryString("ip"), "port:", otel:QueryInt("port"));
otel = otel:NextSiblingElement(firstelename);
end
return true;
end 下面的两个文件是使用lua_tinker对tinyxml库的封装
lua_class.h lua_class.cpp
1 #ifndef luaclass_h 2 #define luaclass_h 3 4 #include "tinyxml.h" 5 6 class _TiXmlAttribute:public TiXmlAttribute 7 { 8 public: 9 _TiXmlAttribute* _TiXmlAttribute::Next(); 10 }; 11 12 class _TiXmlElement:public TiXmlElement 13 { 14 public: 15 int QueryInt( const char* name) const; 16 double QueryDouble( const char* name) const; 17 _TiXmlElement* FirstChildElement( const char * _value ); 18 _TiXmlElement* FirstChild(); 19 _TiXmlElement* NextSiblingElement( const char *_next ) ; 20 _TiXmlAttribute* FirstAttribute(); 21 _TiXmlElement* NextSibling(); 22 }; 23 24 class _TiXmlDocument:public TiXmlDocument 25 { 26 public: 27 bool LoadFile( const char* _filename, TiXmlEncoding encoding ); 28 _TiXmlElement* FirstChildElement( const char * _value ); 29 _TiXmlElement* RootElement(); 30 31 _TiXmlElement* FirstChild(); 32 }; 33 34 35 36 注册代码:
1 #ifndef register_h 2 #define register_h 3 #include "luaclass.h" 4 #include "lua_tinker.h" 5 6 bool regxml(lua_State* L) 7 { 8 //_TiXmlAttribute 9 lua_tinker::class_add<_TiXmlAttribute>(L,"tinyatr"); 10 lua_tinker::class_def<_TiXmlAttribute>(L,"Name",&_TiXmlAttribute::Name); 11 lua_tinker::class_def<_TiXmlAttribute>(L,"Value",&_TiXmlAttribute::Value); 12 lua_tinker::class_def<_TiXmlAttribute>(L,"IntValue",&_TiXmlAttribute::IntValue); 13 _TiXmlAttribute* (_TiXmlAttribute::*ptr0)() = &_TiXmlAttribute::Next; 14 lua_tinker::class_def<_TiXmlAttribute>(L,"Next",&_TiXmlAttribute::Next); 15 16 //_TiXmlElement 17 lua_tinker::class_add<_TiXmlElement>(L,"tinyelm"); 18 lua_tinker::class_con<_TiXmlElement>(L,lua_tinker::constructor<_TiXmlElement,const _TiXmlElement&>); 19 _TiXmlElement* (_TiXmlElement::*ptr1)( const char *) = &_TiXmlElement::FirstChildElement; 20 lua_tinker::class_def<_TiXmlElement>(L,"FirstChildElement",ptr1); 21 _TiXmlElement* (_TiXmlElement::*ptr2)( const char *) = &_TiXmlElement::NextSiblingElement; 22 lua_tinker::class_def<_TiXmlElement>(L,"NextSiblingElement",ptr2); 23 const char* (_TiXmlElement::*ptr3)( const char* ) const = &_TiXmlElement::Attribute; 24 lua_tinker::class_def<_TiXmlElement>(L,"QueryString",ptr3); 25 26 lua_tinker::class_def<_TiXmlElement>(L,"QueryInt",&_TiXmlElement::QueryInt); 27 lua_tinker::class_def<_TiXmlElement>(L,"QueryDouble",&_TiXmlElement::QueryDouble); 28 29 void (_TiXmlElement::*ptr4)( const char*, const char * ) = &_TiXmlElement::SetAttribute; 30 lua_tinker::class_def<_TiXmlElement>(L,"SetString",ptr4); 31 32 //新增 33 lua_tinker::class_def<_TiXmlElement>(L,"Value",&_TiXmlElement::Value); 34 35 36 _TiXmlElement* (_TiXmlElement::*ptr9)() = &_TiXmlElement::FirstChild; 37 lua_tinker::class_def<_TiXmlElement>(L,"FirstChild",ptr9); 38 39 40 _TiXmlElement* (_TiXmlElement::*ptr10)() = &_TiXmlElement::NextSibling; 41 lua_tinker::class_def<_TiXmlElement>(L,"NextSibling",ptr10); 42 43 44 45 46 lua_tinker::class_def<_TiXmlElement>(L,"SetInt",&_TiXmlElement::SetDoubleAttribute); 47 lua_tinker::class_def<_TiXmlElement>(L,"SetDouble",&_TiXmlElement::SetDoubleAttribute); 48 lua_tinker::class_def<_TiXmlElement>(L,"GetText",&_TiXmlElement::GetText); 49 50 _TiXmlAttribute* (_TiXmlElement::*ptr7)() = &_TiXmlElement::FirstAttribute; 51 lua_tinker::class_def<_TiXmlElement>(L,"FirstAttribute",ptr7); 52 53 54 //_TiXmlDocument 55 lua_tinker::class_add<_TiXmlDocument>(L,"tinyxml"); 56 lua_tinker::class_con<_TiXmlDocument>(L,lua_tinker::constructor<_TiXmlDocument>); 57 lua_tinker::class_def<_TiXmlDocument>(L,"LoadFile",&_TiXmlDocument::LoadFile); 58 59 _TiXmlElement* (_TiXmlDocument::*ptr5)( const char * ) = &_TiXmlDocument::FirstChildElement; 60 lua_tinker::class_def<_TiXmlDocument>(L,"FirstChildElement",ptr5); 61 62 bool (_TiXmlDocument::*ptr6)() const = &_TiXmlDocument::SaveFile; 63 lua_tinker::class_def<_TiXmlDocument>(L,"SaveFile",ptr6); 64 65 _TiXmlElement* (_TiXmlDocument::*ptr8)() = &_TiXmlDocument::RootElement; 66 lua_tinker::class_def<_TiXmlDocument>(L,"RootElement",ptr8); 67 68 69 return true; 70 } 71 72 73 74 注意的是lua_tinker直接不支持c++重载,lua的底层是c,在c里面可以用函数指针实现多态,在lua中使用c++的类的成员,要用:,而不是.。 示例:
local function LoadLevelBase(filename)
xml = tinyxml();
if not xml:LoadFile(filename) then
print("open "..filename.." failed!");
end
local rootElement=xml:RootElement();
local element = rootElement:FirstChildElement("element");
local att_Name;
local att_Value;
--遍历xml
while element do
local ChildElement=element:FirstChild();
local ele={};
local attri={};
local event={};
--子节点
while ChildElement do
ele_Name=ChildElement:Value();
if ele_Name=='Event' then
attr = ChildElement:FirstAttribute();
while attr do
att_Name = attr:Name();
att_Value = attr:Value();
attr = attr:Next();
end
else
ele_Value=ChildElement:GetText();
if ele_Name ~= 'Name' then
ele_Value=tonumber(ele_Value);
end
ele[ele_Name]=ele_Value;
--读取元素
-print(ele_Name..'='..ele_Value);
end
ChildElement=ChildElement:NextSibling();
end
end
end
|