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