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__ 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
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 inET.xinclude()
51 import copy
52 outET = copy.deepcopy(inET)
53
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
63
64 structName = inc.attrib['struct']
65 baseName = inc.attrib['name']+'_'
66
67
68
69 structDef = root.xpath("//struct[@name='"+structName+"']")
70
71
72 inc.getparent().replace(inc,etree.Comment('Struct include of '+inc.attrib['name']+' was here'))
73
74 replacement=copy.deepcopy(structDef[0])
75
76 postgis=False
77 postgisName=None
78 postgisType=None
79 if 'postgis_type' in replacement.attrib:
80 postgis=True
81 postgisType=replacement.attrib['postgis_type']
82 postgisName=inc.attrib['name']
83 if verbose: print 'Found PostGIS datatype for structure:',postgisName,postgisType
84
85
86
87
88 for subfield in replacement.xpath('field'):
89 subfield.attrib['name']=baseName+subfield.attrib['name']
90 desc = subfield.xpath('description')
91
92 if postgis:
93 if verbose: print 'Annotating',subfield.attrib['name'], 'with postgis info'
94 subfield.attrib['postgisType']=postgisType
95 subfield.attrib['postgisName']=postgisName
96
97 if len(desc)==1:
98 desc[0].text= inc.xpath('description')[0].text +'\n\n'+ desc[0].text
99 else:
100 print 'WARNING: no description for subfield!!!! Must have exactly one description field'
101
102
103
104
105 newPos = nodePosition+getPos(replacement,subfield)
106 nodePosition+=1
107 parent.insert(newPos,subfield)
108
109
110 return outET
111
113 '''
114 Replace each include-struct with the structure. This code is not
115 pretty, but it seems to work. The include-struct name is
116 prepended to each field name within the struct. The
117 include-struct description is also added to before the fields
118 description.
119
120 @param inET: lxml element tree to expand
121 @return: lxml element tree with expanded structures
122 '''
123 import copy
124 outET = copy.deepcopy(inET)
125
126 root = outET.getroot()
127 structs = root.xpath('struct')
128 for struct in structs:
129 if verbose: print 'nuking struct:',struct.attrib['name']
130 struct.getparent().replace(struct,etree.Comment('Struct '+struct.attrib['name']+' was here'))
131
132 return outET
133
134 if __name__ == '__main__':
135 from optparse import OptionParser
136 parser = OptionParser(usage="%prog [options]",
137 version="%prog "+__version__)
138 parser.add_option('-i','--input-file',dest='inFilename',default=None,
139 help='AIS to read from')
140 parser.add_option('-o','--output-file',dest='outFilename',default='out-ais.xml',
141 help='New AIS file that has structures expanded')
142 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
143 help='Verbose mode')
144
145 parser.add_option('-k','--keep-structs',dest='keepStructs',default=False,action='store_true',
146 help='Keep the structure definitions at the beginning of the file')
147 (options,args) = parser.parse_args()
148
149 tree = etree.parse(options.inFilename)
150
151 newET = expandAis(tree,options.verbose)
152 if not options.keepStructs:
153 newET = nukeStructs(newET,options.verbose)
154 newET.write(options.outFilename)
155
156
157