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