Ir para conteúdo

Nova livraria lua para xml


Poccnn

Posts Recomendados

Fala XTibianos!

Vim disponibilizar e ensinar como usar a livraria xml em lua desenvolvida por mim. 


A livraria: 

Spoiler

 

xml = {} 

-- carrega o arquivo e retornar um objeto para os metametodos ou uma string para outros fins. 
function xml:load(dir) 
local open = io.open(dir,'r') 
local read_open = open:read(-1) 
   open:close() 
   return setmetatable({},{__index = xml, __tostring = function() return read_open   end}) 
end 

-- Converte strings formatadas em xml para tabelas com parametros validos em lua. retornar uma tabela. 
function xml:eval(tag,head) 
local tab,index = {},0 
   if(string.match(tag,'<.-/>'))then 
      --<tag name="carrot"  quant="914"/> 
      for head,corpser in string.gmatch(tag,'<(%a+) (.-)/>') do 
         if not(tab[index+1])then 
            tab[index+1] = { 
               head = head, 
               _M = 'tag' 
            } 
         end 
         for k,v in string.gmatch(corpser,'(%a+).-"(.-)"') do 
            tab[index+1][k] = v 
         end 
         index = index+1 
      end 
   elseif(string.match(tag,'<.->'))then 
      if(string.match(tag,'<(%a+)>'))then 
         --<bloco>  </bloco> 
         tab.head    = string.match(tag,'<(%a+)>') 
         tab._M       = 'bloco' 
         for ke,v in pairs(xml:eval(head)) do 
            tab[ke] = v 
         end 
      elseif(string.match(tag,'<(%a+).->'))then 
         --<string id="author"> Corpo com string </string> 
         tab.head    = string.match(tag,'<(%a+).->') 
         tab._M       = 'tagBloco' 
         for ke,v in string.gmatch(string.match(tag,'<%a+ (.-)>'),'(%a+).-"(.-)"') do 
            tab[ke] = v 
         end 
         for ke,v in pairs(xml:eval(head)) do 
            tab[ke] = v 
         end 
      end 
   elseif not(string.find(head,'<.->'))then 
      return head 
   end 
   return tab 
end 

-- converte tabelas e parametros com argumentos pre-determinados para xml em uma string formatada em xml. retornar uma string. 
function xml:str() 
local str = '' 
   if(self._M == 'tag')then 
      --<tag name="carrot"  quant="914"/> 
      str = '\n<'..(self.tag or '')..' ' 
      for k,v in pairs(self) do 
         if not(k == '_M') and not(k == 'head') and not(k == 'tag') and not(type(v) == 'table') and not(tonumber(k)) then 
            str = str..k..' = "'..v..'" ' 
         end 
      end 
      str = str..'/>' 
   elseif(self._M  == 'tagBloco')then 
   local taghead,corpo = '','' 
      --<string id="author"> Corpo com string </string> 
      for k,v in pairs(self) do 
         if not(type(v) == 'table')then 
            if not(k == '_M') and not(k == 'head') and not(tonumber(k)) then 
               taghead = taghead..' '..k..'="'..v..'"' 
            elseif(k == '_string')then 
               corpo = corpo..' '..v 
            end 
         elseif(type(v) == 'table')then 
            corpo = corpo..xml.str(v) 
         end 
      end 
      str = '<'..(self.head or 'tag')..taghead..'>'..corpo..'\n</'..(self.head or 'tag')..'>' 
   elseif(self._M == 'bloco')then 
      --<bloco>  </bloco> 
   local corpo = '' 
      str = '<'..self.head..'>' 
      for k,v in pairs(self) do 
         if(tonumber(k) and type(v) == 'table')then 
            if(type(v.tag) == 'string')then 
               corpo = corpo..'\n<'..v.tag..' ' 
               for a,b in pairs(v) do 
                  if not(a == '_M' or a == 'tag')then 
                     corpo = corpo..a..'="'..b..'"' 
                  end 
               end 
               corpo = corpo..'>' 
            elseif(type(v.head) == 'string')then 
               corpo = corpo..'\n'..xml.str(v) 
            end 
         end 
      end 
      str = str..corpo..'\n</'..self.head..'>' 
   end 
   return str 
end 

