Xorn
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
xmlread.py
Go to the documentation of this file.
1 # Copyright (C) 2013-2016 Roland Lutz
2 #
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 
17 ## \namespace xorn.geda.xmlread
18 ## Reading gEDA schematic/symbol files in XML format.
19 
20 import cStringIO, xml.parsers.expat
21 from gettext import gettext as _
22 import xorn.base64
23 import xorn.fixednum
24 import xorn.hybridnum
25 import xorn.proxy
26 import xorn.storage
27 import xorn.geda.ref
28 from xorn.geda.xmlformat import *
29 
30 NSSEP = '!'
31 
33  def start_element(self, name, attributes):
34  return self
35 
36  def end_element(self, name):
37  pass
38 
39  def character_data(self, data):
40  pass
41 
42 class NullHandler:
43  def __init__(self, log):
44  self.log = log
45 
46  def start_element(self, name, attributes):
47  self.log.error(_("unexpected element \"%s\"") % name)
48  return VoidHandler()
49 
50  def end_element(self, name):
51  pass
52 
53  def character_data(self, data):
54  s = data.strip()
55  if s:
56  self.log.error(_("unexpected character data \"%s\"") % s)
57 
59  def __init__(self, log, text):
60  self.log = log
61  self.text = text
62 
63  def start_element(self, name, attributes):
64  if name != 'br':
65  return NullHandler.start_element(self, name, attributes)
66 
67  self.text.append('\n')
68  return NullHandler(self.log)
69 
70  def character_data(self, data):
71  self.text.append(data.replace('\\', '\\\\'))
72 
73  def end_element(self, name):
74  self.text.append('\\_')
75 
77  def __init__(self, log, rev, attached_to, data, attribute_name):
78  self.log = log
79  self.rev = rev
80  self.attached_to = attached_to
81  self.data = data
82  self.text = []
83  if attribute_name is not None:
84  self.text.append('%s=' % attribute_name)
85 
86  def start_element(self, name, attributes):
87  if name == 'br':
88  self.text.append('\n')
89  return NullHandler(self.log)
90 
91  if name == 'overbar':
92  self.text.append('\\_')
93  return OverbarHandler(self.log, self.text)
94 
95  return NullHandler.start_element(self, name, attributes)
96 
97  def character_data(self, data):
98  self.text.append(data.replace('\\', '\\\\'))
99 
100  def end_element(self, name):
101  self.data.text = ''.join(self.text).encode('utf-8')
102  ob = self.rev.add_object(self.data)
103  if self.attached_to is not None:
104  self.rev.relocate_object(ob, self.attached_to, None)
105 
107  def __init__(self, log, rev, data):
108  self.log = log
109  self.rev = rev
110  self.data = data
111  self.fragments = []
112 
113  def start_element(self, name, attributes):
114  if name != 'br':
115  return NullHandler.start_element(self, name, attributes)
116 
117  self.fragments.append('\n')
118  return NullHandler(self.log)
119 
120  def character_data(self, data):
121  try:
122  self.fragments.append(data.encode())
123  except UnicodeEncodeError:
124  self.log.error(_("non-ASCII character in path data"))
125 
126  def end_element(self, name):
127  self.data.pathdata = ''.join(self.fragments)
128  self.rev.add_object(self.data)
129 
130 def parse_angle(x):
131  angle = int(x)
132  if angle != 0 and angle != 90 and angle != 180 and angle != 270:
133  raise ValueError
134  return angle
135 
137  def __init__(self, c, rev, attached_to):
138  self.log = c.log
139  self.c = c
140  self.rev = rev
141  self.attached_to = attached_to
142 
143  def start_element(self, name, attributes):
144  if name == 'text' or name == 'attribute':
145  is_attribute = name == 'attribute'
146  data = xorn.storage.Text(
147  x = self.c.parse_attribute(
148  attributes, 'x', None,
149  self.c.parse, 'X coordinate'),
150  y = self.c.parse_attribute(
151  attributes, 'y', None,
152  self.c.parse, 'Y coordinate'),
153  color = self.c.parse_attribute(
154  attributes, 'color',
155  5 if is_attribute else 9,
156  ENUM_COLOR.index, 'color'),
157  text_size = self.c.parse_attribute(
158  attributes, 'size', None,
159  int, 'text size'),
160  visibility = self.c.parse_attribute(
161  attributes, 'visible', None if is_attribute else 1,
162  ENUM_BOOLEAN.index, 'text visibility'),
163  show_name_value = self.c.parse_attribute(
164  attributes, 'show', None if is_attribute else 0,
165  ENUM_SHOW_NAME_VALUE.index, 'show name/value value'),
166  angle = self.c.parse_attribute(
167  attributes, 'angle', 0,
168  parse_angle, 'angle'),
169  alignment = self.c.parse_attribute(
170  attributes, 'alignment', 0,
171  ENUM_ALIGNMENT.index, 'alignment'))
172  if is_attribute:
173  try:
174  name = attributes.pop('name')
175  except KeyError:
176  self.c.log.error(_("attribute name not specified"))
177  name = None
178  else:
179  name = None
180  return TextHandler(
181  self.c.log, self.rev, self.attached_to, data, name)
182 
183  if self.attached_to:
184  self.c.log.error(_("non-text element can't be attached"))
185  return VoidHandler()
186 
187  if name == 'arc':
188  self.rev.add_object(
190  x = self.c.parse_attribute(
191  attributes, 'x', None,
192  self.c.parse, 'X coordinate'),
193  y = self.c.parse_attribute(
194  attributes, 'y', None,
195  self.c.parse, 'Y coordinate'),
196  radius = self.c.parse_attribute(
197  attributes, 'radius', None,
198  self.c.parse, 'radius'),
199  startangle = self.c.parse_attribute(
200  attributes, 'startangle', None,
201  int, 'start angle'),
202  sweepangle = self.c.parse_attribute(
203  attributes, 'sweepangle', None,
204  int, 'sweep angle'),
205  color = self.c.parse_attribute(
206  attributes, 'color', 3,
207  ENUM_COLOR.index, 'color'),
208  line = self.c.parse_line(attributes)))
209  return NullHandler(self.c.log)
210 
211  if name == 'box':
212  self.rev.add_object(
214  x = self.c.parse_attribute(
215  attributes, 'x', None,
216  self.c.parse, 'X coordinate'),
217  y = self.c.parse_attribute(
218  attributes, 'y', None,
219  self.c.parse, 'Y coordinate'),
220  width = self.c.parse_attribute(
221  attributes, 'width', None,
222  self.c.parse, 'width'),
223  height = self.c.parse_attribute(
224  attributes, 'height', None,
225  self.c.parse, 'height'),
226  color = self.c.parse_attribute(
227  attributes, 'color', 3,
228  ENUM_COLOR.index, 'color'),
229  line = self.c.parse_line(attributes),
230  fill = self.c.parse_fill(attributes)))
231  return NullHandler(self.c.log)
232 
233  if name == 'circle':
234  self.rev.add_object(
236  x = self.c.parse_attribute(
237  attributes, 'x', None,
238  self.c.parse, 'X coordinate'),
239  y = self.c.parse_attribute(
240  attributes, 'y', None,
241  self.c.parse, 'Y coordinate'),
242  radius = self.c.parse_attribute(
243  attributes, 'radius', None,
244  self.c.parse, 'radius'),
245  color = self.c.parse_attribute(
246  attributes, 'color', 3,
247  ENUM_COLOR.index, 'color'),
248  line = self.c.parse_line(attributes),
249  fill = self.c.parse_fill(attributes)))
250  return NullHandler(self.c.log)
251 
252  if name == 'component':
253  ob = self.rev.add_object(
255  x = self.c.parse_attribute(
256  attributes, 'x', None,
257  self.c.parse, 'X coordinate'),
258  y = self.c.parse_attribute(
259  attributes, 'y', None,
260  self.c.parse, 'Y coordinate'),
261  selectable = self.c.parse_attribute(
262  attributes, 'selectable', True,
263  ENUM_BOOLEAN.index, 'selectability'),
264  angle = self.c.parse_attribute(
265  attributes, 'angle', 0,
266  parse_angle, 'angle'),
267  mirror = self.c.parse_attribute(
268  attributes, 'mirror', False,
269  ENUM_BOOLEAN.index, 'mirror flag')))
270  try:
271  symbol_id = attributes.pop('symbol')
272  except KeyError:
273  self.c.log.error(_("symbol not specified"))
274  else:
275  if not symbol_id:
276  self.c.log.error(_("symbol id can't be empty"))
277  else:
278  self.c.symbol_refs.append(
279  (self.rev, ob, symbol_id, self.c.log.lineno))
280 
281  return ContentHandler(self.c, self.rev, ob)
282 
283  if name == 'line':
284  x0 = self.c.parse_attribute(attributes, 'x0', None,
285  self.c.parse, 'first X coordinate')
286  y0 = self.c.parse_attribute(attributes, 'y0', None,
287  self.c.parse, 'first Y coordinate')
288  x1 = self.c.parse_attribute(attributes, 'x1', None,
289  self.c.parse, 'second X coordinate')
290  y1 = self.c.parse_attribute(attributes, 'y1', None,
291  self.c.parse, 'second Y coordinate')
292  self.rev.add_object(
294  x = x0, y = y0, width = x1 - x0, height = y1 - y0,
295  color = self.c.parse_attribute(
296  attributes, 'color', 3,
297  ENUM_COLOR.index, 'color'),
298  line = self.c.parse_line(attributes)))
299  return NullHandler(self.c.log)
300 
301  if name == 'net' or name == 'pin':
302  is_pin = name == 'pin'
303  is_bus = self.c.parse_attribute(attributes, 'type', False,
304  ENUM_NETTYPE.index, 'net/pin type')
305  if is_pin:
306  default_color = 1
307  is_inverted = self.c.parse_attribute(
308  attributes, 'inverted', False,
309  ENUM_BOOLEAN.index, 'invertedness')
310  else:
311  if is_bus:
312  default_color = 10
313  else:
314  default_color = 4
315  is_inverted = False
316 
317  x0 = self.c.parse_attribute(attributes, 'x0', None,
318  self.c.parse, 'first X coordinate')
319  y0 = self.c.parse_attribute(attributes, 'y0', None,
320  self.c.parse, 'first Y coordinate')
321  x1 = self.c.parse_attribute(attributes, 'x1', None,
322  self.c.parse, 'second X coordinate')
323  y1 = self.c.parse_attribute(attributes, 'y1', None,
324  self.c.parse, 'second Y coordinate')
325  ob = self.rev.add_object(
327  x = x0, y = y0, width = x1 - x0, height = y1 - y0,
328  color = self.c.parse_attribute(
329  attributes, 'color', default_color,
330  ENUM_COLOR.index, 'color'),
331  is_bus = is_bus,
332  is_pin = is_pin,
333  is_inverted = is_inverted))
334  return ContentHandler(self.c, self.rev, ob)
335 
336  if name == 'path':
337  return PathHandler(self.c.log, self.rev, xorn.storage.Path(
338  color = self.c.parse_attribute(attributes, 'color', 3,
339  ENUM_COLOR.index, 'color'),
340  line = self.c.parse_line(attributes),
341  fill = self.c.parse_fill(attributes)))
342 
343  if name == 'picture':
344  ob = self.rev.add_object(
346  x = self.c.parse_attribute(
347  attributes, 'x', None,
348  self.c.parse, 'X coordinate'),
349  y = self.c.parse_attribute(
350  attributes, 'y', None,
351  self.c.parse, 'Y coordinate'),
352  width = self.c.parse_attribute(
353  attributes, 'width', None,
354  self.c.parse, 'width'),
355  height = self.c.parse_attribute(
356  attributes, 'height', None,
357  self.c.parse, 'height'),
358  angle = self.c.parse_attribute(
359  attributes, 'angle', 0,
360  parse_angle, 'angle'),
361  mirror = self.c.parse_attribute(
362  attributes, 'mirrored', False,
363  ENUM_BOOLEAN.index, 'mirror flag'),
364  pixmap = None))
365  try:
366  pixmap_id = attributes.pop('pixmap')
367  except KeyError:
368  self.c.log.error(_("pixmap not specified"))
369  else:
370  if not pixmap_id:
371  self.c.log.error(_("pixmap id can't be empty"))
372  else:
373  self.c.pixmap_refs.append(
374  (self.rev, ob, pixmap_id, self.c.log.lineno))
375 
376  return NullHandler(self.c.log)
377 
378  self.c.log.error(_("unexpected element \"%s\"") % name)
379  return VoidHandler()
380 
382  def __init__(self, log, pixmap, just_verify):
383  self.log = log
384  self.pixmap = pixmap
385  self.just_verify = just_verify
386  self.f = cStringIO.StringIO()
387 
388  def character_data(self, data):
389  self.f.write(data)
390 
391  def end_element(self, name):
392  self.f.seek(0)
393  try:
394  data = xorn.base64.decode(self.f)
396  self.log.error(_("base64 decoding error"))
397  return
398  if not self.just_verify:
399  self.pixmap.data = data
400  elif data != self.pixmap.data:
401  self.log.warn(_("contents of pixmap file \"%s\" don't match "
402  "embedded data") % self.pixmap.filename)
403 
405  def __init__(self, log, load_symbol, load_pixmap):
406  self.log = log
407  self.ids = set()
408  self.symbols = {}
409  self.pixmaps = {}
410  self.symbol_refs = []
411  self.pixmap_refs = []
412  self.load_symbol = load_symbol
413  self.load_pixmap = load_pixmap
414  self.use_hybridnum = False
415 
416  def parse(self, x):
417  if self.use_hybridnum:
418  return xorn.hybridnum.parse(x, 2)
419  else:
420  return float(xorn.fixednum.parse(x, 2))
421 
422  def parse_attribute(self, d, key, default, processor, msg_fragment):
423  try:
424  x = d.pop(key)
425  except KeyError:
426  if default is not None:
427  return default
428  self.log.error(_("%s not specified") % msg_fragment)
429  else:
430  try:
431  return processor(x)
432  except (KeyError, ValueError):
433  self.log.error(_("invalid %s \"%s\"") % (msg_fragment, x))
434 
435  # guess a well-formed return value from processor function
436  return 0. if processor == self.parse else 0
437 
438  def parse_line(self, attributes):
439  line = xorn.storage.LineAttr()
440  line.width = self.parse_attribute(
441  attributes, 'linewidth', 0, self.parse, 'line width')
442  line.cap_style = self.parse_attribute(
443  attributes, 'capstyle', 0, ENUM_CAPSTYLE.index, 'cap style')
444  line.dash_style = self.parse_attribute(
445  attributes, 'dashstyle', 0, ENUM_DASHSTYLE.index, 'dash style')
446  if line.dash_style != 0 and line.dash_style != 1:
447  line.dash_length = self.parse_attribute(
448  attributes, 'dashlength', None, self.parse, 'dash length')
449  else:
450  line.dash_length = -1
451  if line.dash_style != 0:
452  line.dash_space = self.parse_attribute(
453  attributes, 'dashspace', None, self.parse, 'dash space')
454  else:
455  line.dash_space = -1
456  return line
457 
458  def parse_fill(self, attributes):
459  fill = xorn.storage.FillAttr()
460  fill.type = self.parse_attribute(
461  attributes, 'filltype', 0, ENUM_FILLTYPE.index, 'fill type')
462  if fill.type == 2 or fill.type == 3:
463  fill.width = self.parse_attribute(
464  attributes, 'fillwidth', None, self.parse, 'fill width')
465  fill.angle0 = self.parse_attribute(
466  attributes, 'angle0', None, int, 'first fill angle')
467  fill.pitch0 = self.parse_attribute(
468  attributes, 'pitch0', None, self.parse, 'first fill pitch')
469  else:
470  fill.width = -1
471  fill.angle0 = -1
472  fill.pitch0 = -1
473  if fill.type == 2:
474  fill.angle1 = self.parse_attribute(
475  attributes, 'angle1', None, int, 'second fill angle')
476  fill.pitch1 = self.parse_attribute(
477  attributes, 'pitch1', None, self.parse, 'second fill pitch')
478  else:
479  fill.angle1 = -1
480  fill.pitch1 = -1
481  return fill
482 
484  def __init__(self, c):
485  self.log = c.log
486  self.c = c
488  self.had_content = False
489 
490  def start_element(self, name, attributes):
491  if name == 'content':
492  if self.had_content:
493  self.c.log.error(_("duplicate content tag"))
494  return VoidHandler()
495  self.had_content = True
496  return ContentHandler(self.c, self.rev, None)
497 
498  if name == 'symbol':
499  try:
500  mode = attributes.pop('mode')
501  except KeyError:
502  self.c.log.error(_("symbol mode not specified"))
503  return VoidHandler()
504  if mode == 'omitted':
505  read_symbol = False
506  is_embedded = False
507  elif mode == 'referenced':
508  read_symbol = True
509  is_embedded = False
510  elif mode == 'embedded':
511  read_symbol = True
512  is_embedded = True
513  else:
514  self.c.log.error(_("invalid symbol mode \"%s\"") % mode)
515  return VoidHandler()
516 
517  try:
518  name = attributes.pop('name')
519  except KeyError:
520  if not is_embedded:
521  self.c.log.error(_("symbol name not specified"))
522  return VoidHandler()
523  name = None
524  if is_embedded:
525  symbol = xorn.geda.ref.Symbol(name, None, True)
526  else:
527  symbol = self.c.load_symbol(name, read_symbol)
528  if symbol is None:
529  symbol = xorn.geda.ref.Symbol(name, None, False)
530  is_embedded = True
531  assert not symbol.embedded
532  try:
533  symbol_id = attributes.pop('id')
534  except KeyError:
535  self.c.log.error(_("symbol id not specified"))
536  return VoidHandler()
537  if not symbol_id:
538  self.c.log.error(_("symbol id can't be empty"))
539  return VoidHandler()
540  if symbol_id in self.c.ids:
541  self.c.log.error(_("duplicate id \"%s\"") % symbol_id)
542  return VoidHandler()
543  self.c.ids.add(symbol_id)
544  self.c.symbols[symbol_id] = symbol
545  if not read_symbol:
546  return NullHandler(self.c.log)
547 
548  reh = RootElementHandler(self.c)
549  if is_embedded:
550  symbol.prim_objs = reh.rev
551  return reh
552 
553  if name == 'pixmap':
554  try:
555  mode = attributes.pop('mode')
556  except KeyError:
557  self.c.log.error(_("pixmap mode not specified"))
558  return VoidHandler()
559  if mode == 'omitted':
560  read_pixmap = False
561  is_embedded = False
562  elif mode == 'referenced':
563  read_pixmap = True
564  is_embedded = False
565  elif mode == 'embedded':
566  read_pixmap = True
567  is_embedded = True
568  else:
569  self.c.log.error(_("invalid pixmap mode \"%s\"") % mode)
570  return VoidHandler()
571 
572  try:
573  name = attributes.pop('name')
574  except KeyError:
575  if not is_embedded:
576  self.c.log.error(_("pixmap name not specified"))
577  return VoidHandler()
578  name = None
579  if is_embedded:
580  pixmap = xorn.geda.ref.Pixmap(name, None, True)
581  else:
582  pixmap = self.c.load_pixmap(name, read_pixmap)
583  if pixmap is None:
584  pixmap = xorn.geda.ref.Pixmap(name, None, False)
585  is_embedded = True
586  assert not pixmap.embedded
587  try:
588  pixmap_id = attributes.pop('id')
589  except KeyError:
590  self.c.log.error(_("pixmap id not specified"))
591  return VoidHandler()
592  if not pixmap_id:
593  self.c.log.error(_("pixmap id can't be empty"))
594  return VoidHandler()
595  if pixmap_id in self.c.ids:
596  self.c.log.error(_("duplicate id \"%s\"") % pixmap_id)
597  return VoidHandler()
598  self.c.ids.add(pixmap_id)
599  self.c.pixmaps[pixmap_id] = pixmap
600  if read_pixmap:
601  return PixmapHandler(self.c.log, pixmap, not is_embedded)
602  else:
603  return NullHandler(self.c.log)
604 
605  self.c.log.error(_("unexpected element \"%s\"") % name)
606  return VoidHandler()
607 
608  def end_element(self, name):
609  if not self.had_content:
610  self.c.log.error(_("content missing"))
611 
612 def read_file(f, name, log, load_symbol, load_pixmap):
613  context = LoadContext(log, load_symbol, load_pixmap)
614  reh = RootElementHandler(context)
615 
616  def start_root_element(name, attributes):
617  if name != 'symbol' and name != 'schematic':
618  log.error(_("invalid root element \"%s\"") % name)
619  return VoidHandler()
620 
621  for feature in attributes.pop('file-format-features', '').split(' '):
622  if not feature:
623  continue
624  if feature == 'experimental':
625  pass
626  elif feature == 'hybridnum':
627  if context.use_hybridnum:
628  log.error(_("duplicate file format feature"))
629  context.use_hybridnum = True
630  else:
631  log.error(_("unsupported file format feature \"%s\"")
632  % feature)
633 
634  return reh
635 
636  read_xml_file(f, log, NAMESPACE, start_root_element)
637 
638  for rev, ob, symbol_id, lineno in context.symbol_refs:
639  if symbol_id not in context.symbols:
640  log.lineno = lineno
641  log.error(_("undefined symbol \"%s\"") % symbol_id)
642  continue
643  data = rev.get_object_data(ob)
644  data.symbol = context.symbols[symbol_id]
645  rev.set_object_data(ob, data)
646 
647  for rev, ob, pixmap_id, lineno in context.pixmap_refs:
648  if pixmap_id not in context.pixmaps:
649  log.lineno = lineno
650  log.error(_("undefined pixmap \"%s\"") % pixmap_id)
651  continue
652  data = rev.get_object_data(ob)
653  data.pixmap = context.pixmaps[pixmap_id]
654  rev.set_object_data(ob, data)
655 
656  return xorn.proxy.RevisionProxy(reh.rev)
657 
658 def read_xml_file(f, log, namespace, start_root_element):
659  stack = []
660 
661  def strip_namespace(name, ignore_errors):
662  try:
663  pos = name.index(NSSEP)
664  except ValueError:
665  if not ignore_errors:
666  log.error(_("element name \"%s\" without namespace") % name)
667  return None
668 
669  if name[:pos] != namespace and not ignore_errors:
670  log.error(_("invalid namespace \"%s\"") % name[:pos])
671  return None
672 
673  return name[pos + 1:]
674 
675  def StartElementHandler(name, attributes):
676  log.lineno = p.CurrentLineNumber - 1
677  name = strip_namespace(name, False)
678  if name is None:
679  new_handler = VoidHandler()
680  elif stack:
681  new_handler = stack[-1].start_element(name, attributes)
682  else:
683  new_handler = start_root_element(name, attributes)
684  stack.append(new_handler)
685 
686  if attributes and not isinstance(new_handler, VoidHandler):
687  log.error(_("unexpected attribute(s) %s") % _(", ").join(
688  _("\"%s\"") % attr for attr in sorted(attributes)))
689 
690  def EndElementHandler(name):
691  log.lineno = p.CurrentLineNumber - 1
692  name = strip_namespace(name, True)
693  stack.pop().end_element(name)
694 
695  def CharacterDataHandler(data):
696  log.lineno = p.CurrentLineNumber - 1
697  stack[-1].character_data(data)
698 
699  def StartDoctypeDeclHandler(doctype_name, system_id, public_id,
700  has_internal_subset):
701  log.lineno = p.CurrentLineNumber - 1
702  log.error(_("unexpected XML document type declaration"))
703 
704  def ElementDeclHandler(name, model):
705  log.lineno = p.CurrentLineNumber - 1
706  log.error(_("unexpected XML element type declaration"))
707 
708  def AttlistDeclHandler(elname, attname, type, default, required):
709  log.lineno = p.CurrentLineNumber - 1
710  log.error(_("unexpected XML element type attribute declaration"))
711 
712  def ProcessingInstructionHandler(target, data):
713  log.lineno = p.CurrentLineNumber - 1
714  log.error(_("unexpected XML processing instruction"))
715 
716  def UnparsedEntityDeclHandler(entity_name, base, system_id, public_id,
717  notationName):
718  log.lineno = p.CurrentLineNumber - 1
719  log.error(_("unexpected XML unparsed entity declaration"))
720 
721  def EntityDeclHandler(entity_name, is_parameter_entity, value, base,
722  system_id, public_id, notation_name):
723  log.lineno = p.CurrentLineNumber - 1
724  log.error(_("unexpected XML entity declaration"))
725 
726  def NotationDeclHandler(notation_name, base, system_id, public_id):
727  log.lineno = p.CurrentLineNumber - 1
728  log.error(_("unexpected XML notation declaration"))
729 
730  def StartCdataSectionHandler():
731  log.lineno = p.CurrentLineNumber - 1
732  log.error(_("unexpected XML CDATA section"))
733 
734  def DefaultHandler(data):
735  log.lineno = p.CurrentLineNumber - 1
736  log.error(_("unexpected characters in XML document"))
737 
738  def NotStandaloneHandler():
739  log.lineno = p.CurrentLineNumber - 1
740  log.error(_("XML document hasn't been declared as standalone"))
741 
742  def ExternalEntityRefHandler(context, base, systemId, publicId):
743  log.lineno = p.CurrentLineNumber - 1
744  log.error(_("unexpected reference to external XML entity"))
745 
746  p = xml.parsers.expat.ParserCreate(namespace_separator = '!')
747 
748  p.XmlDeclHandler = None
749  p.StartDoctypeDeclHandler = StartDoctypeDeclHandler
750  p.EndDoctypeDeclHandler = None
751  p.ElementDeclHandler = ElementDeclHandler
752  p.AttlistDeclHandler = AttlistDeclHandler
753  p.StartElementHandler = StartElementHandler
754  p.EndElementHandler = EndElementHandler
755  p.ProcessingInstructionHandler = ProcessingInstructionHandler
756  p.CharacterDataHandler = CharacterDataHandler
757  p.UnparsedEntityDeclHandler = UnparsedEntityDeclHandler
758  p.EntityDeclHandler = EntityDeclHandler
759  p.NotationDeclHandler = NotationDeclHandler
760  p.StartNamespaceDeclHandler = None
761  p.EndNamespaceDeclHandler = None
762  p.CommentHandler = None
763  p.StartCdataSectionHandler = StartCdataSectionHandler
764  p.EndCdataSectionHandler = None
765  p.DefaultHandler = DefaultHandler
766  p.DefaultHandlerExpand = None
767  p.NotStandaloneHandler = NotStandaloneHandler
768  p.ExternalEntityRefHandler = ExternalEntityRefHandler
769 
770  try:
771  p.ParseFile(f)
772  except xml.parsers.expat.ExpatError as e:
773  log.lineno = e.lineno - 1
774  log.error(_("%s") % e)
Reading and writing base64-encoded data.
Definition: base64.py:1
Schematic net segment, bus segment, or pin.
Definition: storage.py:549
Schematic arc.
Definition: storage.py:492
def encode
Write a binary string to a file in base64 representation.
Definition: base64.py:68
Common definitions for XML file format.
Definition: xmlformat.py:1
Raised when reading invalid or unterminated base64-encoded data.
Definition: base64.py:119
High-level revision proxy class.
Definition: proxy.py:24
Schematic picture.
Definition: storage.py:571
Schematic path.
Definition: storage.py:562
def parse
Convert a hybrid string representation to a floating-point number.
Definition: hybridnum.py:133
Schematic box.
Definition: storage.py:504
Schematic component.
Definition: storage.py:527
Schematic circle.
Definition: storage.py:516
Schematic fill style.
Definition: storage.py:481
def decode
Read a string in base64 representation from a file.
Definition: base64.py:138
Fixed-point numbers.
Definition: fixednum.py:1
Schematic line style.
Definition: storage.py:471
Schematic text or attribute.
Definition: storage.py:583
High-level proxy classes for the storage backend.
Definition: proxy.py:1
A particular state of the contents of a file.
Definition: storage.py:35
Referenced symbols and pixmaps.
Definition: ref.py:1
def parse
Convert a fixed-point string representation to an integer.
Definition: fixednum.py:74
Xorn storage backend.
Definition: storage.py:1
Hybrid fixed-/floating-point numbers.
Definition: hybridnum.py:1
Schematic line.
Definition: storage.py:538