src/lxp/totable.lua

Fri, 23 Apr 2021 21:18:24 +0100

author
Matthew Wild <mwild1@gmail.com>
date
Fri, 23 Apr 2021 21:18:24 +0100
changeset 37
233463804681
permissions
-rw-r--r--

Add lxp.totable by Tom?s Guisasola

37
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 -- See Copyright Notice in license.html
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
2 -- Based on Luiz Henrique de Figueiredo's lxml:
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
3 -- http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/#lxml
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5 local lxp = require "lxp"
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7 local table = require"table"
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8 local tinsert, tremove = table.insert, table.remove
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9 local assert, pairs, tostring, type = assert, pairs, tostring, type
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11 -- auxiliary functions -------------------------------------------------------
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 local function starttag (p, tag, attr)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13 local stack = p:getcallbacks().stack
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14 local newelement = {[0] = tag}
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15 for i = 1, #attr do
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16 local attrname = attr[i]
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17 local attrvalue = attr[attrname]
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18 newelement[attrname] = attrvalue
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
19 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
20 tinsert(stack, newelement)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
22
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
23 local function endtag (p, tag)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
24 local stack = p:getcallbacks().stack
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25 local element = tremove(stack)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
26 assert(element[0] == tag, "Error while closing element: table[0] should be `"..tostring(tag).."' but is `"..tostring(element[0]).."'")
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27 local level = #stack
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28 tinsert(stack[level], element)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
31 local function text (p, txt)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
32 local stack = p:getcallbacks().stack
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33 local element = stack[#stack]
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
34 local n = #element
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
35 if type(element[n]) == "string" and n > 0 then
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36 element[n] = element[n] .. txt
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37 else
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
38 tinsert(element, txt)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
39 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
40 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
41
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
42 -- main function -------------------------------------------------------------
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43 local function parse (o)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44 local c = {
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45 StartElement = starttag,
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 EndElement = endtag,
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47 CharacterData = text,
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 _nonstrict = true,
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49 stack = {{}},
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50 }
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
51 local p = lxp.new(c)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52 if type(o) == "string" then
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
53 local status, err, line, col, pos = p:parse(o)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54 if not status then return nil, err, line, col, pos end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 else
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56 for l in pairs(o) do
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
57 local status, err, line, col, pos = p:parse(l)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
58 if not status then return nil, err, line, col, pos end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
59 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
60 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
61 local status, err, line, col, pos = p:parse() -- close document
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
62 if not status then return nil, err, line, col, pos end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
63 p:close()
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
64 return c.stack[1][1]
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
65 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
66
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
67 -- utility functions ---------------------------------------------------------
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
68 local function compact (t) -- remove empty entries
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
69 local n = 0
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
70 for i = 1, #t do
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
71 local v = t[i]
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
72 if v then
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73 n = n+1
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
74 if n ~= i then
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 t[n] = v
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
76 t[i] = nil
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
77 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
78 else
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
79 t[i] = nil
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
81 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
82 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
83
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
84 local function clean (t) -- remove empty strings
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
85 for i = 1, #t do
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
86 local v = t[i]
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
87 local tv = type(v)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
88 if tv == "table" then
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
89 clean (v)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
90 elseif tv == "string" and v:match"^%s*$" then
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
91 t[i] = false
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
92 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
93 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
94 compact (t)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
95 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
96
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
97 local function torecord (t) -- move 1-value subtables to table entries
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
98 for i = 1, #t do
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
99 local v = t[i]
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
100 if type(v) == "table" then
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
101 if #v == 1 and type(v[1]) == "string" and t[v[0]] == nil then
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
102 t[v[0]] = v[1]
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
103 t[i] = false
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
104 else
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
105 torecord (v)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
106 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
107 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
108 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
109 compact (t)
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
110 end
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
111
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
112 return {
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
113 clean = clean,
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
114 compact = compact,
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
115 parse = parse,
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
116 torecord = torecord,
233463804681 Add lxp.totable by Tom?s Guisasola
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
117 }

mercurial