1
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
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
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
61
62 structName = inc.attrib['struct']
63 baseName = inc.attrib['name']+'_'
64
65
66 structDef = root.xpath("struct[@name='"+structName+"']")
67
68
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
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']
80 if verbose: print 'Found PostGIS datatype for structure:',postgisName,postgisType
81
82
83
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
99
100
101
102 newPos = nodePosition+getPos(replacement,subfield)
103 nodePosition+=1
104 parent.insert(newPos,subfield)
105
106
107 return outET
108
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
152