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__ parser 
 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 inET.xinclude() 51 import copy 52 outET = copy.deepcopy(inET) 53 #outET.xinclude() 54 55 root = outET.getroot() 56 includeStructs = root.xpath('message/include-struct') 57 for inc in includeStructs: 58 59 if verbose: print 'inc:',inc.attrib['name'], 'parent:',inc.getparent().tag 60 parent = inc.getparent() 61 nodePosition = getPos(parent,inc) 62 #if verbose: print 'pos:',nodePosition 63 64 structName = inc.attrib['struct'] 65 baseName = inc.attrib['name']+'_' 66 67 if len(inc.xpath('do_not_mangle_name'))>0: 68 if verbose: print 'Not mangling',structName,baseName[:-1] 69 baseName = '' 70 #if verbose: print 'baseName:',baseName, 'structName=',structName 71 72 # // means find all struct tags at all levels 73 structDef = root.xpath("//struct[@name='"+structName+"']") 74 75 # Put in a comment where the include-struct was. 76 inc.getparent().replace(inc,etree.Comment('Struct include of '+inc.attrib['name']+' was here')) 77 78 replacement=copy.deepcopy(structDef[0]) 79 80 postgis=False # Does this structure have an associated postgis data structure? 81 postgisName=None 82 postgisType=None 83 if 'postgis_type' in replacement.attrib: 84 postgis=True 85 postgisType=replacement.attrib['postgis_type'] 86 postgisName=inc.attrib['name'] #baseName 87 if verbose: print 'Found PostGIS datatype for structure:',postgisName,postgisType 88 89 90 # FIX: what happens when the include is at the beginning or end of the list? 91 92 for subfield in replacement.xpath('field'): 93 subfield.attrib['name']=baseName+subfield.attrib['name'] 94 desc = subfield.xpath('description') 95 96 if postgis: 97 if verbose: print 'Annotating',subfield.attrib['name'], 'with postgis info' 98 subfield.attrib['postgisType']=postgisType 99 subfield.attrib['postgisName']=postgisName 100 101 if len(desc)==1: 102 txt = inc.xpath('description')[0].text 103 if None == txt: 104 if verbose: 'WARNING: are you sure you want no text in this description?' 105 txt = '' 106 else: txt +='\n\t' 107 desc[0].text= txt+desc[0].text 108 else: 109 print 'WARNING: no description for subfield!!!! Must have exactly one description field' 110 # Now that the node is ready, jam it in there after the replaced comment 111 112 #print "FIX: make sure these end up in the right place!!!!" 113 114 newPos = nodePosition+getPos(replacement,subfield) #+1 115 nodePosition+=1 116 parent.insert(newPos,subfield) 117 #if verbose: print 'New parent:',etree.tostring(parent) 118 119 return outET
120
121 -def nukeStructs(inET,verbose=False):
122 ''' 123 Replace each include-struct with the structure. This code is not 124 pretty, but it seems to work. The include-struct name is 125 prepended to each field name within the struct. The 126 include-struct description is also added to before the fields 127 description. 128 129 @param inET: lxml element tree to expand 130 @return: lxml element tree with expanded structures 131 ''' 132 import copy 133 outET = copy.deepcopy(inET) 134 135 root = outET.getroot() 136 structs = root.xpath('struct') 137 for struct in structs: 138 if verbose: print 'nuking struct:',struct.attrib['name'] 139 struct.getparent().replace(struct,etree.Comment('Struct '+struct.attrib['name']+' was here')) 140 141 return outET
142 143 if __name__ == '__main__': 144 from optparse import OptionParser 145 parser = OptionParser(usage="%prog [options]", 146 version="%prog "+__version__) 147 parser.add_option('-i','--input-file',dest='inFilename',default=None, 148 help='AIS to read from') 149 parser.add_option('-o','--output-file',dest='outFilename',default='out-ais.xml', 150 help='New AIS file that has structures expanded') 151 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true', 152 help='Verbose mode') 153 154 parser.add_option('-k','--keep-structs',dest='keepStructs',default=False,action='store_true', 155 help='Keep the structure definitions at the beginning of the file') 156 (options,args) = parser.parse_args() 157 158 tree = etree.parse(options.inFilename) 159 #tree.xinclude() 160 newET = expandAis(tree,options.verbose) 161 if not options.keepStructs: 162 newET = nukeStructs(newET,options.verbose) 163 newET.write(options.outFilename) 164 165 #if options.verbose: print etree.tostring(newET) 166