Question

I'm trying to parse data from XML files like

<level>
  <bg>details1</bg>
  <bg>details2</bg>
</level>

With xml.find(bg) I can only get details 1 out. It's because xml.find Returns the first (sub-)table which matches the search condition or nil.

If I want to read both bg out. How could I achieve it in LuaXML? Or please introduce other Lua XML library works.

Addons My real scenario is like this

<a>
   <b>
    <level>
      <bg>details1</bg>
    </level>
    <level>
      <bg>details2</bg>
    </level>
   </b>
</a>

I know I need to get whole b object out and use xml.tag to read level out. But my attempts fail. Could you help me on this code?


I finally get my solution like this based on Mike Corcoran's suggestion.

require 'luaxml'

local text = [[
<a>
   <bcde>
    <level>
      <bg>details1</bg>
    </level>
    <level>
      <bg>details2</bg>
    </level>
   </bcde>
</a>
]]

local txml = xml.eval(text)
for _, node in pairs(txml:find("bcde")) do
 if node.TAG ~= nil then
        if node[node.TAG] == "level" then
            local bg = node:find("bg")
                if bg ~= nil then
                for i=1, #bg do
                    print( bg[i])
                end
            end
        end
    end
end

There are too many layers and seems slow.. Any suggestion to improve efficiency?

Was it helpful?

Solution 2

Just iterate over all children of the level tag (unless there is other information in there you aren't telling us about that needs to be filtered)

require 'luaxml'

local text = [[
<level>
    <bg>details1</bg>
    <bg>details2</bg>
</level>
]]

local VALUE = 1

local txml = xml.eval(text)
for _, node in pairs(txml:find("level")) do
    if node.TAG ~= nil then
        print(node[VALUE])
    end
end

and if you need to filter out everything except for the <bg> tags, you can just slightly modify the loop to this:

for _, node in pairs(txml:find("level")) do
    if node.TAG ~= nil then
        if node[node.TAG] == "bg" then
            print(node[VALUE])
        end
    end
end

OTHER TIPS

After calling xml.load you get back a table that represents the xml file just loaded. You can get to a specific node by accessing its corresponding numerical index in the table:

require 'luaxml'

local level = xml.load('level.xml')

-- level[1] == <bg>details1</bg>
-- level[2] == <bg>details2</bg>
for i = 1, #level do
  print(level[i])
end

Edit: From your edited question, here's one way to pull the data out of the xml file:

require 'luaxml'

local xmlroot = xml.load('your.xml')
local b = xmlroot:find 'b'

for level = 1, #b do
  print(b[level][1][1])
end

If you have control over the xml format you can modify it somewhat to make the parse more readable:

<a>
   <b>
    <level bg="details1"> </level>
    <level bg="details2"> </level>
   </b>
</a>

With this change bg becomes an attribute of the level node. This reduces one level of indirection. To access bg attribute just use the lua . operator with bg as the key. The parsing loop can then be modified to:

for level = 1, #b do
  print(b[level].bg)
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top