]> git.sesse.net Git - vlc/blob - share/lua/modules/simplexml.lua
bda68a4869a3a3097c550470319b45a4eb0da48b
[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)
33     local xml = vlc.xml()
34     local reader = xml:create_reader(stream)
35
36     local tree
37     local parents = {}
38     while reader:read() > 0 do
39         local nodetype = reader:node_type()
40         --print(nodetype, reader:name())
41         if nodetype == 'startelem' then
42             local name = reader:name()
43             local node = { name= '', attributes= {}, children= {} }
44             node.name = name
45             while reader:next_attr() == 0 do
46                 node.attributes[reader:name()] = reader:value()
47             end
48             if tree then
49                 table.insert(tree.children, node)
50                 table.insert(parents, tree)
51             end
52             tree = node
53         elseif nodetype == 'endelem' then
54             if #parents > 0 then
55                 local name = reader:name()
56                 local tmp = {}
57                 --print(name, tree.name, #parents)
58                 while name ~= tree.name do
59                     if #parents == 0 then
60                         error("XML parser error/faulty logic")
61                     end
62                     local child = tree
63                     tree = parents[#parents]
64                     table.remove(parents)
65                     table.remove(tree.children)
66                     table.insert(tmp, 1, child)
67                     for i, node in pairs(child.children) do
68                         table.insert(tmp, i+1, node)
69                     end
70                     child.children = {}
71                 end
72                 for _, node in pairs(tmp) do
73                     table.insert(tree.children, node)
74                 end
75                 tree = parents[#parents]
76                 table.remove(parents)
77             end
78         elseif nodetype == 'text' then
79             table.insert(tree.children, reader:value())
80         end
81     end
82
83     if #parents > 0 then
84         error("XML parser error/Missing closing tags")
85     end
86     return tree
87 end
88
89 function parse_url(url)
90     return parsexml(vlc.stream(url))
91 end
92
93 function parse_string(str)
94     return parsexml(vlc.memory_stream(str))
95 end
96
97 function add_name_maps(tree)
98     tree.children_map = {}
99     for _, node in pairs(tree.children) do
100         if type(node) == "table" then
101             if not tree.children_map[node.name] then
102                 tree.children_map[node.name] = {}
103             end
104             table.insert(tree.children_map[node.name], node)
105             add_name_maps(node)
106         end
107     end
108 end