]> git.sesse.net Git - vlc/blob - share/lua/modules/simplexml.lua
Change vlc.stream() and vlc.memory_stream() error reporting to behave like lua's...
[vlc] / share / lua / modules / simplexml.lua
1 --[==========================================================================[
2  simplexml.lua: Lua simple xml parser wrapper
3 --[==========================================================================[
4  Copyright (C) 2010 Antoine Cellerier
5  $Id$
6
7  Authors: Antoine Cellerier <dionoea at videolan dot org>
8
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  GNU General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 --]==========================================================================]
23
24 module("simplexml",package.seeall)
25
26 --[[ Returns the xml tree structure
27 --   Each node is of one of the following types:
28 --     { name (string), attributes (key->value map), children (node array) }
29 --     text content (string)
30 --]]
31
32 local function parsexml(stream, errormsg)
33     if not stream then return nil, errormsg end
34     local xml = vlc.xml()
35     local reader = xml:create_reader(stream)
36
37     local tree
38     local parents = {}
39     while reader:read() > 0 do
40         local nodetype = reader:node_type()
41         --print(nodetype, reader:name())
42         if nodetype == 'startelem' then
43             local name = reader:name()
44             local node = { name= '', attributes= {}, children= {} }
45             node.name = name
46             while reader:next_attr() == 0 do
47                 node.attributes[reader:name()] = reader:value()
48             end
49             if tree then
50                 table.insert(tree.children, node)
51                 table.insert(parents, tree)
52             end
53             tree = node
54         elseif nodetype == 'endelem' then
55             if #parents > 0 then
56                 local name = reader:name()
57                 local tmp = {}
58                 --print(name, tree.name, #parents)
59                 while name ~= tree.name do
60                     if #parents == 0 then
61                         error("XML parser error/faulty logic")
62                     end
63                     local child = tree
64                     tree = parents[#parents]
65                     table.remove(parents)
66                     table.remove(tree.children)
67                     table.insert(tmp, 1, child)
68                     for i, node in pairs(child.children) do
69                         table.insert(tmp, i+1, node)
70                     end
71                     child.children = {}
72                 end
73                 for _, node in pairs(tmp) do
74                     table.insert(tree.children, node)
75                 end
76                 tree = parents[#parents]
77                 table.remove(parents)
78             end
79         elseif nodetype == 'text' then
80             table.insert(tree.children, reader:value())
81         end
82     end
83
84     if #parents > 0 then
85         error("XML parser error/Missing closing tags")
86     end
87     return tree
88 end
89
90 function parse_url(url)
91     return parsexml(vlc.stream(url))
92 end
93
94 function parse_string(str)
95     return parsexml(vlc.memory_stream(str))
96 end
97
98 function add_name_maps(tree)
99     tree.children_map = {}
100     for _, node in pairs(tree.children) do
101         if type(node) == "table" then
102             if not tree.children_map[node.name] then
103                 tree.children_map[node.name] = {}
104             end
105             table.insert(tree.children_map[node.name], node)
106             add_name_maps(node)
107         end
108     end
109 end