Search code examples
xmlxml-parsinglualuaxml

LuaXML parse the XML with multiple tags with the same name


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?


Solution

  • 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