LuaXML.lua 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. local base = _G
  2. -- symbolic name for tag index, this allows accessing the tag by var[xml.TAG]
  3. xml.TAG = 0
  4. -- sets or returns tag of a LuaXML object
  5. function xml.tag(var,tag)
  6. if base.type(var)~="table" then return end
  7. if base.type(tag)=="nil" then
  8. return var[xml.TAG]
  9. end
  10. var[xml.TAG] = tag
  11. end
  12. -- creates a new LuaXML object either by setting the metatable of an existing Lua table or by setting its tag
  13. function xml.new(arg)
  14. if base.type(arg)=="table" then
  15. base.setmetatable(arg,{__index=xml, __tostring=xml.str})
  16. return arg
  17. end
  18. local var={}
  19. base.setmetatable(var,{__index=xml, __tostring=xml.str})
  20. if base.type(arg)=="string" then var[xml.TAG]=arg end
  21. return var
  22. end
  23. -- appends a new subordinate LuaXML object to an existing one, optionally sets tag
  24. function xml.append(var,tag)
  25. if base.type(var)~="table" then return end
  26. local newVar = xml.new(tag)
  27. var[#var+1] = newVar
  28. return newVar
  29. end
  30. -- converts any Lua var into an XML string
  31. function xml.str(var,indent,tagValue)
  32. if base.type(var)=="nil" then return end
  33. local indent = indent or 0
  34. local indentStr=""
  35. for i = 1,indent do indentStr=indentStr.." " end
  36. local tableStr=""
  37. if base.type(var)=="table" then
  38. local tag = var[0] or tagValue or base.type(var)
  39. local s = indentStr.."<"..tag
  40. for k,v in base.pairs(var) do -- attributes
  41. if base.type(k)=="string" then
  42. if base.type(v)=="table" and k~="_M" then -- otherwise recursiveness imminent
  43. tableStr = tableStr..xml.str(v,indent+1,k)
  44. else
  45. s = s.." "..k.."=\""..xml.encode(base.tostring(v)).."\""
  46. end
  47. end
  48. end
  49. if #var==0 and #tableStr==0 then
  50. s = s.." />\n"
  51. elseif #var==1 and base.type(var[1])~="table" and #tableStr==0 then -- single element
  52. s = s..">"..xml.encode(base.tostring(var[1])).."</"..tag..">\n"
  53. else
  54. s = s..">\n"
  55. for k,v in base.ipairs(var) do -- elements
  56. if base.type(v)=="string" then
  57. s = s..indentStr.." "..xml.encode(v).." \n"
  58. else
  59. s = s..xml.str(v,indent+1)
  60. end
  61. end
  62. s=s..tableStr..indentStr.."</"..tag..">\n"
  63. end
  64. return s
  65. else
  66. local tag = base.type(var)
  67. return indentStr.."<"..tag.."> "..xml.encode(base.tostring(var)).." </"..tag..">\n"
  68. end
  69. end
  70. -- saves a Lua var as xml file
  71. function xml.save(var,filename)
  72. if not var then return end
  73. if not filename or #filename==0 then return end
  74. local file = base.io.open(filename,"w")
  75. file:write("<?xml version=\"1.0\"?>\n<!-- file \"",filename, "\", generated by LuaXML -->\n\n")
  76. file:write(xml.str(var))
  77. base.io.close(file)
  78. end
  79. -- recursively parses a Lua table for a substatement fitting to the provided tag and attribute
  80. function xml.find(var, tag, attributeKey,attributeValue)
  81. -- check input:
  82. if base.type(var)~="table" then return end
  83. if base.type(tag)=="string" and #tag==0 then tag=nil end
  84. if base.type(attributeKey)~="string" or #attributeKey==0 then attributeKey=nil end
  85. if base.type(attributeValue)=="string" and #attributeValue==0 then attributeValue=nil end
  86. -- compare this table:
  87. if tag~=nil then
  88. if var[0]==tag and ( attributeValue == nil or var[attributeKey]==attributeValue ) then
  89. base.setmetatable(var,{__index=xml, __tostring=xml.str})
  90. return var
  91. end
  92. else
  93. if attributeValue == nil or var[attributeKey]==attributeValue then
  94. base.setmetatable(var,{__index=xml, __tostring=xml.str})
  95. return var
  96. end
  97. end
  98. -- recursively parse subtags:
  99. for k,v in base.ipairs(var) do
  100. if base.type(v)=="table" then
  101. local ret = xml.find(v, tag, attributeKey,attributeValue)
  102. if ret ~= nil then return ret end
  103. end
  104. end
  105. end