1. luaxml的官网 对应的有lua5.1和lua5.2的版本
2. 核心代码有2个, 一个LuaXML_lib.C文件, 一个LuaXML.lua文件
-
/**
-
LuaXML License
-
-
LuaXml is licensed under the terms of the MIT license reproduced below,
-
the same as Lua itself. This means that LuaXml is free software and can be
-
used for both academic and commercial purposes at absolutely no cost.
-
-
Copyright (C) 2007-2010 Gerald Franz, www.viremo.de
-
-
Permission is hereby granted, free of charge, to any person obtaining a copy
-
of this software and associated documentation files (the "Software"), to deal
-
in the Software without restriction, including without limitation the rights
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-
copies of the Software, and to permit persons to whom the Software is
-
furnished to do so, subject to the following conditions:
-
-
http://viremo.eludi.net/LuaXML/
-
-
*/
-
-
#if defined __WIN32__ || defined WIN32
-
# include <windows.h>
-
# define _EXPORT __declspec(dllexport)
-
#else
-
# define _EXPORT
-
#endif
-
-
#include <lua.h>
-
#include <lauxlib.h>
-
#include <lualib.h>
-
-
#include <stdio.h>
-
#include <string.h>
-
#include <ctype.h>
-
#include <stdlib.h>
-
-
static const char ESC=27;
-
static const char OPN=28;
-
static const char CLS=29;
-
-
//--- auxliary functions -------------------------------------------
-
-
static const char* char2code(unsigned char ch, char buf[8]) {
-
unsigned char i=0;
-
buf[i++]='&';
-
buf[i++]='#';
-
if(ch>99) buf[i++]=ch/100+48;
-
if(ch>9) buf[i++]=(ch%100)/10+48;
-
buf[i++]=ch%10+48;
-
buf[i++]=';';
-
buf[i]=0;
-
return buf;
-
}
-
-
static size_t find(const char* s, const char* pattern, size_t start) {
-
const char* found =strstr(s+start, pattern);
-
return found ? found-s : strlen(s);
-
}
-
-
//--- internal tokenizer -------------------------------------------
-
-
typedef struct Tokenizer_s {
-
const char* s; // stores string to be tokenized
-
size_t s_size; // stores size of string to be tokenized
-
size_t i; // stores current read position
-
int tagMode; // stores current read context
-
const char* m_next; // stores next token, if already determined
-
size_t m_next_size; // size of next token
-
char* m_token; // pointer to current token
-
size_t m_token_size; // size of current token
-
size_t m_token_capacity; // capacity of current token
-
} Tokenizer;
-
-
Tokenizer* Tokenizer_new(const char* str, size_t str_size) {
-
Tokenizer *tok = (Tokenizer*)malloc(sizeof(Tokenizer));
-
memset(tok, 0, sizeof(Tokenizer));
-
tok->s_size = str_size;
-
tok->s = str;
-
return tok;
-
}
-
-
void Tokenizer_delete(Tokenizer* tok) {
-
free(tok->m_token);
-
free(tok);
-
}
-
-
//void Tokenizer_print(Tokenizer* tok) { printf(" @%u %s\n", tok->i, !tok->m_token ? "(null)" : (tok->m_token[0]==ESC)?"(esc)" : (tok->m_token[0]==OPN)?"(open)": (tok->m_token[0]==CLS)?"(close)" : tok->m_token); fflush(stdout); }
-
static const char* Tokenizer_set(Tokenizer* tok, const char* s, size_t size) {
-
if(!size||!s) return 0;
-
free(tok->m_token);
-
tok->m_token = (char*)malloc(size+1);
-
strncpy(tok->m_token,s, size);
-
tok->m_token[size] = 0;
-
tok->m_token_size = tok->m_token_capacity = size;
-
//Tokenizer_print(tok);
-
return tok->m_token;
-
}
-
-
static void Tokenizer_append(Tokenizer* tok, char ch) {
-
if(tok->m_token_size+1>=tok->m_token_capacity) {
-
tok->m_token_capacity = (tok->m_token_capacity==0) ? 16 : tok->m_token_capacity*2;
-
tok->m_token = (char*)realloc(tok->m_token, tok->m_token_capacity);
-
}
-
tok->m_token[tok->m_token_size]=ch;
-
tok->m_token[++tok->m_token_size]=0;
-
}
-
-
const char* Tokenizer_next(Tokenizer* tok) {
-
const char* ESC_str = "\033";
-
const char* OPEN_str = "\034";
-
const char* CLOSE_str = "\035";
-
-
-
if(tok->m_token) {
-
free(tok->m_token);
-
tok->m_token = 0;
-
tok->m_token_size=tok->m_token_capacity = 0;
-
}
-
-
int quotMode=0;
-
int tokenComplete = 0;
-
while(tok->m_next_size || (tok->i < tok->s_size)) {
-
-
if(tok->m_next_size) {
-
Tokenizer_set(tok, tok->m_next, tok->m_next_size);
-
tok->m_next=0;
-
tok->m_next_size=0;
-
return tok->m_token;
-
}
-
-
switch(tok->s[tok->i]) {
-
case '"':
-
case '\'':
-
if(tok->tagMode) {
-
if(!quotMode) quotMode=tok->s[tok->i];
-
else if(quotMode==tok->s[tok->i]) quotMode=0;
-
}
-
Tokenizer_append(tok, tok->s[tok->i]);
-
break;
-
case '<':
-
if(!quotMode&&(tok->i+4s_size)&&(strncmp(tok->s+tok->i,"<!--",4)==0)) // strip comments
-
tok->i=find(tok->s, "-->", tok->i+4)+2;
-
else if(!quotMode&&(tok->i+9s_size)&&(strncmp(tok->s+tok->i,"<![CDATA[",9)==0)) { // interpet CDATA
-
size_t b=tok->i+9;
-
tok->i=find(tok->s, "]]>",b)+3;
-
if(!tok->m_token_size) return Tokenizer_set(tok, tok->s+b, tok->i-b-3);
-
tokenComplete = 1;
-
tok->m_next = tok->s+b;
-
tok->m_next_size = tok->i-b-3;
-
--tok->i;
-
}
-
else if(!quotMode&&(tok->i+1s_size)&&((tok->s[tok->i+1]=='?')||(tok->s[tok->i+1]=='!'))) // strip meta information
-
tok->i=find(tok->s, ">", tok->i+2);
-
else if(!quotMode&&!tok->tagMode) {
-
if((tok->i+1s_size)&&(tok->s[tok->i+1]=='/')) {
-
tok->m_next=ESC_str;
-
tok->m_next_size = 1;
-
tok->i=find(tok->s, ">", tok->i+2);
-
}
-
else {
-
tok->m_next = OPEN_str;
-
tok->m_next_size = 1;
-
tok->tagMode=1;
-
}
-
tokenComplete = 1;
-
}
-
else Tokenizer_append(tok, tok->s[tok->i]);
-
break;
-
case '/':
-
if(tok->tagMode&&!quotMode) {
-
tokenComplete = 1;
-
if((tok->i+1 < tok->s_size) && (tok->s[tok->i+1]=='>')) {
-
tok->tagMode=0;
-
tok->m_next=ESC_str;
-
tok->m_next_size = 1;
-
++tok->i;
-
}
-
else Tokenizer_append(tok, tok->s[tok->i]);
-
}
-
else Tokenizer_append(tok, tok->s[tok->i]);
-
break;
-
case '>':
-
if(!quotMode&&tok->tagMode) {
-
tok->tagMode=0;
-
tokenComplete = 1;
-
tok->m_next = CLOSE_str;
-
tok->m_next_size = 1;
-
}
-
else Tokenizer_append(tok, tok->s[tok->i]);
-
break;
-
case ' ':
-
case '\r':
-
case '\n':
-
case '\t':
-
if(tok->tagMode&&!quotMode) {
-
if(tok->m_token_size) tokenComplete=1;
-
}
-
else if(tok->m_token_size) Tokenizer_append(tok, tok->s[tok->i]);
-
break;
-
default: Tokenizer_append(tok, tok->s[tok->i]);
-
}
-
++tok->i;
-
if((tok->i>=tok->s_size)||(tokenComplete&&tok->m_token_size)) {
-
tokenComplete=0;
-
while(tok->m_token_size&&isspace(tok->m_token[tok->m_token_size-1])) // trim whitespace
-
tok->m_token[--tok->m_token_size]=0;
-
if(tok->m_token_size) break;
-
}
-
}
-
//Tokenizer_print(tok);
-
return tok->m_token;
-
}
-
-
//--- local variables ----------------------------------------------
-
-
/// stores number of special character codes
-
static size_t sv_code_size=0;
-
/// stores currently allocated capacity for special character codes
-
static size_t sv_code_capacity=16;
-
/// stores code table for special characters
-
static char** sv_code=0;
-
-
//--- public methods -----------------------------------------------
-
-
static void Xml_pushDecode(lua_State* L, const char* s, size_t s_size) {
-
size_t start=0, pos;
-
if(!s_size) s_size=strlen(s);
-
luaL_Buffer b;
-
luaL_buffinit(L, &b);
-
const char* found = strstr(s, "&#");
-
if(!found) pos = s_size;
-
else pos = found-s;
-
while(found&&(pos+5
-
if(pos>start) luaL_addlstring(&b,s+start, pos-start);
-
luaL_addchar(&b, 100*(s[pos+2]-48)+10*(s[pos+3]-48)+(s[pos+4]-48));
-
start=pos+6;
-
found = strstr(found+6, "&#");
-
if(!found) pos = s_size;
-
else pos = found-s;
-
}
-
if(pos>start) luaL_addlstring(&b,s+start, pos-start);
-
luaL_pushresult(&b);
-
size_t i;
-
for(i=sv_code_size-1; i
-
luaL_gsub(L, lua_tostring(L,-1), sv_code[i], sv_code[i-1]);
-
lua_remove(L,-2);
-
}
-
}
-
-
int Xml_eval(lua_State *L) {
-
char* str = 0;
-
size_t str_size=0;
-
if(lua_isuserdata(L,1)) str = (char*)lua_touserdata(L,1);
-
else {
-
const char * sTmp = luaL_checklstring(L,1,&str_size);
-
str = (char*)malloc(str_size+1);
-
memcpy(str, sTmp, str_size);
-
str[str_size]=0;
-
}
-
Tokenizer* tok = Tokenizer_new(str, str_size ? str_size : strlen(str));
-
lua_settop(L,0);
-
const char* token=0;
-
int firstStatement = 1;
-
while((token=Tokenizer_next(tok))!=0) if(token[0]==OPN) { // new tag found
-
if(lua_gettop(L)) {
-
int newIndex=lua_objlen(L,-1)+1;
-
lua_pushnumber(L,newIndex);
-
lua_newtable(L);
-
lua_settable(L, -3);
-
lua_pushnumber(L,newIndex);
-
lua_gettable(L,-2);
-
}
-
else {
-
if (firstStatement) {
-
lua_newtable(L);
-
firstStatement = 0;
-
}
-
else return lua_gettop(L);
-
}
-
// set metatable:
-
lua_newtable(L);
-
lua_pushliteral(L, "__index");
-
lua_getglobal(L, "xml");
-
lua_settable(L, -3);
-
-
lua_pushliteral(L, "__tostring"); // set __tostring metamethod
-
lua_getglobal(L, "xml");
-
lua_pushliteral(L,"str");
-
lua_gettable(L, -2);
-
lua_remove(L, -2);
-
lua_settable(L, -3);
-
lua_setmetatable(L, -2);
-
-
// parse tag and content:
-
lua_pushnumber(L,0); // use index 0 for storing the tag
-
lua_pushstring(L, Tokenizer_next(tok));
-
lua_settable(L, -3);
-
-
while(((token = Tokenizer_next(tok))!=0)&&(token[0]!=CLS)&&(token[0]!=ESC)) { // parse tag header
-
size_t sepPos=find(token, "=", 0);
-
if(token[sepPos]) { // regular attribute
-
const char* aVal =token+sepPos+2;
-
lua_pushlstring(L, token, sepPos);
-
size_t lenVal = strlen(aVal)-1;
-
if(!lenVal) Xml_pushDecode(L, "", 0);
-
else Xml_pushDecode(L, aVal, lenVal);
-
lua_settable(L, -3);
-
}
-
}
-
if(!token||(token[0]==ESC)) {
-
if(lua_gettop(L)>1) lua_settop(L,-2); // this tag has no content, only attributes
-
else break;
-
}
-
}
-
else if(token[0]==ESC) { // previous tag is over
-
if(lua_gettop(L)>1) lua_settop(L,-2); // pop current table
-
else break;
-
}
-
else { // read elements
-
lua_pushnumber(L,lua_objlen(L,-1)+1);
-
Xml_pushDecode(L, token, 0);
-
lua_settable(L, -3);
-
}
-
Tokenizer_delete(tok);
-
free(str);
-
return lua_gettop(L);
-
}
-
-
int Xml_load (lua_State *L) {
-
const char * filename = luaL_checkstring(L,1);
-
FILE * file=fopen(filename,"r");
-
if(!file) return luaL_error(L,"LuaXml ERROR: \"%s\" file error or file not found!",filename);
-
-
fseek (file , 0 , SEEK_END);
-
size_t sz = ftell (file);
-
rewind (file);
-
char* buffer = (char*)malloc(sz+1);
-
sz = fread (buffer,1,sz,file);
-
fclose(file);
-
buffer[sz]=0;
-
lua_pushlightuserdata(L,buffer);
-
lua_replace(L,1);
-
return Xml_eval(L);
-
};
-
-
int Xml_registerCode(lua_State *L) {
-
const char * decoded = luaL_checkstring(L,1);
-
const char * encoded = luaL_checkstring(L,2);
-
-
size_t i;
-
for(i=0; i
-
if(strcmp(sv_code[i],decoded)==0)
-
return luaL_error(L,"LuaXml ERROR: code already exists.");
-
if(sv_code_size+2>sv_code_capacity) {
-
sv_code_capacity*=2;
-
sv_code = (char**)realloc(sv_code, sv_code_capacity*sizeof(char*));
-
}
-
sv_code[sv_code_size]=(char*)malloc(strlen(decoded)+1);
-
strcpy(sv_code[sv_code_size++], decoded);
-
sv_code[sv_code_size]=(char*)malloc(strlen(encoded)+1);
-
strcpy(sv_code[sv_code_size++],encoded);
-
return 0;
-
}
-
-
int Xml_encode(lua_State *L) {
-
if(lua_gettop(L)!=1) return 0;
-
luaL_checkstring(L,-1);
-
size_t i;
-
for(i=0; i
-
luaL_gsub(L, lua_tostring(L,-1), sv_code[i], sv_code[i+1]);
-
lua_remove(L,-2);
-
}
-
char buf[8];
-
const char* s=lua_tostring(L,1);
-
size_t start, pos;
-
luaL_Buffer b;
-
luaL_buffinit(L, &b);
-
for(start=pos=0; s[pos]!=0; ++pos) if(s[pos]<0) {
-
if(pos>start) luaL_addlstring(&b,s+start, pos-start);
-
luaL_addstring(&b,char2code((unsigned char)(s[pos]),buf));
-
start=pos+1;
-
}
-
if(pos>start) luaL_addlstring(&b,s+start, pos-start);
-
luaL_pushresult(&b);
-
lua_remove(L,-2);
-
return 1;
-
}
-
-
int _EXPORT luaopen_LuaXML_lib (lua_State* L) {
-
static const struct luaL_Reg funcs[] = {
-
{"load", Xml_load},
-
{"eval", Xml_eval},
-
{"encode", Xml_encode},
-
{"registerCode", Xml_registerCode},
-
{NULL, NULL}
-
};
-
luaL_register(L, "xml", funcs);
-
// register default codes:
-
if(!sv_code) {
-
sv_code=(char**)malloc(sv_code_capacity*sizeof(char*));
-
sv_code[sv_code_size++]="&";
-
sv_code[sv_code_size++]="&";
-
sv_code[sv_code_size++]="<";
-
sv_code[sv_code_size++]="<";
-
sv_code[sv_code_size++]=">";
-
sv_code[sv_code_size++]=">";
-
sv_code[sv_code_size++]="\"";
-
sv_code[sv_code_size++]=""";
-
sv_code[sv_code_size++]="'";
-
sv_code[sv_code_size++]="'";
-
}
-
return 1;
-
}
-
--[[ LuaXML.lua的核心代码
-
http://viremo.eludi.net/LuaXML/
-
version 1.8.0 (Lua 5.2), LuaXML_130610.zip
-
version 1.7.4 (Lua 5.1), LuaXML_101012.zip
-
-
xml.new(arg): 创建一个新的XML对象
-
xml.append(var, tag): 添加一个子节点
-
xml.load(filename): 加载XML文件
-
xml.save(var,filename): 保存XML文件
-
xml.eval(xmlstring): 解析XML字符串
-
xml.tag(var, tag): 设置或返回一个XML对象
-
xml.str(var, indent, tag): 以字符串形式返回XML
-
xml.find(var, tag, attributeKey, attributeValue): 查找子节点
-
xml.registerCode(decoded, encoded): 设置文件编码类型
-
-
]]--
-
-
require("LuaXML_lib")
-
-
local base = _G
-
local xml = xml
-
module("xml")
-
-
-- symbolic name for tag index, this allows accessing the tag by var[xml.TAG]
-
TAG = 0
-
-
-- sets or returns tag of a LuaXML object
-
function tag(var,tag)
-
if base.type(var)~="table" then return end
-
if base.type(tag)=="nil" then
-
return var[TAG]
-
end
-
var[TAG] = tag
-
end
-
-
-- creates a new LuaXML object either by setting the metatable of an existing Lua table or by setting its tag
-
function new(arg)
-
if base.type(arg)=="table" then
-
base.setmetatable(arg,{__index=xml, __tostring=xml.str})
-
return arg
-
end
-
local var={}
-
base.setmetatable(var,{__index=xml, __tostring=xml.str})
-
if base.type(arg)=="string" then var[TAG]=arg end
-
return var
-
end
-
-
-- appends a new subordinate LuaXML object to an existing one, optionally sets tag
-
function append(var,tag)
-
if base.type(var)~="table" then return end
-
local newVar = new(tag)
-
var[#var+1] = newVar
-
return newVar
-
end
-
-
-- converts any Lua var into an XML string
-
function str(var,indent,tagValue)
-
if base.type(var)=="nil" then return end
-
local indent = indent or 0
-
local indentStr=""
-
for i = 1,indent do indentStr=indentStr.." " end
-
local tableStr=""
-
-
if base.type(var)=="table" then
-
local tag = var[0] or tagValue or base.type(var)
-
local s = indentStr.."<"..tag
-
for k,v in base.pairs(var) do -- attributes
-
if base.type(k)=="string" then
-
if base.type(v)=="table" and k~="_M" then -- otherwise recursiveness imminent
-
tableStr = tableStr..str(v,indent+1,k)
-
else
-
s = s.." "..k.."=\""..encode(base.tostring(v)).."\""
-
end
-
end
-
end
-
if #var==0 and #tableStr==0 then
-
s = s.." />\n"
-
elseif #var==1 and base.type(var[1])~="table" and #tableStr==0 then -- single element
-
s = s..">"..encode(base.tostring(var[1]))..""..tag..">\n"
-
else
-
s = s..">\n"
-
for k,v in base.ipairs(var) do -- elements
-
if base.type(v)=="string" then
-
s = s..indentStr.." "..encode(v).." \n"
-
else
-
s = s..str(v,indent+1)
-
end
-
end
-
s=s..tableStr..indentStr..""..tag..">\n"
-
end
-
return s
-
else
-
local tag = base.type(var)
-
return indentStr.."<"..tag.."> "..encode(base.tostring(var)).." "..tag..">\n"
-
end
-
end
-
-
-
-- saves a Lua var as xml file
-
function save(var,filename)
-
if not var then return end
-
if not filename or #filename==0 then return end
-
local file = base.io.open(filename,"w")
-
file:write("\n\n\n")
-
file:write(str(var))
-
base.io.close(file)
-
end
-
-
-
-- recursively parses a Lua table for a substatement fitting to the provided tag and attribute
-
function find(var, tag, attributeKey,attributeValue)
-
-- check input:
-
if base.type(var)~="table" then return end
-
if base.type(tag)=="string" and #tag==0 then tag=nil end
-
if base.type(attributeKey)~="string" or #attributeKey==0 then attributeKey=nil end
-
if base.type(attributeValue)=="string" and #attributeValue==0 then attributeValue=nil end
-
-- compare this table:
-
if tag~=nil then
-
if var[0]==tag and ( attributeValue == nil or var[attributeKey]==attributeValue ) then
-
base.setmetatable(var,{__index=xml, __tostring=xml.str})
-
return var
-
end
-
else
-
if attributeValue == nil or var[attributeKey]==attributeValue then
-
base.setmetatable(var,{__index=xml, __tostring=xml.str})
-
return var
-
end
-
end
-
-- recursively parse subtags:
-
for k,v in base.ipairs(var) do
-
if base.type(v)=="table" then
-
local ret = find(v, tag, attributeKey,attributeValue)
-
if ret ~= nil then return ret end
-
end
-
end
-
end
重新写个Makefile, 生成新环境下的so文件
-
OPENWRT = 1
-
-
ifeq ($(OPENWRT), 1)
-
#CC = ~/OpenWrt-SDK-ar71xx-for-linux-i486-gcc-4.6-linaro_uClibc-0.9.33.2/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-gcc
-
CC = ~/OpenWrt-Toolchain-ar71xx-for-mips_r2-gcc-4.6-linaro_uClibc-0.9.33.2/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-gcc
-
CFLAGS += -I ~/openwrt-lib/include -L ~/openwrt-lib/lib
-
-
else
-
CC = gcc
-
endif
-
-
CFLAGS += -Wall -O2
-
#CFLAGS += -g
-
CFLAGS1 += -fPIC -shared #仅so 文件需要
-
-
#可执行文件名和相关的源码文件. lua的so和bin无法同时生成.
-
SHAREOBJ = LuaXML_lib.so
-
SRCS += LuaXML_lib.c
-
-
#以下无需改动
-
OBJS = $(SRCS:.c=.o)
-
-
all: SO_FILE
-
-
SO_FILE: $(OBJS)
-
$(CC) $(CFLAGS) $(CFLAGS1) $(SRCS) -o $(SHAREOBJ) $(LFLAGS1)
-
-
.PHONY: clean
-
clean:
-
@echo "cleanning project"
-
$(RM) *.a $(OBJS) *~ *.so *.lo $(APP_BINARY) $(SHAREOBJ)
-
@echo "clean completed"
将此新生成的LuaXML_lib.so和LuaXML.lua拷贝到路由器上的 /usr/lib/lua目录下即可.
3. openwrt下的测试
-
require('LuaXml')
-
-
-- 加载XML文件
-
local xfile = xml.load("test1.xml")
-
-- 查找子节点
-
local item = xfile:find("item")
-
-- 节点不为空
-
if item ~= nil then
-
print(item);
-
-- 获得子节点数量
-
print( "num = " .. table.getn(item))
-
-
-- 修改键值
-
print("old id = " .. item.id)
-
item.id = "abc";
-
print("new id = " .. item.id)
-
-
-- 第1个子节点
-
local field = item[1]
-
print(field.name, field)
-
-
-- 第2个子节点
-
field = item[2]
-
print(field.name, field)
-
end
-
-
-- 添加子节点
-
local xNewFile = xml.new("root")
-
-- 设置子节点键值
-
local child = xNewFile:append("child")
-
child.id = 1
-
xNewFile:append("text1")[1] = 'test1'
-
-
xNewFile:append("child").id = 2
-
xNewFile:append("text2")[1] = 'test2'
-
--print( xNewFile)
-
-- 保存文件
-
xNewFile:save "t1.xml"
-
-
-- 构造xml字符串
-
local str_xml = xml.str(xNewFile)
-
--local str_xml = " test1 test2"
-
--local str_xml = " test12 test21 "
-
print("xml string: \n" .. str_xml)
-
-
-- 解析xml字符串
-
local xml_info = xml.eval(str_xml)
-
-
local field_name = "text1"
-
local item = xml_info:find(field_name)
-
if item ~= nil then
-
local value = item[1]
-
print(field_name .. " = " .. value)
-
end
-
-
local field_name = "text2"
-
local item = xml_info:find(field_name)
-
if item ~= nil then
-
local value = item[1]
-
print(field_name .. " = " .. value)
-
end
运行结果如下
-
root@OpenWrt:/xutest/lua# lua test1.lua
-
<item id="1">
-
<field name="aa" />
-
<field name="bb" />
-
</item>
-
-
num = 2
-
old id = 1
-
new id = abc
-
aa <field name="aa" />
-
-
bb <field name="bb" />
-
-
xml string:
-
<root>
-
<child id="1" />
-
<text1>test1</text1>
-
<child id="2" />
-
<text2>test2</text2>
-
</root>
-
-
text1 = test1
-
text2 = test2
-
root@OpenWrt:/xutest/lua
阅读(2883) | 评论(0) | 转发(0) |