-- Busca um bloco xml atraves dos argumentos fornecidos. retornar um objeto para os metametodos ou uma string para outros fins. 
function xml:find(headTag,param,value) -- Testado. Ok. 
local tab = {} 
local tag,head = nil,nil 
   if not(headTag) or type(headTag) ~= 'string' then 
      return false 
   elseif not(string.find(tostring(self),'<?xml version="1.0".-?>'))then 
   --<?xml version="1.0" encoding="UTF-8"?> 
      return false,'Versao do arquivo xml nao aceita ou desconhecida - use versao 1.0' 
   elseif not(param and value)then 
      tag,head = string.match(tostring(self),'(<'..headTag..'>)(.-)</'..headTag..'>') 
      if not(tag)then   tag,head = string.match(tostring(self),'(<'..headTag..'.->)(.-)</'..headTag..'>') end 
   elseif tostring(param) then 
      for tg,hd in string.gmatch(tostring(self),'(<'..headTag..'.->)(.-)</'..headTag..'>') do 
         if(string.find(tg,param..'="'..value..'"'))then 
            tag,head = tg,hd 
         end 
      end 
   end 
   if(tag and head)then 
      tab = xml:eval(tag,head) 
   end 
   return setmetatable(tab,{__index = xml, __tostring = xml.str}) 
end 

-- Cria um novo objeto xml com o nome da taghead inserido. 
function xml:new(arg) 
   return setmetatable({head = arg or 'xmltag', _M = 'bloco'},{__index = xml, __tostring = xml.str}) 
end 

-- Essa função não é equivalente a da libluaxml que modificar o nome da taghead. 
-- Essa função cria uma tag do tipo >> <tagExemplo valor="1" novo="new"/> 
function xml:tag(arg,param) 
-- arg, seria o nome da tag (<tagExemplo .../>) 
-- param, seria uma tabela contendo todos os valores que serão postos na tag ({valor=1,novo="new"}). 
local tab = {tag=arg,_M='tag'} 
   if(type(param) == 'table')then 
      for k,v in pairs(param) do 
         tab[k] = v 
      end 
   end 
   table.insert(self,tab) 
end 

-- Essa função não é equivalente a da libluaxml. 
-- Essa função cria uma tag do tipo >> <tagExemplo pode="ter" valores="aqui" opcional=":)">valores inseridos aqui tambem (obs. com uso de metametodos)</tagExemplo> 
function xml:append(arg,param) 
-- arg, seria o nome da tag (<tagExemplo .../>) 
-- param, seria uma tabela contendo todos os valores que serão postos na tag ({valor=1,novo="new"}). 
local tab = {head=arg,_M='tagBloco'} 
   if(type(param) == 'table')then 
      for k,v in pairs(param) do 
         tab[k] = v 
      end 
   end 
   if(type(param) == 'string')then table.insert(tab,param) end 
   table.insert(self,tab) 
   return setmetatable(tab,{__index = xml, __tostring = xml.str}) 
end 

-- salva os dados em um arquivo xml 
-- Se, já existir o arquivo, ele será substituido. 
function xml:save(dir) 
local dir = type(dir) == 'string' and #dir > 6 and dir or 'newFileByXmlGenerator.xml' 
   if not(string.find(dir,'.xml'))then dir = dir..'.xml' end 
   local file = io.open(dir,"w") 
   file:write("<?xml version=\"1.0\"?>\n<!-- file \"",dir, "\", criado por LuaXML system desenvolvido por Marcryzius -->\n\n") 
   file:write(self:str()) 
   io.close(file) 
end 

 

 

Vou ensinar como usar ela. 

Vou usar como exemplo uma parte do arquivo vocations.xml: 

   

Spoiler

<vocation id="1" name="Sorcerer" description="a Sorcerer" needpremium="0" gaincap="10" gainhp="5" gainmana="30" gainhpticks="1" gainhpamount="0.8" gainmanaticks="1" gainmanaamount="6.7" manamultiplier="1.1" attackspeed="2000" soulmax="100" gainsoulticks="600" fromvoc="1"> 
      <formula meleeDamage="1.0" distDamage="1.0" wandDamage="1.0" magDamage="1.1" magHealingDamage="1.0" defense="1.0" magDefense="1.2" armor="1.0"/> 
      <skill fist="1.5" club="2.0" sword="2.0" axe="2.0" distance="2.0" shielding="1.5" fishing="1.1" experience="1.0"/> 
   </vocation> 
   <vocation id="2" name="Druid" description="a Druid" needpremium="0" gaincap="10" gainhp="5" gainmana="30" gainhpticks="1" gainhpamount="0.8" gainmanaticks="1" gainmanaamount="6.7" manamultiplier="1.1" attackspeed="2000" soulmax="100" gainsoulticks="600" fromvoc="2"> 
      <formula meleeDamage="1.0" distDamage="1.0" wandDamage="1.0" magDamage="1.1" magHealingDamage="1.1" defense="1.0" magDefense="1.1" armor="1.0"/> 

 

