1 -- See Copyright Notice in license.html |
1 -- See Copyright Notice in license.html |
2 -- $Id: lom.lua,v 1.6 2005/06/09 19:18:40 tuler Exp $ |
|
3 |
2 |
4 local lxp = require "lxp" |
3 local lxp = require "lxp" |
5 |
4 |
|
5 local table = require"table" |
6 local tinsert, tremove = table.insert, table.remove |
6 local tinsert, tremove = table.insert, table.remove |
7 local assert, type, print = assert, type, print |
7 local assert, pairs, type = assert, pairs, type |
8 |
8 |
9 |
9 |
|
10 -- auxiliary functions ------------------------------------------------------- |
10 local function starttag (p, tag, attr) |
11 local function starttag (p, tag, attr) |
11 local stack = p:getcallbacks().stack |
12 local stack = p:getcallbacks().stack |
12 local newelement = {tag = tag, attr = attr} |
13 local newelement = {tag = tag, attr = attr} |
13 tinsert(stack, newelement) |
14 tinsert(stack, newelement) |
14 end |
15 end |
30 else |
31 else |
31 tinsert(element, txt) |
32 tinsert(element, txt) |
32 end |
33 end |
33 end |
34 end |
34 |
35 |
|
36 -- main function ------------------------------------------------------------- |
35 local function parse (o) |
37 local function parse (o) |
36 local c = { StartElement = starttag, |
38 local c = { StartElement = starttag, |
37 EndElement = endtag, |
39 EndElement = endtag, |
38 CharacterData = text, |
40 CharacterData = text, |
39 _nonstrict = true, |
41 _nonstrict = true, |
40 stack = {{}} |
42 stack = {{}} |
41 } |
43 } |
42 local p = lxp.new(c) |
44 local p = lxp.new(c) |
43 local status, err |
45 local to = type(o) |
44 if type(o) == "string" then |
46 if to == "string" then |
45 status, err = p:parse(o) |
47 local status, err, line, col, pos = p:parse(o) |
46 if not status then return nil, err end |
48 if not status then return nil, err, line, col, pos end |
47 else |
49 else |
48 for l in pairs(o) do |
50 local iter, state, init |
49 status, err = p:parse(l) |
51 if to == "table" then |
50 if not status then return nil, err end |
52 iter, state, init = pairs(o) |
51 end |
53 elseif to == "function" then |
52 end |
54 iter = o |
53 status, err = p:parse() |
55 elseif to == "userdata" and o.read then |
54 if not status then return nil, err end |
56 iter, state = o.read, o |
55 p:close() |
57 else |
56 return c.stack[1][1] |
58 error ("Bad argument #1 to parse: expected a string, a table, a function or a file, but got "..to, 2) |
|
59 end |
|
60 for l in iter, state, init do |
|
61 local status, err, line, col, pos = p:parse(l) |
|
62 if not status then return nil, err, line, col, pos end |
|
63 end |
|
64 end |
|
65 local status, err, line, col, pos = p:parse() -- close document |
|
66 if not status then return nil, err, line, col, pos end |
|
67 p:close() |
|
68 return c.stack[1][1] |
57 end |
69 end |
58 |
70 |
59 return { parse = parse } |
71 -- utility functions --------------------------------------------------------- |
|
72 local function find_elem (self, tag) |
|
73 if self.tag == tag then |
|
74 return self |
|
75 end |
|
76 for i = 1, #self do |
|
77 local v = self[i] |
|
78 if type(v) == "table" then |
|
79 local found = find_elem (v, tag) |
|
80 if found then |
|
81 return found |
|
82 end |
|
83 end |
|
84 end |
|
85 return nil |
|
86 end |
|
87 |
|
88 local function list_children (self, tag) |
|
89 local i = 0 |
|
90 return function () |
|
91 i = i+1 |
|
92 local v = self[i] |
|
93 while v do |
|
94 if type (v) == "table" and (tag == nil or tag == v.tag) then |
|
95 return v |
|
96 end |
|
97 i = i+1 |
|
98 v = self[i] |
|
99 end |
|
100 return nil |
|
101 end |
|
102 end |
|
103 |
|
104 return { |
|
105 find_elem = find_elem, |
|
106 list_children = list_children, |
|
107 parse = parse, |
|
108 } |