netmsgs  1.2.2
RoadNarrows Robotics Network Messaging Package
NetMsgsXmlParser.py
Go to the documentation of this file.
1 ###############################################################################
2 #
3 # Package: NetMsgs
4 #
5 # File: NetMsgsXmlParser.py
6 #
7 
8 """
9 NetMsgs XML parser module.
10 """
11 
12 ## \file
13 ## \package NetMsgs.NetMsgsXmlParser
14 ##
15 ## $LastChangedDate: 2013-08-08 13:02:57 -0600 (Thu, 08 Aug 2013) $
16 ## $Rev: 3183 $
17 ##
18 ## \brief NetMsgs XML parser module.
19 ##
20 ## \todo Add brief elements to xdefs for better comments to generated language
21 ## constructs
22 ##
23 ## \sa
24 ## \htmlonly
25 ## <a href="../pydoc/NetMsgs.NetMsgsXmlParser.html">PyDoc Generated Documentation</a>
26 ## \endhtmlonly
27 ##
28 ## \author Robin Knight (robin.knight@roadnarrows.com)
29 ##
30 ## \copyright
31 ## \h_copy 2009-2017. RoadNarrows LLC.\n
32 ## http://www.roadnarrows.com\n
33 ## All Rights Reserved
34 ##
35 
36 # Permission is hereby granted, without written agreement and without
37 # license or royalty fees, to use, copy, modify, and distribute this
38 # software and its documentation for any purpose, provided that
39 # (1) The above copyright notice and the following two paragraphs
40 # appear in all copies of the source code and (2) redistributions
41 # including binaries reproduces these notices in the supporting
42 # documentation. Substantial modifications to this software may be
43 # copyrighted by their authors and need not follow the licensing terms
44 # described here, provided that the new terms are clearly indicated in
45 # all files where they apply.
46 #
47 # IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
48 # OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
49 # PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
50 # DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
51 # EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
52 # THE POSSIBILITY OF SUCH DAMAGE.
53 #
54 # THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
55 # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
56 # FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
57 # "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
58 # PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
59 #
60 ###############################################################################
61 
62 import os
63 import xml.parsers.expat as expat
64 import time
65 
66 import NetMsgsBase as nmBase
67 
68 #------------------------------------------------------------------------------
69 # CLASS: NetMsgsXmlParserError
70 #------------------------------------------------------------------------------
71 class NetMsgsXmlParserError(Exception):
72  """ XML Parser Exception Class. """
73 
74  def __init__(self, msg='XML Parser Error'):
75  """ Raise exception.
76 
77  Parameters:
78  msg - Exception message string.
79  """
80  Exception.__init__(self, msg)
81 
82 ##
83 
84 #-----------------------------------------------------------------------------
85 # CLASS: NetMsgsXmlParser
86 #-----------------------------------------------------------------------------
88  """ RoadNarrows Net Messages XML Parser Class.
89 
90  The NetMsgsXmlParser class parses a RoadNarrows netmsgs XML specification.
91  The parsed information is available to the calling program.
92 
93  XML Syntax:
94  <netmsgs>
95  <meta>
96  ...
97  </meta>
98  <field_types>
99  ...
100  </field_types>
101  <msg_types>
102  ...
103  </msg_types>
104  </netmsgs>
105  """
106 
107  def __init__(self, filename=None, debug=0, **kwargs):
108  """ Initialize NetMsgsXmlParser instance.
109 
110  Parameters:
111  filename - XML file name.
112  debug - Set debugging level: 0 == off, 1, 2, 3.
113  kwargs - Optional XML overrides:
114  encoding - Message encoding. One of itv flat.
115  endian - Byte order. One of big little native.
116  ns - Message namespace (name prefix).
117  brief - Brief description.
118  """
119  ## associated xml file name
120  self.mFileName = filename
121 
122  ## debug print at given <= level
123  self.mDebug = debug
124 
125  ## XML overrides
126  self.mXmlOverrides = {}
127  self.mXmlOverrides['encoding'] = kwargs.get('encoding', None)
128  self.mXmlOverrides['endian'] = kwargs.get('endian', None)
129  self.mXmlOverrides['ns'] = kwargs.get('ns', None)
130  self.mXmlOverrides['brief'] = kwargs.get('brief', None)
131 
132  if filename:
133  ## xml file base name
134  self.mBaseName = os.path.basename(filename)
135  else:
136  self.mBaseName = None
137 
138  ## xml tree starting at '_root'
139  self.XmlTree = {
140  '_root': [ 'netmsgs' ],
141  'netmsgs': [ 'meta', 'field_types', 'msg_types' ],
142  'meta': [ 'brief', 'ns', 'prologue', 'epilogue' ],
143  'field_types': [ 'ftypedef' ],
144  'ftypedef': [ 'fielddef' ],
145  'msg_types': [ 'msgdef' ],
146  'msgdef': [ 'fielddef', 'pad' ],
147  'fielddef': [ 'min', 'max', 'const', 'fielddef' ]
148  }
149 
150  ## XML element start callbacks
151  self.XmlCbStartElem = {
152  'netmsgs': self.XmlCbStartNetMsgs,
153  'meta': self.XmlCbStartSection,
154  'brief': None,
155  'ns': None,
156  'prologue': None,
157  'epilogue': None,
158  'field_types': self.XmlCbStartSection,
159  'ftypedef': self.XmlCbStartFTypeDef,
160  'msg_types': self.XmlCbStartSection,
161  'msgdef': self.XmlCbStartMsgDef,
162  'fielddef': self.XmlCbStartFieldDef,
163  'const': None,
164  'min': None,
165  'max': None,
166  'pad': self.XmlCbStartPad,
167  }
168 
169  ## XML element start callbacks
170  self.XmlCbEndElem = {
171  'netmsgs': None,
172  'meta': self.XmlCbEndSection,
173  'brief': self.XmlCbEndMetaData,
174  'ns': self.XmlCbEndMetaData,
175  'prologue': self.XmlCbEndMetaLang,
176  'epilogue': self.XmlCbEndMetaLang,
177  'field_types': self.XmlCbEndSection,
178  'ftypedef': self.XmlCbEndFTypeDef,
179  'msg_types': self.XmlCbEndSection,
180  'msgdef': self.XmlCbEndMsgDef,
181  'fielddef': self.XmlCbEndFieldDef,
182  'const': self.XmlCbEndFieldDefConst,
183  'min': self.XmlCbEndFieldDefMinMax,
184  'max': self.XmlCbEndFieldDefMinMax,
185  'pad': None,
186  }
187 
188  ## parsed and augmented database
189  self.mDB = {
190  'netmsgs': { 'encoding': 'itv', 'endian': 'big' },
191  'meta': { 'brief': "Net Messages",
192  'ns': "",
193  'c': {'prologue': "", 'epilogue': ""},
194  'h': {'prologue': "", 'epilogue': ""},
195  'python':{'prologue': "", 'epilogue': ""}},
196  'field_types': {nmBase.NMKeyOrder:[]},
197  'msg_types': {nmBase.NMKeyOrder:[]},
198  }
199 
200  # XML working state
201  self._XmlParser = None # xml parser
202  self._XmlElemStack = [] # xml element stack
203  self._XmlCurElem = None # current element name (top of stack)
204  self._XmlSection = '_root' # major section context
205  self._XmlFieldDefDepth = 0 # depth of recursive <fielddef> element
206  self._XmlElems = [] # full list of elements
207 
208  # DB working state
209  self._DbFieldDictStack = [] # field defs stack
210  self._DbCurFieldDict = None # working fielddef list
211 
212  # list of XML elements in preferred order
213  self._InitElemOList(self.XmlTree['_root'], self._XmlElems)
214  ##
215 
216  #--
217  def _InitElemOList(self, elemList, olist):
218  """ Make an ordered list of XML element names.
219 
220  Names are derieved from the XML tree.
221 
222  Parameters:
223  elemList - List of element names
224 
225  Return Value:
226  Orders element list.
227  """
228  for elem in elemList:
229  if elem not in olist:
230  olist += [elem]
231  if self.XmlTree.has_key(elem):
232  self._InitElemOList(self.XmlTree[elem], olist)
233  ##
234 
235 
236  #.............................................................................
237  # XML Get/Set Attribute Functions
238  #.............................................................................
239 
240  #--
241  def __getitem__(self, dbkey):
242  """ x.__getitem__(dbkey) <==> x[dbkey]
243 
244  Get database entry.
245  """
246  return self.mDB[dbkey]
247  ##
248 
249  #--
250  def __setitem__(self, dbkey, val):
251  """ x.__setitem__(dbkey, val) <==> x[dbkey]=val
252 
253  Set new or overwrite existing database entry.
254  """
255  self.mDB[dbkey] = val
256  ##
257 
258  #--
259  def GetDBData(self, dbkey):
260  """ Get database entry.
261 
262  Parameters:
263  dbkey - Parsed data key.
264 
265  Return Value:
266  Database data.
267  """
268  return self.mDB[dbkey]
269  ##
270 
271  #--
272  def GetDBDict(self):
273  """ Get full database dictionary.
274 
275  Return Value:
276  Dictionary.
277  """
278  return self.mDB
279  ##
280 
281  #--
282  def GetDBList(self):
283  """ Get the full list of database keys.
284 
285  Return Value:
286  List of pnames.
287  """
288  return self.mDB.keys()
289  ##
290 
291  #--
292  def GetElemList(self):
293  """ Get the full list of XML element names.
294 
295  The list is in preferred output order.
296 
297  Return Value:
298  List of element names.
299  """
300  return self._XmlElems
301  ##
302 
303  #--
304  def GetXMLFileName(self):
305  """ Get the NetMsgs XML file name.
306 
307  Return Value:
308  String.
309  """
310  return self.mFileName
311  ##
312 
313 
314  #.............................................................................
315  # XML Parsing and Validation
316  #.............................................................................
317 
318  #--
319  def ParseFile(self, filename):
320  """ Parse the Xml XML data specified in the given file.
321 
322  Parameters:
323  filename - README XML file name.
324  """
325  self.mFileName = filename
326  if filename: # xml file base name
327  self.mBaseName = os.path.basename(filename)
328  self.Parse()
329  ##
330 
331  #--
332  def Parse(self):
333  """ Parse the Xml XML data listed in the current file.
334  """
335  if not self.mFileName:
336  self.Error('No filename')
337  self.Debug(1, "Parsing RN NetMsgs XML file %s" % (self.mFileName))
338  try:
339  fp = open(self.mFileName, 'r')
340  except IOError, err:
341  self.Error(self.mFileName, err)
342  self.Reset()
343  self._XmlParser = expat.ParserCreate()
344  self._XmlParser.returns_unicode = False
345  #self._XmlParser.UseForeignDTD(True)
346  #self._XmlParser.ExternalEntityRefHandler = self.XmlHandlerDTD
347  #self._XmlParser.StartDoctypeDeclHandler = self.XmlHandlerStartDoctype
348  #self.EntityDeclHandler = self.XmlHandlerEntityDecl
349  #self._XmlParser.ElementDeclHandler = self.XmlHandlerElementDecl
350  self._XmlParser.StartElementHandler = self.XmlHandlerStartElem
351  self._XmlParser.CharacterDataHandler = self.XmlHandlerCharData
352  self._XmlParser.EndElementHandler = self.XmlHandlerEndElem
353  self._XmlParser.CommentHandler = self.XmlHandlerComment
354  try:
355  self._XmlParser.ParseFile(fp)
356  except expat.ExpatError as e:
357  self.ExpatError(expat.ErrorString(e.code))
358  self.PostParse()
359  ##
360 
361  #--
362  def Reset(self):
363  """ Reset the XML parser.
364  """
365  if self._XmlParser is not None:
366  del self._XmlParser
367  self._XmlParser = None
368  self._XmlElemStack = []
369  self._XmlCurElem = None
370  self._XmlSection = '_root'
371  self._XmlFieldDefDepth = 0
372  self._DbFieldDictStack = []
373  self._DbCurFieldDict = None
374  ##
375 
376  #--
377  def PostParse(self):
378  """ Post-parse configuration and validation. """
379  for k,v in self.mXmlOverrides.iteritems():
380  if v is None:
381  continue
382  elif k == 'encoding':
383  if v not in nmBase.NMEncoding:
384  self.XmlError("XML Override: %s='%s'" % (k, v),
385  "unknown message encoding")
386  else:
387  self.mDB['netmsgs'][k] = v
388  elif k == 'endian':
389  if v not in nmBase.NMEndian:
390  self.XmlError("XML Override: %s='%s'" % (k, v),
391  "unknown message field byte order")
392  else:
393  self.mDB['netmsgs'][k] = v
394  elif k == 'ns':
395  if not nmBase.IsIdentifier(v):
396  self.XmlError("XML Override: %s='%s'" % (k, v),
397  "namespace value must be an identifier")
398  else:
399  self.mDB['meta'][k] = v
400  elif k == 'brief':
401  self.mDB['meta'][k] = v
402  else:
403  self.XmlWarning("XML Override: %s" % (k, v),
404  "unknown override")
405  ##
406 
407 
408  #.............................................................................
409  # XML Parser Callback Handlers
410  #.............................................................................
411 
412  #--
413  def XmlHandlerDTD(self, context, base, systemId, publicId):
414  """ XML Parser handler called back at start of DTD processing.
415  """
416  self.XmlDebug(1, "start-of-dtd-parse",
417  "base=%s" % repr(base),
418  "systemId=%s" % repr(systemId),
419  "publicId=%s" % repr(publicId))
420  self._XmlParser.ExternalEntityParserCreate(context)
421  return 0 # error
422  ##
423 
424  #--
425  def XmlHandlerStartDoctype(self, doctypeName, systemId, publicId,
426  has_internal_subset):
427  """ XML Parser handler called back at start of DOCTYPE processing.
428  """
429  self.XmlDebug(1, "start-of-DOCTYPE",
430  "doctypeName=%s" % repr(doctypeName),
431  "systemId=%s" % repr(systemId),
432  "publicId=%s" % repr(publicId),
433  "has_internal=%s" % repr(has_internal_subset))
434  ##
435 
436  #--
437  def XmlHandlerEntityDecl(entityName, is_parameter_entity, value, base,
438  systemId, publicId, notationName):
439  """ XML Parser handler called back at start of DTD ENTITY processing.
440  """
441  self.XmlDebug(1, "entity-decl",
442  "entityName=%s" % repr(entityName))
443  ##
444 
445  #--
446  def XmlHandlerElementDecl(self, name, model):
447  """ XML Parser handler called back at start of DTD ELEMENT processing.
448  """
449  self.XmlDebug(1, "element-decl",
450  "name=%s" % repr(name),
451  "model=%s" % repr(model))
452  ##
453 
454  #--
455  def XmlHandlerStartElem(self, elem, attrs):
456  """ XML Parser handler called back at start of element.
457 
458  Parameters:
459  elem - Element name.
460  attrs - Dictionary of element attributes.
461  """
462  self.XmlDebug(1, "start-of-element", "<%s> attrs=%s" % (elem, repr(attrs)))
463  if elem in self._XmlElems:
464  self.PushElem(elem, attrs)
465  cb = self.XmlCbStartElem.get(elem)
466  if cb:
467  cb(elem, **attrs)
468  else:
469  self.XmlError("<%s>" % (elem), "unrecognized element")
470  ##
471 
472  #--
473  def XmlHandlerEndElem(self, elem):
474  """ XML Parser handler called back at end of element.
475 
476  The associated database element(s) are set with the converted data.
477  The data must conform to the requirements of the element.
478 
479  Parameters:
480  elem - Element name.
481  """
482  self.XmlDebug(1, "end-of-element", "<%s> data=" % (elem))
483  if elem == self._XmlCurElem['elem']:
484  elem = self._XmlCurElem['elem']
485  attrs = self._XmlCurElem['attrs']
486  data = self._XmlCurElem['data'].strip()
487  self.XmlDebug(1, "%s" % (data))
488  cb = self.XmlCbEndElem.get(elem)
489  if cb:
490  cb(elem, data, **attrs)
491  self.PopElem()
492  else:
493  self.Error("Bug: Lost track of elements: Expected <%s>, got <%s>" % \
494  (self._XmlCurElem['elem'], elem))
495  ##
496 
497  #--
498  def XmlHandlerCharData(self, data):
499  """ XML Parser handler called back for each line of element data.
500 
501  Parameters:
502  data - Unstructured element data.
503  """
504  self.XmlDebug(2, "char data:", repr(data))
505  self._XmlCurElem['data'] += data
506  ##
507 
508  #--
509  def XmlHandlerComment(self, comment):
510  """ XML Parser handler called back for each end of a comment block.
511 
512  Parameters:
513  comment - Comment text sans '<!-' and '-->'.
514  """
515  self.XmlDebug(1, "comment:", repr(comment))
516  ##
517 
518  def XmlCbStartNetMsgs(self, elem, **attrs):
519  """ Start-Of-Element callback for the 'netmsgs' top element.
520 
521  Parameters:
522  elem - Element name.
523  attrs - Element attributes.
524  """
525  encoding = attrs.get('encoding', 'itv').lower()
526  endian = attrs.get('endian', 'big').lower()
527  if encoding not in nmBase.NMEncoding:
528  self.XmlError("<%s encoding='%s'>" % (elem, encoding),
529  "unknown message encoding")
530  if endian not in nmBase.NMEndian:
531  self.XmlError("<%s endian='%s'>" % (elem, endian),
532  "unknown message field byte order")
533  self.mDB[elem]['encoding'] = encoding
534  self.mDB[elem]['endian'] = endian
535  self._XmlSection = elem
536  ##
537 
538  def XmlCbStartSection(self, elem, **attrs):
539  """ Start-Of-Element callback for a major XML section.
540 
541  Parameters:
542  elem - Element name.
543  attrs - Element attributes.
544  """
545  self._XmlSection = elem
546  ##
547 
548  def XmlCbEndSection(self, elem, data, **attrs):
549  """ End-Of-Element callback for a major XML section.
550 
551  Parameters:
552  elem - Element name.
553  data - Element data.
554  attrs - Element attributes.
555  """
556  self._XmlSection = 'netmsgs'
557  ##
558 
559  #--
560  def XmlCbEndMetaData(self, elem, data, **attrs):
561  """ End Callback for the 'meta' general data sub-elements.
562 
563  The associated XML parser database entries are updated with the current
564  parsed data.
565 
566  Parameters:
567  elem - Element name.
568  data - Element data.
569  attrs - Element attributes.
570  """
571  if elem == 'ns':
572  if not nmBase.IsIdentifier(data):
573  self.XmlError("<%s>%s</%s>" % (elem, data, elem),
574  "namespace value must be an identifier")
575  self.mDB['meta'][elem] = data
576  ##
577 
578  #--
579  def XmlCbEndMetaLang(self, elem, data, **attrs):
580  """ End-Of-Element callback for the 'meta' language-specific data
581  sub-elements.
582 
583  The associated XML parser database entries are updated with the current
584  parsed data.
585 
586  Parameters:
587  elem - Element name.
588  data - Element data.
589  attrs - Element attributes.
590  """
591  lang = attrs.get('lang')
592  if not lang:
593  self.XmlError("<%s>" % (elem),
594  "required '%s' attribute not specified." % (attr))
595  self.mDB['meta'][lang][elem] = data
596  ##
597 
598  #--
599  def XmlCbStartFTypeDef(self, elem, **attrs):
600  """ Start-Of-Element callback for the 'ftypedef' element.
601 
602  The associated XML parser database entries are updated with the current
603  parsed data.
604 
605  Parameters:
606  elem - Element name.
607  attrs - Element attributes.
608  """
609  ftid = self.XmlChkTokenId(elem, 'ftid', attrs.get('ftid'))
610  ftype, vtype = self.XmlChkTokenFType(elem, attrs.get('ftype'))
611  fsize = attrs.get('size')
612  if self.mDB['field_types'].has_key(ftid):
613  self.XmlError("<%s ftid='%s'>" % (elem, ftid),
614  "field type id already exists.")
615  self.mDB['field_types'][nmBase.NMKeyOrder] += [ftid]
616  self.mDB['field_types'][ftid] = {'disposition': 'active', 'ftype': ftype}
617  if fsize:
618  if ftype in ['string', 'vector']:
619  self.mDB['field_types'][ftid]['size'] = fsize
620  else:
621  self.XmlWarning("<%s ftid='%s' size='%s'>" % (elem, ftid, fsize),
622  "size attribute ignored.")
623  if ftype == 'vector':
624  self.mDB['field_types'][ftid]['vtype'] = vtype
625  elif ftype == 'struct':
626  self.mDB['field_types'][ftid]['fields'] = {nmBase.NMKeyOrder: []}
627  self.PushFieldDict(self.mDB['field_types'][ftid]['fields'])
628  ##
629 
630  #--
631  def XmlCbEndFTypeDef(self, elem, data, **attrs):
632  """ End-Of-Element callback for the 'ftypedef' element.
633 
634  The associated XML parser database entries are updated with the current
635  parsed data.
636 
637  Parameters:
638  elem - Element name.
639  data - Element data.
640  attrs - Element attributes.
641  """
642  self.PopFieldDict()
643  ##
644 
645  #--
646  def XmlCbStartMsgDef(self, elem, **attrs):
647  """ Start-Of-Element callback for the 'msgdef' element.
648 
649  The associated XML parser database entries are updated with the current
650  parsed data.
651 
652  Parameters:
653  elem - Element name.
654  attrs - Element attributes.
655  """
656  msgid = self.XmlChkTokenId(elem, 'msgid', attrs.get('msgid'))
657  if self.mDB['msg_types'].has_key(msgid):
658  self.XmlError("<%s msgid='%s'>" % (elem, msgid),
659  "messsage definition id already exists.")
660  dispo = self.XmlChkTokenDispo(elem, attrs.get('disposition'))
661  self.mDB['msg_types'][nmBase.NMKeyOrder] += [msgid]
662  self.mDB['msg_types'][msgid] = {'disposition': dispo,
663  'ftype': 'struct',
664  'fields': {nmBase.NMKeyOrder:[]} }
665  self.PushFieldDict(self.mDB['msg_types'][msgid]['fields'])
666  ##
667 
668  #--
669  def XmlCbEndMsgDef(self, elem, data, **attrs):
670  """ End-Of-Element callback for the 'msgdef' element.
671 
672  The associated XML parser database entries are updated with the current
673  parsed data.
674 
675  Parameters:
676  elem - Element name.
677  data - Element data.
678  attrs - Element attributes.
679  """
680  self.PopFieldDict()
681  ##
682 
683  #--
684  def XmlCbStartFieldDef(self, elem, **attrs):
685  """ Start-Of-Element callback for the 'fielddef' element.
686 
687  The associated XML parser database entries are updated with the current
688  parsed data.
689 
690  Parameters:
691  elem - Element name.
692  attrs - Element attributes.
693  """
694  self._XmlFieldDefDepth += 1
695  pid, pattr = self.XmlFieldDefContext()
696  if pattr['ftype'] != 'struct':
697  self.XmlError("<%s>" % (elem),
698  "field definition not allowed in current context.")
699  fname = self.XmlChkTokenId(elem, 'fname', attrs.get('fname'))
700  ftype, vtype = self.XmlChkTokenFType(elem, attrs.get('ftype'))
701  fsize = attrs.get('size')
702  dispo = self.XmlChkTokenDispo(elem, attrs.get('disposition'))
703  if self._DbCurFieldDict.has_key(fname):
704  self.XmlError("<%s fname='%s'>" % (elem, fname),
705  "field definition name already exists in current context.")
706  self._DbCurFieldDict[nmBase.NMKeyOrder] += [fname]
707  self._DbCurFieldDict[fname] = {'ftype': ftype}
708  if fsize:
709  if ftype in ['string', 'vector']:
710  self._DbCurFieldDict[fname]['size'] = fsize
711  else:
712  self.XmlWarning("<%s fname='%s' size='%s'>" % (elem, fname, fsize),
713  "size attribute ignored.")
714  self._DbCurFieldDict[fname]['disposition'] = dispo
715  if ftype == 'vector':
716  self._DbCurFieldDict[fname]['vtype'] = vtype
717  elif ftype == 'struct':
718  self._DbCurFieldDict[fname]['fields'] = {nmBase.NMKeyOrder:[]}
719  self.PushFieldDict(self._DbCurFieldDict[fname]['fields'])
720  ##
721 
722  #--
723  def XmlCbEndFieldDef(self, elem, data, **attrs):
724  """ End-Of-Element callback for the 'fielddef' element.
725 
726  The associated XML parser database entries are updated with the current
727  parsed data.
728 
729  Parameters:
730  elem - Element name.
731  data - Element data.
732  attrs - Element attributes.
733  """
734  self._XmlFieldDefDepth -= 1
735  fname = attrs.get('fname')
736  while len(self._DbFieldDictStack) > self._XmlFieldDefDepth+1:
737  self.PopFieldDict()
738  ##
739 
740  #--
741  def XmlCbEndFieldDefConst(self, elem, data, **attrs):
742  """ End-Of-Element callback for the 'fielddef' 'const' sub-element.
743 
744  The associated XML parser database entries are updated with the current
745  parsed data.
746 
747  Parameters:
748  elem - Element name.
749  attrs - Element attributes.
750  """
751  pfname, pattr = self.XmlFieldDefContext()
752  pftype = pattr['ftype']
753  if self.IsSimple(pftype) or pftype == 'string':
754  self._DbCurFieldDict[pfname][elem] = data
755  elif pftype == 'vector' and \
756  ( self.IsSimple(self._DbCurFieldDict[pfname]['vtype']) or \
757  self._DbCurFieldDict[pfname]['vtype'] == 'string' ):
758  self._DbCurFieldDict[pfname][elem] = data
759  else:
760  self.XmlWarning("<%s>" % (elem),
761  "element ignored in <fielddef fname='%s'> context." % (pfname))
762  ##
763 
764  #--
765  def XmlCbEndFieldDefMinMax(self, elem, data, **attrs):
766  """ End-Of-Element callback for the 'fielddef' min/max limits sub-elements.
767 
768  The associated XML parser database entries are updated with the current
769  parsed data.
770 
771  Parameters:
772  elem - Element name.
773  data - Element data.
774  attrs - Element attributes.
775  """
776  pfname, pattr = self.XmlFieldDefContext()
777  pftype = pattr['ftype']
778  if self.IsSimple(pftype):
779  self._DbCurFieldDict[pfname][elem] = data
780  elif pftype == 'vector' and \
781  self.IsSimple(self._DbCurFieldDict[pfname]['vtype']):
782  self._DbCurFieldDict[pfname][elem] = data
783  else:
784  self.XmlWarning("<%s>" % (elem),
785  "element ignored in <fielddef fname='%s'> context." % (pfname))
786  ##
787 
788  #--
789  def XmlCbStartPad(self, elem, **attrs):
790  """ Start-Of-Element callback for the 'pad' element.
791 
792  The associated XML parser database entries are updated with the current
793  parsed data.
794 
795  Parameters:
796  elem - Element name.
797  attrs - Element attributes.
798  """
799  inst = len(self._DbCurFieldDict[nmBase.NMKeyOrder])
800  count = attrs.get('count', '1')
801  fname = "%s%d" % (nmBase.NMKeyPad, inst)
802  self._DbCurFieldDict[nmBase.NMKeyOrder] += [fname]
803  self._DbCurFieldDict[fname] = {'ftype':'pad', 'count': count}
804  ##
805 
806 
807  #.............................................................................
808  # XML Write Functions
809  #.............................................................................
810 
811  #--
812  def WriteXmlFile(self, filename, comment=None):
813  """ Create a Product XML file from the given parsed or set data.
814 
815  Parameters:
816  filename - Product XML file name.
817  comment - Comment string.
818  """
819  fp = open(filename, 'w')
820  self.WriteXml(fp, comment)
821  ##
822 
823  #--
824  def WriteXml(self, fp, comment=None):
825  """ Create a Product XML file from the given parsed or set data.
826 
827  Parameters:
828  fp - Opened for writing file pointer.
829  comment - Comment string.
830  """
831  fp.write("<!--\n")
832  if comment:
833  fp.write(" - ")
834  fp.write("%s\n" % (comment))
835  fp.write(" - ")
836  now = time.localtime()
837  fp.write("%d.%02d.%02d %02d:%02d:%02d\n" % \
838  ( now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min,
839  now.tm_sec))
840  fp.write(" -->\n")
841  self.WriteXmlTree(fp, 0, '_root', self.XmlTree['_root'])
842  fp.flush()
843  fp.close()
844  ##
845 
846  #--
847  def WriteXmlTree(self, fp, level, elemParent, elemList):
848  """ Write out XML tree.
849 
850  Parameters:
851  fp - Opened for writing file pointer.
852  level - element level (depth)
853  elemList - element level (depth)
854  """
855  pass
856  ##
857 
858 
859  #.............................................................................
860  # DB Print Functions
861  #.............................................................................
862 
863  #--
864  def PrettyPrintDB(self, comment=None):
865  """ Pretty print database dictionary of parsed XML values. """
866  now = time.localtime()
867 
868  print "#"
869  if comment:
870  print "# %s" % (comment)
871  print "# %s database dump." % (self.__class__)
872  print "# Input XML file: %s" % (self.mFileName)
873  print "# Date: %d.%02d.%02d %02d:%02d:%02d" % \
874  (now.tm_year, now.tm_mon, now.tm_mday,
875  now.tm_hour, now.tm_min, now.tm_sec)
876  print "#"
877 
878  sections = self.mDB.keys()
879 
880  dbkey = 'netmsgs'
881  print "%s:\n{" % (dbkey)
882  print " encoding: %s" % (self.mDB[dbkey]['encoding'])
883  print " endian: %s" % (self.mDB[dbkey]['endian'])
884  print '}'
885  sections.remove(dbkey)
886 
887  dbkey = 'meta'
888  print "%s:\n{" % (dbkey)
889  print " brief: %s" % (repr(self.mDB[dbkey]['brief']))
890  print " ns: %s" % (repr(self.mDB[dbkey]['ns']))
891  for lang in ['h', 'c', 'python']:
892  print " %s:prologue: %s" % (lang, self.mDB[dbkey][lang]['prologue'])
893  print " %s:epilogue: %s" % (lang, self.mDB[dbkey][lang]['epilogue'])
894  print '}'
895  sections.remove(dbkey)
896 
897  dbkey = 'field_types'
898  print "%s:\n{" % (dbkey)
899  print " %s: %s" % \
900  (nmBase.NMKeyOrder, repr(self.mDB[dbkey][nmBase.NMKeyOrder]))
901  for ftid in self.mDB[dbkey][nmBase.NMKeyOrder]:
902  self.PrettyPrintDBFieldDef(2, ftid, self.mDB[dbkey][ftid])
903  print '}'
904  sections.remove(dbkey)
905 
906  dbkey = 'msg_types'
907  print "%s:\n{" % (dbkey)
908  print " %s: %s" % \
909  (nmBase.NMKeyOrder, repr(self.mDB[dbkey][nmBase.NMKeyOrder]))
910  for msgid in self.mDB[dbkey][nmBase.NMKeyOrder]:
911  self.PrettyPrintDBFieldDef(2, msgid, self.mDB[dbkey][msgid])
912  print '}'
913  sections.remove(dbkey)
914 
915  # application specific db augments
916  for dbkey in sections:
917  print "%s:" % (dbkey)
918  print " %s" % (repr(self.mDB[dbkey]))
919  ##
920 
921  #--
922  def PrettyPrintDBFields(self, indent, fields):
923  """ Pretty print database fields sub-dictionary of parsed XML values.
924 
925  Parameters:
926  indent - Indentation.
927  fields - mDB[...]['fields'] sub-dictionary.
928  """
929  dbkey = 'fields'
930  print "%*s%s:" % (indent, '', dbkey)
931  print "%*s{" % (indent, '')
932  indent += 2
933  print "%*s%s: %s" % (indent, '', \
934  nmBase.NMKeyOrder, repr(fields[nmBase.NMKeyOrder]))
935  for fname in fields[nmBase.NMKeyOrder]:
936  self.PrettyPrintDBFieldDef(indent, fname, fields[fname])
937  indent -= 2
938  print "%*s}" % (indent, '')
939  ##
940 
941  #--
942  def PrettyPrintDBFieldDef(self, indent, fname, fielddef):
943  """ Pretty print database fielddef sub-dictionary of parsed XML values.
944 
945  Parameters:
946  indent - Indentation.
947  fields - mDB[...]['fields'] sub-dictionary.
948  """
949  sections = fielddef.keys()
950  if 'fields' in sections:
951  sections.remove('fields')
952  print "%*s%s:" % (indent, '', fname)
953  print "%*s{" % (indent, '')
954  indent += 2
955  for k in ['ftype', 'vtype', 'size', 'const', 'min', 'max', 'count']:
956  if fielddef.has_key(k):
957  self.PrettyPrintVal(indent, k, fielddef[k])
958  sections.remove(k)
959  for k in sections:
960  self.PrettyPrintVal(indent, k, fielddef[k])
961  if fielddef.has_key('fields'):
962  self.PrettyPrintDBFields(indent, fielddef['fields'])
963  indent -= 2
964  print "%*s}" % (indent, '')
965  ##
966 
967  #--
968  def PrettyPrintVal(self, indent, name, val):
969  """ Pretty print value.
970 
971  Parameters:
972  indent - Indentation
973  name - name
974  value - dictionary or other value type.
975  """
976  print "%*s%s: " % (indent, '', name),
977  if type(val) == dict:
978  print "\n%*s{" % (indent, '')
979  for k,v in val.iteritems():
980  self.PrettyPrintVal(indent+2, k, v)
981  print "%*s}" % (indent, '')
982  else:
983  print repr(val)
984  ##
985 
986 
987  #.............................................................................
988  # XML Utilities
989  #.............................................................................
990 
991  #--
992  def XmlChkTokenId(self, elem, attr, id):
993  """ Parse and validate XML element id attribute.
994 
995  Parameters:
996  elem - Element name value.
997  attr - Element attribute name.
998  id - Element attribute value.
999 
1000  Return:
1001  id
1002  """
1003  if not id:
1004  self.XmlError("<%s>" % (elem),
1005  "required '%s' attribute not specified." % (attr))
1006  elif not nmBase.IsIdentifier(id):
1007  self.XmlError("<%s %s='%s'>" % (elem, attr, id),
1008  "'%s' not an identifier." % (attr))
1009  return id
1010  ##
1011 
1012  #--
1013  def XmlChkTokenFType(self, elem, ftype):
1014  """ Parse and validate XML element ftype attribute.
1015 
1016  Parameters:
1017  elem - Element name value.
1018  ftype - Element ftype raw attribute value.
1019 
1020  Return:
1021  Returns ('vector', vtype) if vector.
1022  Returns (ftype, None) otherwise.
1023  """
1024  if not ftype:
1025  self.XmlError("<%s>" % (elem),
1026  "required 'ftype' attribute not specified.")
1027  ftype, vtype = self.XmlTokenFType(ftype)
1028  if vtype:
1029  if not nmBase.NMBuiltInFieldTypes.has_key(vtype) and \
1030  not self.mDB['field_types'].has_key(vtype):
1031  self.XmlError("<%s ftype='%s%s'>" % \
1032  (elem, vtype, nmBase.NMVectorSuffix),
1033  "vector field type is unknown.")
1034  else:
1035  if not nmBase.NMBuiltInFieldTypes.has_key(ftype) and \
1036  not self.mDB['field_types'].has_key(ftype):
1037  self.XmlError("<%s ftype='%s'>" % (elem, ftype),
1038  "field type is unknown.")
1039  return ftype, vtype
1040  ##
1041 
1042  #--
1043  def XmlTokenFType(self, token):
1044  """ Parse XML element ftype token.
1045 
1046  Parameters:
1047  token - Element ftype token raw value.
1048 
1049  Return:
1050  Returns ('vector', vtype) if vector.
1051  Returns (ftype, None) otherwise.
1052  """
1053  if not token:
1054  ftype = None
1055  vtype = None
1056  elif token[-2:] == nmBase.NMVectorSuffix:
1057  ftype = 'vector'
1058  vtype = token[:-2]
1059  else:
1060  ftype = token
1061  vtype = None
1062  ftype = nmBase.NMAliasMap.get(ftype, ftype)
1063  vtype = nmBase.NMAliasMap.get(vtype, vtype)
1064  return (ftype, vtype)
1065  ##
1066 
1067  #--
1068  def XmlChkTokenDispo(self, elem, dispo):
1069  """ Parse and validate XML element 'disposition' attribute.
1070 
1071  Parameters:
1072  elem - Element name value.
1073  dispo - Element attribute value.
1074 
1075  Return:
1076  dispo
1077  """
1078  enity = ['active', 'deprecated']
1079  if not dispo:
1080  return 'active'
1081  elif dispo not in enity:
1082  self.XmlError("<%s %s='%s'>" % (elem, 'disposition', dispo),
1083  "attribute value not one of: %s" % repr(enity))
1084  return dispo
1085  ##
1086 
1087  #--
1089  """ Get current field definition context.
1090 
1091  Return:
1092  Returns (pid, pinfo) - the parent element id/name and parent
1093  (implicit) field attributes.
1094  """
1095  elemParen = self.GetParentElem()
1096  if elemParen['elem'] == 'ftypedef': # <ftypedef> field type
1097  pid = elemParen['attrs']['ftid']
1098  pftype = elemParen['attrs']['ftype']
1099  elif elemParen['elem'] == 'msgdef': # <msgdef> implicit structure
1100  pid = elemParen['attrs']['msgid']
1101  pftype = 'struct'
1102  elif elemParen['elem'] == 'fielddef': # <fielddef> field type
1103  pid = elemParen['attrs']['fname']
1104  pftype = elemParen['attrs']['ftype']
1105  else:
1106  pid = None
1107  pftype = None
1108  pftype, pvtype = self.XmlTokenFType(pftype)
1109  return pid, {'ftype': pftype, 'vtype': pvtype}
1110  ##
1111 
1112  #--
1113  def IsSimple(self, ftype):
1114  """ Returns True (False) is field type is (not) simple.
1115 
1116  Parameters:
1117  ftype - (Derived) field type.
1118  """
1119  if nmBase.NMBuiltInFieldTypes.has_key(ftype):
1120  if nmBase.NMBuiltInFieldTypes[ftype]['comp'] == 'simple':
1121  return True
1122  else:
1123  return False
1124  while self.mDB['field_types'].has_key(ftype):
1125  ftype = self.mDB['field_types'][ftype]['ftype']
1126  if nmBase.NMBuiltInFieldTypes.has_key(ftype):
1127  if nmBase.NMBuiltInFieldTypes[ftype]['comp'] == 'simple':
1128  return True
1129  else:
1130  return False
1131  return False
1132  ##
1133 
1134  #--
1135  def PushElem(self, elem, attrs):
1136  """ Push element name on stack of elements.
1137 
1138  Parameters:
1139  elem - Element name.
1140  attrs - Element attributes.
1141  """
1142  if len(self._XmlElemStack) > 0:
1143  elemParent = self._XmlElemStack[-1]['elem']
1144  else:
1145  elemParent = '_root'
1146  if elem not in self.XmlTree[elemParent]:
1147  self.XmlError("<%s>" % (elem),
1148  "element not a valid child element of <%s>." % (elemParent))
1149  self._XmlElemStack += [{'elem':elem, 'attrs':attrs, 'data':''}]
1150  self._XmlCurElem = self._XmlElemStack[-1]
1151  self.XmlDebug(3, "elem stack push:", repr(self._XmlCurElem))
1152  ##
1153 
1154  #--
1155  def PopElem(self):
1156  """ Pop element from stack of elements.
1157  """
1158  if len(self._XmlElemStack) > 0:
1159  self._XmlElemStack = self._XmlElemStack[0:-1]
1160  if len(self._XmlElemStack) > 0:
1161  self._XmlCurElem = self._XmlElemStack[-1]
1162  else:
1163  self._XmlCurElem = None
1164  self.XmlDebug(3, "elem stack pop:", repr(self._XmlCurElem))
1165  ##
1166 
1167  #--
1168  def PushFieldDict(self, fielddict):
1169  """ Push field definitions dictionary on top of stack."
1170 
1171  Parameters:
1172  fielddict - Field definitions dictionary.
1173  """
1174  self._DbFieldDictStack += [fielddict]
1175  self._DbCurFieldDict = fielddict
1176  self.XmlDebug(3, "fielddict stack push:", repr(self._DbCurFieldDict))
1177  ##
1178 
1179  #--
1180  def PopFieldDict(self):
1181  """ Pop field definitions dictionary from top of stack.
1182  """
1183  if len(self._DbFieldDictStack ) > 0:
1184  self._DbFieldDictStack = self._DbFieldDictStack[0:-1]
1185  if len(self._DbFieldDictStack ) > 0:
1186  self._DbCurFieldDict = self._DbFieldDictStack[-1]
1187  else:
1188  self._DbCurFieldDict = None
1189  self.XmlDebug(3, "fielddict stack pop:", repr(self._DbCurFieldDict))
1190  ##
1191 
1192  #--
1193  def GetParentElem(self):
1194  """ Get the parent element of current top element.
1195  """
1196  if len(self._XmlElemStack) > 1:
1197  return self._XmlElemStack[-2]
1198  else:
1199  return {}
1200  ##
1201 
1202  #--
1204  """ Get the parent element's name of current top element.
1205  """
1206  if len(self._XmlElemStack) > 1:
1207  return self._XmlElemStack[-2]['elem']
1208  else:
1209  return None
1210  ##
1211 
1212  #--
1213  def XmlWarning(self, *args):
1214  """ Print XML syntax warning.
1215 
1216  Parameters:
1217  *args - List of warning message arguments.
1218  """
1219  wmsg = "Warning: %s[L%d,C%d]" % \
1220  (self.mBaseName,
1221  self._XmlParser.CurrentLineNumber,
1222  self._XmlParser.CurrentColumnNumber)
1223  for a in args:
1224  wmsg += ": %s" %(a)
1225  print wmsg
1226  ##
1227 
1228  #--
1229  def ExpatError(self, *args):
1230  """ Raise XML parser error on expat parser error.
1231 
1232  Parameters:
1233  *args - List of error message arguments.
1234  """
1235  emsg = "%s[L%d,C%d]" % \
1236  (self.mBaseName,
1237  self._XmlParser.ErrorLineNumber,
1238  self._XmlParser.ErrorColumnNumber)
1239  for a in args:
1240  emsg += ": %s" %(a)
1241  raise NetMsgsXmlParserError(emsg)
1242  ##
1243 
1244  #--
1245  def XmlError(self, *args):
1246  """ Raise XML parser error on XML syntax or semanitc error.
1247 
1248  Parameters:
1249  *args - List of warning message arguments.
1250  """
1251  emsg = "%s[L%d,C%d]" % \
1252  (self.mBaseName,
1253  self._XmlParser.CurrentLineNumber,
1254  self._XmlParser.CurrentColumnNumber)
1255  for a in args:
1256  emsg += ": %s" %(a)
1257  raise NetMsgsXmlParserError(emsg)
1258  ##
1259 
1260  #--
1261  def Error(self, *args):
1262  """ Raise XML parser error on general error.
1263 
1264  Parameters:
1265  *args - List of error message arguments.
1266  """
1267  if self.mBaseName:
1268  emsg = "%s" % (self.mBaseName)
1269  else:
1270  emsg = ''
1271  for a in args:
1272  emsg += ": %s" %(a)
1273  raise NetMsgsXmlParserError(emsg)
1274  ##
1275 
1276  #--
1277  def XmlDebug(self, level, *args):
1278  """ Print XML debugging info.
1279 
1280  Parameters:
1281  level - Debugging level.
1282  *args - List of debug message arguments.
1283  """
1284  if level > self.mDebug:
1285  return
1286  dmsg = "DBG: %s[L%d,C%d]" % \
1287  (self.mBaseName,
1288  self._XmlParser.CurrentLineNumber,
1289  self._XmlParser.CurrentColumnNumber)
1290  for a in args:
1291  dmsg += ": %s" %(a)
1292  print dmsg
1293  ##
1294 
1295  #--
1296  def Debug(self, level, *args):
1297  """ Print debugging info.
1298 
1299  Parameters:
1300  level - Debugging level.
1301  *args - List of debug message arguments.
1302  """
1303  if level > self.mDebug:
1304  return
1305  dmsg = 'DBG'
1306  for a in args:
1307  dmsg += ": %s" %(a)
1308  print dmsg
1309  ##
1310 ##
1311 
1312 
1313 #-------------------------------------------------------------------------------
1314 # Unit Test Main
1315 #-------------------------------------------------------------------------------
1316 if __name__ == '__main__':
1317  """ Unit Test """
1318 
1319  import sys
1320  import getopt
1321 
1322  ## command name
1323  _Argv0 = __file__
1324 
1325  #--
1326  class UTUsage(Exception):
1327  """ Command-Line Options Usage Exception Class. """
1328  def __init__(self, msg):
1329  """ Raise usage excpetion
1330 
1331  Parameters:
1332  msg - Error message string.
1333  """
1334  ## error message attribute
1335  self.msg = msg
1336  ##
1337 
1338  #--
1339  def UTPrintUsageErr(emsg):
1340  """ Print Error Usage Message.
1341 
1342  Parameters:
1343  msg - Error message string.
1344  """
1345  if emsg:
1346  print "%s: %s" % (_Argv0, emsg)
1347  else:
1348  print "%s: error" % (_Argv0)
1349  print "Try '%s --help' for more information." % (_Argv0)
1350  ##
1351 
1352  #--
1354  """ Print Command-Line Usage Message. """
1355  print """
1356 usage: %s [OPTIONS] <xmlfile>
1357 
1358  %s --help
1359  """ % (_Argv0, _Argv0)
1360  print """Options and arguments:
1361  -d, --debug=<level> : Debug level. One of: 0 1 2 3
1362  Default: 0 (off)
1363  -o, --overrides=<list> : XML overrides. List of form name=value,...
1364  Supported overrides:
1365  encoding, endian, ns, brief
1366 
1367  -h, --help : Display this help and exit.
1368  """
1369  ##
1370 
1371  #--
1372  def UTGetOptions(argv=None, **kwargs):
1373  """ Get Main Options
1374 
1375  Parameters:
1376  argv - Argument list. If not None, the overrides command-line
1377  arguments.
1378  kwargs - Keyword argument list.
1379  """
1380  global _Argv0
1381 
1382  if argv is None:
1383  argv = sys.argv
1384 
1385  _Argv0 = kwargs.get('argv0', __file__)
1386 
1387  # defaults
1388  kwargs['debug'] = 0
1389 
1390  # parse command-line options
1391  try:
1392  try:
1393  opts, args = getopt.getopt(argv[1:], "?hd:o:",
1394  ['help', 'debug=', "overrides=", ''])
1395  except getopt.error, msg:
1396  raise UTUsage(msg)
1397  for opt, optarg in opts:
1398  if opt in ('-h', '--help', '-?'):
1399  UTPrintUsage()
1400  sys.exit(0)
1401  elif opt in ('-d', '--debug'):
1402  try:
1403  kwargs['debug'] = int(optarg)
1404  except ValueError:
1405  raise UTUsage("%s %s: not an integer value" % (opt, optarg))
1406  elif opt in ('-o', '--overrides'):
1407  overrides = optarg.split(',')
1408  for entry in overrides:
1409  try:
1410  name,value = entry.split('=')
1411  name = name.strip()
1412  value = value.strip()
1413  kwargs[name] = value
1414  except:
1415  raise UTUsage("%s %s: bad syntax" % (opt, repr(optarg)))
1416  except UTUsage, err:
1417  UTPrintUsageErr(err.msg)
1418  sys.exit(2)
1419 
1420  if len(args) < 1:
1421  UTPrintUsageErr("No input xml file specified")
1422  sys.exit(2)
1423  else:
1424  kwargs['filename'] = args[0]
1425 
1426  return kwargs
1427  ##
1428 
1429  #--
1430  def UTMain(argv=None, **kwargs):
1431  """ Unit Test Main.
1432 
1433  Parameters:
1434  argv - Optional argument list to override command-line arguments.
1435  kwargs - Optional keyword argument list.
1436  """
1437  global _Argv0
1438 
1439  kwargs = UTGetOptions(argv, **kwargs)
1440 
1441  xmlNetMsgs = NetMsgsXmlParser(**kwargs)
1442 
1443  try:
1444  xmlNetMsgs.Parse()
1445  except NetMsgsXmlParserError as inst:
1446  print "Error: %s" % (inst)
1447  return 8
1448 
1449  xmlNetMsgs.PrettyPrintDB()
1450  ##
1451 
1452  ## Run unit test code.
1453  sys.exit( UTMain() )
def PrettyPrintDBFieldDef(self, indent, fname, fielddef)
def UTMain(argv=None, kwargs)
def XmlCbEndMsgDef(self, elem, data, attrs)
def XmlCbEndFieldDef(self, elem, data, attrs)
XmlCbStartElem
XML element start callbacks.
def XmlCbEndFieldDefMinMax(self, elem, data, attrs)
XmlCbEndElem
XML element start callbacks.
def XmlHandlerDTD(self, context, base, systemId, publicId)
def XmlCbEndFieldDefConst(self, elem, data, attrs)
def WriteXmlTree(self, fp, level, elemParent, elemList)
def UTGetOptions(argv=None, kwargs)
mDebug
debug print at given <= level
def _InitElemOList(self, elemList, olist)
def XmlCbEndFTypeDef(self, elem, data, attrs)
def WriteXmlFile(self, filename, comment=None)
XmlTree
xml tree starting at &#39;_root&#39;
def XmlHandlerEntityDecl(entityName, is_parameter_entity, value, base, systemId, publicId, notationName)
def __init__(self, filename=None, debug=0, kwargs)
def PrettyPrintDBFields(self, indent, fields)
def __init__(self, msg='XML Parser Error')
def XmlCbEndMetaLang(self, elem, data, attrs)
def XmlHandlerStartDoctype(self, doctypeName, systemId, publicId, has_internal_subset)
def XmlCbEndSection(self, elem, data, attrs)
def PrettyPrintVal(self, indent, name, val)
def XmlCbEndMetaData(self, elem, data, attrs)