Search code examples
xmlparsinglualuaxml

How to parse the attribute value of a specific tag of an xml file which has multiple occurrences through Lua?


This is a short snippet of my main XML file named oem.xml -

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Service>
<NewInstance ref="a39d725e7689b99e91af6fcb68bc5ec2">
<Std>DiscoveredElement</Std>
<Key>a39d725e7689b99e91af6fcb68bc5ec2</Key>
<Attributes>
<Attribute name="group" value="OEM All Targets On uxunt200.schneider.com" />
</Attributes>
</NewInstance>
<NewRelationship>
<Parent>
<Instance ref="a39d725e7689b99e91af6fcb68bc5ec2" />
</Parent>
<Components>
<Instance ref="E0246C56D81A7A79559669CD16A8B555" />
<Instance ref="2D5481A0EA3F81AC1E06E2C32231F41B" />
</Components>
<NewInstance ref="E961625723F5FDC8BD550077282E074C">
<Std>DiscoveredElement</Std>
<Key>E961625723F5FDC8BD550077282E074C</Key>
<Attributes>
<Attribute name="ServerNames" value="WLS_B2B4a" />
<Attribute name="orcl_gtp_os" value="Linux" />
<Attribute name="ORACLE_HOME" value="" />
</NewInstance>
</Service>

Now I want to print the text of attribute value and name(eg. Attribute name="ServerNames" value="WLS_B2B4a" ) for all occurrences of the <Attribute> tag.

I tried the following code :

require("LuaXml")
local file = xml.load("oem.xml")
local search = file:find("Attributes")

for Attribute = 1, #search do
  print(search[Attribute].value)
  print(search[Attribute].name)
end

This gives me result for only the first occurrence of the attribute tag.I want to parse till end of the file for all occurrences. Please suggest a solution using the LuaXml library.


Solution

  • LuaXML seems to be pretty minimal and xml.find states:

    Returns the first (sub-)table which matches the search condition or nil.

    A simpler solution would be using Lua string pattern:

    local file = io.open("oem.xml", "rb")   -- Open file for reading (binary data)
    for name, value in file:read("*a"):gmatch("<Attribute name=\"(.-)\" value=\"(.-)\" />") do  -- Read whole file content and iterate through attribute matches
        print(string.format("Name: %s\nValue: %s", name, value))    -- Print what we got
    end
    file:close()    -- Close file (for instant lock-free, no waiting for garbage collector)
    

    Don't forget to check file for being valid.