Package ais :: Module expandais
[hide private]
[frames] | no frames]

Source Code for Module ais.expandais

  1  #!/usr/bin/env python 
  2   
  3  __version__ = '$Revision: 4820 $'.split()[1] 
  4  __date__ = '$Date: 2006-09-28 12:11:51 -0400 (Thu, 28 Sep 2006) $'.split()[1] 
  5  __author__ = 'Kurt Schwehr' 
  6   
  7  __doc__=''' 
  8  Expand structs in ais xml to include-struct elements while applying name mangling 
  9   
 10  @requires: U{lxml<http://codespeak.net/lxml/>} 
 11  @requires: U{epydoc<http://epydoc.sourceforge.net/>} > 3.0alpha3 
 12   
 13  @author: '''+__author__+''' 
 14  @version: ''' + __version__ +''' 
 15  @copyright: 2006 
 16  @var __date__: Date of last svn commit 
 17  @undocumented: __version__ __author__ __doc__ myparser 
 18  @since: 2006-Sep-26 
 19  @status: under development 
 20  @organization: U{CCOM<http://ccom.unh.edu/>} 
 21   
 22  @license: GPL v2 
 23  ''' 
 24   
 25  import sys 
 26  from lxml import etree  
 27   
28 -def getPos(parent,child):
29 ''' 30 Return the position number of the child node. It seems like this 31 really should be a part of the element tree interface. Perhaps 32 I overlooked it. 33 ''' 34 for i in range(len(parent)): 35 if parent[i]==child: return i 36 return None
37 38
39 -def expandAis(inET,verbose=False):
40 ''' 41 Replace each include-struct with the structure. This code is not 42 pretty, but it seems to work. The include-struct name is 43 prepended to each field name within the struct. The 44 include-struct description is also added to before the fields 45 description. 46 47 @param inET: lxml element tree to expand 48 @return: lxml element tree with expanded structures 49 ''' 50 import copy 51 outET = copy.deepcopy(inET) 52 53 root = outET.getroot() 54 includeStructs = root.xpath('message/include-struct') 55 for inc in includeStructs: 56 57 if verbose: print 'inc:',inc.attrib['name'], 'parent:',inc.getparent().tag 58 parent = inc.getparent() 59 nodePosition = getPos(parent,inc) 60 #if verbose: print 'pos:',nodePosition 61 62 structName = inc.attrib['struct'] 63 baseName = inc.attrib['name']+'_' 64 #if verbose: print 'baseName:',baseName, 'structName=',structName 65 66 structDef = root.xpath("struct[@name='"+structName+"']") 67 68 # Put in a comment where the include-struct was. 69 inc.getparent().replace(inc,etree.Comment('Struct include of '+inc.attrib['name']+' was here')) 70 71 replacement=copy.deepcopy(structDef[0]) 72 73 postgis=False # Does this structure have an associated postgis data structure? 74 postgisName=None 75 postgisType=None 76 if 'postgis_type' in replacement.attrib: 77 postgis=True 78 postgisType=replacement.attrib['postgis_type'] 79 postgisName=inc.attrib['name'] #baseName 80 if verbose: print 'Found PostGIS datatype for structure:',postgisName,postgisType 81 82 83 # FIX: what happens when the include is at the beginning or end of the list? 84 85 for subfield in replacement.xpath('field'): 86 subfield.attrib['name']=baseName+subfield.attrib['name'] 87 desc = subfield.xpath('description') 88 89 if postgis: 90 if verbose: print 'Annotating',subfield.attrib['name'], 'with postgis info' 91 subfield.attrib['postgisType']=postgisType 92 subfield.attrib['postgisName']=postgisName 93 94 if len(desc)==1: 95 desc[0].text= inc.xpath('description')[0].text +'\n\n'+ desc[0].text 96 else: 97 print 'WARNING: no description for subfield!!!! Must have exactly one description field' 98 # Now that the node is ready, jam it in there after the replaced comment 99 100 #print "FIX: make sure these end up in the right place!!!!" 101 102 newPos = nodePosition+getPos(replacement,subfield) #+1 103 nodePosition+=1 104 parent.insert(newPos,subfield) 105 #if verbose: print 'New parent:',etree.tostring(parent) 106 107 return outET
108
109 -def nukeStructs(inET,verbose=False):
110 ''' 111 Replace each include-struct with the structure. This code is not 112 pretty, but it seems to work. The include-struct name is 113 prepended to each field name within the struct. The 114 include-struct description is also added to before the fields 115 description. 116 117 @param inET: lxml element tree to expand 118 @return: lxml element tree with expanded structures 119 ''' 120 import copy 121 outET = copy.deepcopy(inET) 122 123 root = outET.getroot() 124 structs = root.xpath('struct') 125 for struct in structs: 126 if verbose: print 'nuking struct:',struct.attrib['name'] 127 struct.getparent().replace(struct,etree.Comment('Struct '+struct.attrib['name']+' was here')) 128 129 return outET
130 131 if __name__ == '__main__': 132 from optparse import OptionParser 133 myparser = OptionParser(usage="%prog [options]", 134 version="%prog "+__version__) 135 myparser.add_option('-i','--input-file',dest='inFilename',default=None, 136 help='AIS to read from') 137 myparser.add_option('-o','--output-file',dest='outFilename',default='out-ais.xml', 138 help='New AIS file that has structures expanded') 139 myparser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true', 140 help='Verbose mode') 141 142 myparser.add_option('-k','--keep-structs',dest='keepStructs',default=False,action='store_true', 143 help='Keep the structure definitions at the beginning of the file') 144 (options,args) = myparser.parse_args() 145 146 newET = expandAis(etree.parse(options.inFilename),options.verbose) 147 if not options.keepStructs: 148 newET = nukeStructs(newET,options.verbose) 149 newET.write(options.outFilename) 150 151 #if options.verbose: print etree.tostring(newET) 152