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 if len(inc.xpath('do_not_mangle_name'))>0:
68 if verbose: print 'Not mangling',structName,baseName[:-1]
69 baseName = ''
70
71
72
73 structDef = root.xpath("//struct[@name='"+structName+"']")
74
75
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
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']
87 if verbose: print 'Found PostGIS datatype for structure:',postgisName,postgisType
88
89
90
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
111
112
113
114 newPos = nodePosition+getPos(replacement,subfield)
115 nodePosition+=1
116 parent.insert(newPos,subfield)
117
118
119 return outET
120
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
160 newET = expandAis(tree,options.verbose)
161 if not options.keepStructs:
162 newET = nukeStructs(newET,options.verbose)
163 newET.write(options.outFilename)
164
165
166