File: xml.lua

package info (click to toggle)
httest 2.4.23-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,876 kB
  • sloc: ansic: 19,553; sh: 10,550; xml: 1,047; makefile: 510; lisp: 145; perl: 31
file content (98 lines) | stat: -rw-r--r-- 3,683 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
-----------------------------------------------------------------------------------------
-- LUA only XmlParser from Alexander Makeev
-----------------------------------------------------------------------------------------
XmlParser = {};

function XmlParser:ToXmlString(value)
        value = string.gsub (value, "&", "&");              -- '&' -> "&"
        value = string.gsub (value, "<", "&lt;");               -- '<' -> "&lt;"
        value = string.gsub (value, ">", "&gt;");               -- '>' -> "&gt;"
        --value = string.gsub (value, "'", "&apos;");   -- '\'' -> "&apos;"
        value = string.gsub (value, "\"", "&quot;");    -- '"' -> "&quot;"
        -- replace non printable char -> "&#xD;"
        value = string.gsub(value, "([^%w%&%;%p%\t% ])",
        function (c) 
                return string.format("&#x%X;", string.byte(c)) 
                --return string.format("&#x%02X;", string.byte(c)) 
                --return string.format("&#%02d;", string.byte(c)) 
        end);
        return value;
end

function XmlParser:FromXmlString(value)
        value = string.gsub(value, "&#x([%x]+)%;",
        function(h) 
                return string.char(tonumber(h,16)) 
        end);
        value = string.gsub(value, "&#([0-9]+)%;",
        function(h) 
                return string.char(tonumber(h,10)) 
        end);
        value = string.gsub (value, "&quot;", "\"");
        value = string.gsub (value, "&apos;", "'");
        value = string.gsub (value, "&gt;", ">");
        value = string.gsub (value, "&lt;", "<");
        value = string.gsub (value, "&amp;", "&");
        return value;
end
   
function XmlParser:ParseArgs(s)
  local arg = {}
  string.gsub(s, "(%w+)=([\"'])(.-)%2", function (w, _, a)
        arg[w] = self:FromXmlString(a);
        end)
  return arg
end

function XmlParser:ParseXmlText(xmlText)
  local stack = {}
  local top = { Name = nil, Value = nil, Attributes = {}, ChildNodes = {} }
  table.insert(stack, top)
  local ni, c, label, xarg, empty
  local i, j = 1, 1
  while true do
    ni, j, c, label, xarg, empty = string.find(xmlText, "<(%/?)([%w:]+)(.-)(%/?)>", i)
    if not ni then break end
    local text = string.sub(xmlText, i, ni-1);
    if not string.find(text, "^%s*$") then
      top.Value = (top.Value or "")..self:FromXmlString(text);
    end
    if empty == "/" then  -- empty element tag
      table.insert(top.ChildNodes, { Name = label, Value = nil, Attributes = self:ParseArgs(xarg), ChildNodes = {}})
    elseif c == "" then   -- start tag
      top = {Name=label, Value=nil, Attributes=self:ParseArgs(xarg), ChildNodes={}}
      table.insert(stack, top)   -- new level
    else  -- end tag
      local toclose = table.remove(stack)  -- remove top
      top = stack[#stack]
      if #stack < 1 then
        error("XmlParser: nothing to close with "..label)
      elseif toclose.Name ~= label then
        error("XmlParser: trying to close "..toclose.Name.." with "..label)
      else
        table.insert(top.ChildNodes, toclose)
      end
    end
    i = j+1
  end
  local text = string.sub(xmlText, i);
  if not string.find(text, "^%s*$") then
      stack[#stack].Value=(stack[#stack].Value or "")..self:FromXmlString(text);
  end
  if #stack > 1 then
    error("XmlParser: unclosed "..stack[stack.n].Name)
  end
  return stack[1].ChildNodes[1];
end

function XmlParser:ParseXmlFile(xmlFileName)
        local hFile,err = io.open(xmlFileName,"r");
        if (not err) then
                local xmlText=hFile:read("*a"); -- read file content
                io.close(hFile);
        return self:ParseXmlText(xmlText),nil;
        else
                return nil,err;
        end
end