Primeiro, carregar o arquivo. 
Ele vai retornar um objeto para ser usado pelos metametodos ou uma string para outros fins como "print". 

Citar

local voc = xml:load('vocations.xml') 

 

Buscar a tag desejada. 
Ele vai retornar uma tabela contendo todos os parametros que foram lidos no arquivo. 
O primeiro argumento da função, é o nome da tag requerida. exemplo: <tagNome ....>, tagNome seria o primeiro argumento da função. 
O segundo elemento é usado para diferenciar um bloco de outro como no caso do arquivo vocations que contem varias vocations, mas apenas uma é a requerida. 
O terceiro elemento é o que diferencia um bloco de outro similar. seguindo o exemplo do arquivo vocations, existe varias vocações, mas apenas uma delas tem o id de numero 2. 

Citar

local find = voc:find('vocation','id',2) 

 

Imprime o que foi lido no arquivo. 

Citar

print(find) 


a saida seria essa, nesse caso. 

Citar

<vocation description="a Druid" gaincap="10" needpremium="0" gainhpticks="1" gainmanaamount="6.7" gainmanaticks="1" soulmax="100" id="2" attackspeed="2000" gainsoulticks="600" name="Druid" fromvoc="2" manamultiplier="1.1" gainhpamount="0.8" gainmana="30" gainhp="5"> 
<magHealingDamage = "1.1" defense = "1.0" magDefense = "1.1" wandDamage = "1.0" armor = "1.0" meleeDamage = "1.0" magDamage = "1.1" distDamage = "1.0" /> 
<fist = "1.5" axe = "1.8" fishing = "1.1" sword = "1.8" club = "1.8" experience = "1.0" shielding = "1.5" distance = "1.8" /> 
</vocation> 

 

Mas, ela tambem é uma tabela, por isso, voce pode pegar os elementos dentro dela dessa forma. 

Citar

find.description > "a Druid" 
find.id > 2 
find.needpremium > 0 
... 

 

As tags existentes dentro do bloco "vocation", tambem é uma tabela com indice numerico; portanto é valido pegar os dados dela dessa forma. 

Citar

find[1].defense > 1 
find[1].magDamage > 1.1 
find[2].fist > 1.5 
find[2].axe > 1.8 
... 

 

Cada tag que exista dentro do bloco, vem como uma tabela com indicie numerico. 

 

Criando objetos para xml:
O argumento inserido , seria o nome do bloco. Ex -> <novo> </novo> 

Citar

local novo = xml:new('novo') 

 

Adiciona tag's dentro do corpo do bloco. 

Citar

novo:tag('print',{dir=1,move="sul"}) 
novo:tag('nova',{dir=2,move="norte",sem="valido"}) 

Pode ser adicionado quantas tags quiser. 

 

Cria uma tagbloco ou bloco dentro do bloco principal. Ex -> <tagBloco inserido="primer" ordem="2" face="not"> </tagBloco> 
Essa função retorna um objeto para ser usado pelos metametodos ou uma string para outros fins como "print". 

Citar

local tagBloco = find:append('tagBloco',{inserido='primer',ordem=2,face='not'}) 

 

Dessa forma que foi declarada sem uma tabela contendo os parametros da tag, ela é criada como um bloco. Ex -> <newBloco> </newBloco> 

Citar

local newBloco = find:append('newBloco') 

 

Adiciona tag's ao corpo do novo bloco/tagbloco criado pela função append. 

Citar

tagBloco:tag('inside',{system='F_ord',mac="TTvalido"}) 
tagBloco:tag('newInside',{system='F_ord',mac="TTvalido",base="TT_down"}) 
newBloco:tag('newInsideBloco',{system='F_ord',mac="TTvalido",base="TT_down"}) 

 

E por fim, salva os dados em um arquivo. 
Nessa função, existe o argumento unico que é o destino do arquivo e seu nome, que nesse caso foi ocultado. 

Citar

find:save() -- Não declarei diretorio e nem o nome do arquivo, logo ele será criado onde estiver o script. 

 

É isso ae pessoal, espero que gostem.
 

@Daniel, deleta esse topico. Por algum motivo, duplicou o topico.

Link para o comentário
Compartilhar em outros sites

×
×
  • Criar Novo...