Atlas  0.7.0
Networking protocol for the Worldforge system.
parse_xml.py
1 # parse XML into objects
2 
3 # Copyright 2000, 2001 by Aloril
4 # Copyright 2002 by AIR-IX SUUNNITTELU/Ahiplan Oy
5 
6 # This library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
10 
11 # This library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Lesser General Public License for more details.
15 
16 import string
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 import xml
21 import xml.sax
22 
23 import atlas
24 from . import decoder
25 
26 """
27 usage:
28 parseXML=get_parser()
29 atlas_objects=parseXML("input XML string here")
30 
31 resulting atlas_objects has 0 or more atlas objects
32 
33 
34 NOTE: you need to make separate parser for each stream (for example
35 when several clients connect)
36 """
37 
38 
39 class XmlException(Exception): pass
40 
41 
42 class AtlasParser(xml.sax.ContentHandler, decoder.BaseDecoder):
43 
44  def __init__(self):
45  super().__init__()
46  self.data = ""
47  self.root_obj = []
48  self.name_stack = []
49  self.obj_stack = [self.root_obj]
50  self.seen_atlas_tag = 0
51  self.msgList = []
52 
53  def setup(self, stream_flag=None):
54  """uses tree that start from root_obj, current route to leave
55  is kept in obj_stack"""
56  # Root object is never removed or visible for parser users,
57  # incoming objects are added to its value
58  self.root_obj = []
59  self.name_stack = []
60  self.obj_stack = [self.root_obj]
61 
62  # resulting complete atlas 'messages' are added here
63  decoder.BaseDecoder.setup(self, stream_flag)
64 
65  def set_stream_mode(self, mode=1):
66  decoder.BaseDecoder.set_stream_mode(self, mode)
67  self.seen_atlas_tag = 0
68 
69  def parse_init(self):
70  if not self.stream_flag and not self.seen_atlas_tag:
71  self.feed("<atlas>")
72 
73 
90 
91  def eos(self):
92  """end of stream"""
93  return not [_f for _f in [ch not in string.whitespace for ch in self.data] if _f] and self.obj_stack == [[]]
94 
95  def unknown_starttag(self, tag, attributes):
96  raise XmlException("Unknown tag: " + tag)
97 
98  def characters(self, data):
99  """#PCDATA (actual string,int,float,uri content)"""
100  self.data = self.data + data
101 
102  def startElement(self, tag, attributes):
103  if tag == "atlas":
104  self.start_atlas()
105  elif tag == "int":
106  self.start_int(attributes)
107  elif tag == "float":
108  self.start_float(attributes)
109  elif tag == "string":
110  self.start_string(attributes)
111  elif tag == "map":
112  self.start_map(attributes)
113  elif tag == "list":
114  self.start_list(attributes)
115 
116  def endElement(self, tag):
117  if tag == "atlas":
118  self.end_atlas()
119  elif tag == "int":
120  self.end_int()
121  elif tag == "float":
122  self.end_float()
123  elif tag == "string":
124  self.end_string()
125  elif tag == "map":
126  self.end_map()
127  elif tag == "list":
128  self.end_list()
129  pass
130 
131  def start_atlas(self):
132  self.seen_atlas_tag = 1
133 
134  def end_atlas(self):
135  self.seen_atlas_tag = 0
136 
137  def start_value(self, attributes):
138  """for int/float/string: save name if have one"""
139  self.name_stack.append(attributes.get("name", ""))
140  self.data = ""
141 
142  def end_value(self, value):
143  """put value into mapping/list"""
144  self.data = ""
145  obj = self.obj_stack[-1]
146  name = self.name_stack[-1]
147  del self.name_stack[-1]
148  if name:
149  if not isinstance(obj, atlas.Object):
150  raise XmlException("attribute outside mapping (%s:%s)!" % \
151  (name, value))
152  setattr(obj, name, value)
153  else:
154  if not isinstance(obj, list):
155  raise XmlException("value mapping list (%s)!" % value)
156  obj.append(value)
157 
158  def push_value(self, attributes, initial_value):
159  """for list/map: add to stack"""
160  self.start_value(attributes)
161  self.obj_stack.append(initial_value)
162 
163  def pop_value(self):
164  """for list/map: remove from stack"""
165  obj = self.obj_stack[-1]
166  del self.obj_stack[-1]
167  self.end_value(obj)
168  # check top level
169  if len(self.obj_stack) == 1:
170  obj = self.obj_stack[0][0]
171  self.msgList.append(obj)
172  del self.obj_stack[0][0]
173 
174  # all single type methods make object with optional name and type
175  # and clear data and at the end tag then parse content
176  def start_int(self, attributes):
177  self.start_value(attributes)
178 
179  def end_int(self):
180  try:
181  value = int(self.data)
182  except ValueError:
183  value = int(self.data)
184  self.end_value(value)
185 
186  def start_float(self, attributes):
187  self.start_value(attributes)
188 
189  def end_float(self):
190  self.end_value(float(self.data))
191 
192  def start_string(self, attributes):
193  self.start_value(attributes)
194 
195  def end_string(self):
196  self.end_value(self.data)
197 
198  def start_list(self, attributes):
199  self.push_value(attributes, [])
200 
201  def end_list(self):
202  self.pop_value()
203 
204  def start_map(self, attributes):
205  self.push_value(attributes, atlas.Object())
206 
207  def end_map(self):
208  self.pop_value()
209 
210 
211 def string2object(string):
212  """convert a string of one entity into an object"""
213  # make a parser
214  parse = get_parser()
215 
216  parse("<atlas>")
217  return parse(string)[0]
218 
219 
220 def parse_string_to_dict(string, full_stream=0):
221  """convert a string of entities into a dict of entites"""
222  # make a parser
223  parse = get_decoder(full_stream)
224 
225 
228 
229  # parse the input file that is xml and put it in all_objects
230  all_objects = parse(string)
231 
232  # make a blank dictionary
233  objects = {}
234 
235  # cut all_object apart and insert it into object
236  for obj in all_objects:
237  objects[obj.id] = obj
238 
239  # return a dict of the parsed item
240  return objects
241 
242 
243 def read_file_to_dict(file):
244  fp = open(file)
245  objects = parse_string_to_dict(fp.read(), full_stream=1)
246  fp.close()
247  return objects
248 
249 
250 def get_decoder(stream_flag=None):
251  xml_msg_parser = AtlasParser()
252  xml_msg_parser.setup(stream_flag)
253  return xml_msg_parser
254 
255 def parse_stream(data):
256  handler = AtlasParser()
257  xml.sax.parseString(data, handler)
258  res=atlas.Messages(*tuple(handler.msgList))
259  return res
260 
atlas.codecs.parse_xml.AtlasParser.start_atlas
def start_atlas(self)
Definition: parse_xml.py:131
atlas.codecs.decoder.BaseDecoder.data
data
Definition: decoder.py:24
atlas.codecs.parse_xml.AtlasParser
Definition: parse_xml.py:42
atlas.codecs.parse_xml.AtlasParser.obj_stack
obj_stack
Definition: parse_xml.py:49
atlas.codecs.parse_xml.AtlasParser.end_list
def end_list(self)
Definition: parse_xml.py:201
atlas.codecs.parse_xml.AtlasParser.start_float
def start_float(self, attributes)
Definition: parse_xml.py:186
atlas.codecs.parse_xml.AtlasParser.end_int
def end_int(self)
Definition: parse_xml.py:179
atlas.codecs.parse_xml.AtlasParser.start_value
def start_value(self, attributes)
Definition: parse_xml.py:137
atlas.codecs.parse_xml.AtlasParser.root_obj
root_obj
Definition: parse_xml.py:47
atlas.codecs.decoder.BaseDecoder
Definition: decoder.py:22
atlas.codecs.parse_xml.AtlasParser.end_float
def end_float(self)
Definition: parse_xml.py:189
atlas.codecs.parse_xml.AtlasParser.seen_atlas_tag
seen_atlas_tag
Definition: parse_xml.py:50
atlas.codecs.parse_xml.AtlasParser.start_string
def start_string(self, attributes)
Definition: parse_xml.py:192
atlas.codecs.parse_xml.AtlasParser.push_value
def push_value(self, attributes, initial_value)
Definition: parse_xml.py:158
atlas.codecs.parse_xml.AtlasParser.start_int
def start_int(self, attributes)
Definition: parse_xml.py:176
atlas.codecs.parse_xml.AtlasParser.name_stack
name_stack
Definition: parse_xml.py:48
atlas.codecs.parse_xml.AtlasParser.end_string
def end_string(self)
Definition: parse_xml.py:195
atlas.codecs.parse_xml.AtlasParser.start_map
def start_map(self, attributes)
Definition: parse_xml.py:204
atlas.codecs.parse_xml.AtlasParser.end_atlas
def end_atlas(self)
Definition: parse_xml.py:134
atlas.codecs.parse_xml.AtlasParser.setup
def setup(self, stream_flag=None)
Definition: parse_xml.py:53
atlas.codecs.parse_xml.AtlasParser.end_map
def end_map(self)
Definition: parse_xml.py:207
atlas.codecs.decoder.BaseDecoder.stream_flag
stream_flag
Definition: decoder.py:29
atlas.codecs.parse_xml.XmlException
Definition: parse_xml.py:39
atlas.codecs.parse_xml.AtlasParser.pop_value
def pop_value(self)
Definition: parse_xml.py:163
atlas.codecs.decoder.BaseDecoder.msgList
msgList
Definition: decoder.py:25
atlas.codecs.parse_xml.AtlasParser.end_value
def end_value(self, value)
Definition: parse_xml.py:142
atlas.Messages
Definition: __init__.py:203
atlas.Object
Definition: __init__.py:36
atlas.codecs.parse_xml.AtlasParser.eos
def eos(self)
def parse_stream(self, msg): """parse incoming data and return all complete messages""" #print msg se...
Definition: parse_xml.py:91
atlas.codecs.parse_xml.AtlasParser.start_list
def start_list(self, attributes)
Definition: parse_xml.py:198
atlas.codecs.parse_xml.AtlasParser.characters
def characters(self, data)
Definition: parse_xml.py:98