1 |
1 |
2 local lfs = require "lfs"; |
2 local lfs = require "lfs"; |
3 local lxp = require "lxp"; |
|
4 local st = require "util.stanza"; |
3 local st = require "util.stanza"; |
|
4 local parse_xml = require "util.xml".parse; |
5 local os_getenv = os.getenv; |
5 local os_getenv = os.getenv; |
6 local io_open = io.open; |
6 local io_open = io.open; |
7 local assert = assert; |
7 local assert = assert; |
8 local ipairs = ipairs; |
8 local ipairs = ipairs; |
9 local coroutine = coroutine; |
9 local coroutine = coroutine; |
14 local function is_dir(path) return lfs.attributes(path, "mode") == "directory"; end |
14 local function is_dir(path) return lfs.attributes(path, "mode") == "directory"; end |
15 local function is_file(path) return lfs.attributes(path, "mode") == "file"; end |
15 local function is_file(path) return lfs.attributes(path, "mode") == "file"; end |
16 local function clean_path(path) |
16 local function clean_path(path) |
17 return path:gsub("\\", "/"):gsub("//+", "/"):gsub("^~", os_getenv("HOME") or "~"); |
17 return path:gsub("\\", "/"):gsub("//+", "/"):gsub("^~", os_getenv("HOME") or "~"); |
18 end |
18 end |
19 |
|
20 local parse_xml = (function() |
|
21 local ns_prefixes = { |
|
22 ["http://www.w3.org/XML/1998/namespace"] = "xml"; |
|
23 }; |
|
24 local ns_separator = "\1"; |
|
25 local ns_pattern = "^([^"..ns_separator.."]*)"..ns_separator.."?(.*)$"; |
|
26 return function(xml) |
|
27 local handler = {}; |
|
28 local stanza = st.stanza("root"); |
|
29 function handler:StartElement(tagname, attr) |
|
30 local curr_ns,name = tagname:match(ns_pattern); |
|
31 if name == "" then |
|
32 curr_ns, name = "", curr_ns; |
|
33 end |
|
34 if curr_ns ~= "" then |
|
35 attr.xmlns = curr_ns; |
|
36 end |
|
37 for i=1,#attr do |
|
38 local k = attr[i]; |
|
39 attr[i] = nil; |
|
40 local ns, nm = k:match(ns_pattern); |
|
41 if nm ~= "" then |
|
42 ns = ns_prefixes[ns]; |
|
43 if ns then |
|
44 attr[ns..":"..nm] = attr[k]; |
|
45 attr[k] = nil; |
|
46 end |
|
47 end |
|
48 end |
|
49 stanza:tag(name, attr); |
|
50 end |
|
51 function handler:CharacterData(data) |
|
52 stanza:text(data); |
|
53 end |
|
54 function handler:EndElement(tagname) |
|
55 stanza:up(); |
|
56 end |
|
57 local parser = lxp.new(handler, "\1"); |
|
58 local ok, err, line, col = parser:parse(xml); |
|
59 if ok then ok, err, line, col = parser:parse(); end |
|
60 --parser:close(); |
|
61 if ok then |
|
62 return stanza.tags[1]; |
|
63 else |
|
64 return ok, err.." (line "..line..", col "..col..")"; |
|
65 end |
|
66 end; |
|
67 end)(); |
|
68 |
19 |
69 local function load_xml(path) |
20 local function load_xml(path) |
70 local f, err = io_open(path); |
21 local f, err = io_open(path); |
71 if not f then return f, err; end |
22 if not f then return f, err; end |
72 local data = f:read("*a"); |
23 local data = f:read("*a"); |