]> git.sesse.net Git - vlc/blob - share/lua/modules/simplexml.lua
LUA SD: Fix Librivox duration parser.
[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     local nodetype, nodename = reader:next_node()
40
41     while nodetype > 0 do
42         if nodetype == 1 then
43             local node = { name= nodename, attributes= {}, children= {} }
44             local attr, value = reader:next_attr()
45             while attr ~= nil do
46                 node.attributes[attr] = value
47                 attr, value = reader:next_attr()
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 == 2 then
55             if #parents > 0 then
56                 local tmp = {}
57                 while nodename ~= tree.name do
58                     if #parents == 0 then
59                         error("XML parser error/faulty logic")
60                     end
61                     local child = tree
62                     tree = parents[#parents]
63                     table.remove(parents)
64                     table.remove(tree.children)
65                     table.insert(tmp, 1, child)
66                     for i, node in pairs(child.children) do
67                         table.insert(tmp, i+1, node)
68                     end
69                     child.children = {}
70                 end
71                 for _, node in pairs(tmp) do
72                     table.insert(tree.children, node)
73                 end
74                 tree = parents[#parents]
75                 table.remove(parents)
76             end
77         elseif nodetype == 3 then
78             table.insert(tree.children, nodename)
79         end
80         nodetype, nodename = reader:next_node()
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
109