2 # -*- coding: iso-8859-1 -*-
4 from xml.sax import saxutils
23 E_OP_PARAM_COMMENT = 17
26 # Caracteres a eliminar
32 if DEBUG: print >>sys.stderr, s.encode('iso-8859-1', 'replace')
34 class ObjFinder(saxutils.DefaultHandler):
41 self.curr_param = None
42 def startElement(self, name, attrs):
43 if name == 'dia:object': # Comienzo de una clase
44 if attrs.get('type', None) == 'UML - Class':
47 dprint("E_CLASS (encontrado dia:object)")
48 elif name == 'dia:attribute':
49 name = attrs.get('name', None)
50 if self.estado == E_CLASS: # Datos de la clase
51 if name == 'name': # Nombre de la clase
52 self.curr['name'] = ''
53 self.estado = E_CLASS_NAME
54 dprint("E_CLASS -> E_CLASS_NAME (encontrado dia:attribute con name)")
55 elif name == 'comment': # Es la descripción de la clase
56 self.curr['comment'] = ''
57 self.estado = E_CLASS_COMMENT
58 dprint("E_CLASS -> E_CLASS_COMMENT (encontrado dia:attribute con comment)")
59 elif name == 'attributes': # Paso a encontrar atributos
60 self.curr['attrs'] = []
62 dprint("E_CLASS -> E_ATTRS (encontrado dia:attribute con attributes)")
63 elif name == 'operations': # Paso a encontrar operaciones
66 dprint("E_CLASS -> E_OPS (encontrado dia:attribute con operations)")
67 elif self.estado == E_ATTR: # Datos del atributo
68 if name == 'name': # Nombre del atributo
69 self.curr_attr['name'] = ''
70 self.estado = E_ATTR_NAME
71 dprint("E_ATTR -> E_ATTR_NAME (encontrado dia:attribute con name)")
72 elif name == 'type': # Es el tipo del atributo
73 self.curr_attr['type'] = ''
74 self.estado = E_ATTR_TYPE
75 dprint("E_ATTR -> E_ATTR_TYPE (encontrado dia:attribute con type)")
76 elif name == 'comment': # Es la descripción del atributo
77 self.curr_attr['comment'] = ''
78 self.estado = E_ATTR_COMMENT
79 dprint("E_ATTR -> E_ATTR_COMMENT (encontrado dia:attribute con comment)")
80 elif self.estado == E_OP: # Datos del atributo
81 if name == 'name': # Nombre del atributo
82 self.curr_op['name'] = ''
83 self.estado = E_OP_NAME
84 dprint("E_OP -> E_OP_NAME (encontrado dia:attribute con name)")
85 elif name == 'type': # Es el tipo del atributo
86 self.curr_op['type'] = ''
87 self.estado = E_OP_TYPE
88 dprint("E_OP -> E_OP_TYPE (encontrado dia:attribute con type)")
89 elif name == 'comment': # Es la descripción del atributo
90 self.curr_op['comment'] = ''
91 self.estado = E_OP_COMMENT
92 dprint("E_OP -> E_OP_COMMENT (encontrado dia:attribute con comment)")
93 elif name == 'parameters': # Paso a encontrar parámetros de operaciones
94 self.curr_op['params'] = []
95 self.estado = E_OP_PARAMS
96 dprint("E_OP -> E_OP_PARAMS (encontrado dia:attribute con parameters)")
97 elif self.estado == E_OP_PARAM: # Datos del parametro
98 if name == 'name': # Nombre del parametro
99 self.curr_param['name'] = ''
100 self.estado = E_OP_PARAM_NAME
101 dprint("E_OP_PARAM -> E_OP_PARAM_NAME (encontrado dia:attribute con name)")
102 elif name == 'type': # Es el tipo del parametro
103 self.curr_param['type'] = ''
104 self.estado = E_OP_PARAM_TYPE
105 dprint("E_OP_PARAM -> E_OP_PARAM_TYPE (encontrado dia:attribute con type)")
106 elif name == 'comment': # Es la descripción del parametro
107 self.curr_param['comment'] = ''
108 self.estado = E_OP_PARAM_COMMENT
109 dprint("E_OP_PARAM -> E_OP_PARAM_COMMENT (encontrado dia:attribute con comment)")
110 elif name == 'dia:composite': # Comienza composite
111 if self.estado == E_ATTRS: # Si estoy en atributos
113 self.estado = E_ATTR # Paso a buscar sus atributos
114 dprint("E_ATTRS -> E_ATTR (encontrado dia:composite)")
115 elif self.estado == E_OPS: # Si estoy en operaciones
117 self.estado = E_OP # Paso a buscar sus operaciones
118 dprint("E_OPS -> E_OP (encontrado dia:composite)")
119 elif self.estado == E_OP_PARAMS: # Si estoy en parametros de operaciones
121 self.estado = E_OP_PARAM # Paso a buscar sus parametros
122 dprint("E_OP_PARAMS -> E_OP_PARAM (encontrado dia:composite)")
123 def characters(self, data):
124 if self.estado == E_CLASS_NAME:
125 self.curr['name'] += data.strip(STRIPCHARS)
126 dprint("E_CLASS_NAME: %s" % data.strip(STRIPCHARS))
127 elif self.estado == E_CLASS_COMMENT:
128 self.curr['comment'] += data.strip(STRIPCHARS)
129 dprint("E_CLASS_COMMENT: %s" % data.strip(STRIPCHARS))
130 elif self.estado == E_ATTR_NAME:
131 self.curr_attr['name'] += data.strip(STRIPCHARS)
132 dprint("E_ATTR_NAME: %s" % data.strip(STRIPCHARS))
133 elif self.estado == E_ATTR_TYPE:
134 self.curr_attr['type'] += data.strip(STRIPCHARS)
135 dprint("E_ATTR_TYPE: %s" % data.strip(STRIPCHARS))
136 elif self.estado == E_ATTR_COMMENT:
137 self.curr_attr['comment'] += data.strip(STRIPCHARS)
138 dprint("E_ATTR_COMMENT: %s" % data.strip(STRIPCHARS))
139 elif self.estado == E_OP_NAME:
140 self.curr_op['name'] += data.strip(STRIPCHARS)
141 dprint("E_OP_NAME: %s" % data.strip(STRIPCHARS))
142 elif self.estado == E_OP_TYPE:
143 self.curr_op['type'] += data.strip(STRIPCHARS)
144 dprint("E_OP_TYPE: %s" % data.strip(STRIPCHARS))
145 elif self.estado == E_OP_COMMENT:
146 self.curr_op['comment'] += data.strip(STRIPCHARS)
147 dprint("E_OP_COMMENT: %s" % data.strip(STRIPCHARS))
148 elif self.estado == E_OP_PARAM_NAME:
149 self.curr_param['name'] += data.strip(STRIPCHARS)
150 dprint("E_OP_PARAM_NAME: %s" % data.strip(STRIPCHARS))
151 elif self.estado == E_OP_PARAM_TYPE:
152 self.curr_param['type'] += data.strip(STRIPCHARS)
153 dprint("E_OP_PARAM_TYPE: %s" % data.strip(STRIPCHARS))
154 elif self.estado == E_OP_PARAM_COMMENT:
155 self.curr_param['comment'] += data.strip(STRIPCHARS)
156 dprint("E_OP_PARAM_COMMENT: %s" % data.strip(STRIPCHARS))
157 def endElement(self, name):
158 if name == 'dia:object':
159 if self.estado == E_CLASS:
160 self.clases.append(self.curr)
163 dprint("E_CLASS -> None")
164 elif name == 'dia:attribute':
165 if self.estado == E_CLASS_NAME:
166 self.estado = E_CLASS
167 dprint("E_CLASS_NAME -> E_CLASS")
168 elif self.estado == E_CLASS_COMMENT:
169 self.estado = E_CLASS
170 dprint("E_CLASS_COMMENT -> E_CLASS")
171 elif self.estado == E_ATTR_NAME:
173 dprint("E_ATTR_NAME -> E_ATTR")
174 elif self.estado == E_ATTR_TYPE:
176 dprint("E_ATTR_TYPE -> E_ATTR")
177 elif self.estado == E_ATTR_COMMENT:
179 dprint("E_ATTR_COMMENT -> E_ATTR")
180 elif self.estado == E_ATTRS:
181 self.estado = E_CLASS
182 dprint("E_ATTRS -> E_CLASS")
183 elif self.estado == E_OP_NAME:
185 dprint("E_OP_NAME -> E_OP")
186 elif self.estado == E_OP_TYPE:
188 dprint("E_OP_TYPE -> E_OP")
189 elif self.estado == E_OP_COMMENT:
191 dprint("E_OP_COMMENT -> E_OP")
192 elif self.estado == E_OPS:
193 self.estado = E_CLASS
194 dprint("E_OPS -> E_CLASS")
195 elif self.estado == E_OP_PARAM_NAME:
196 self.estado = E_OP_PARAM
197 dprint("E_OP_PARAM_NAME -> E_OP_PARAM")
198 elif self.estado == E_OP_PARAM_TYPE:
199 self.estado = E_OP_PARAM
200 dprint("E_OP_PARAM_TYPE -> E_OP_PARAM")
201 elif self.estado == E_OP_PARAM_COMMENT:
202 self.estado = E_OP_PARAM
203 dprint("E_OP_PARAM_COMMENT -> E_OP_PARAM")
204 elif self.estado == E_OP_PARAMS:
206 dprint("E_OP_PARAMS -> E_OP")
207 elif name == 'dia:composite':
208 if self.estado == E_ATTR:
209 self.curr['attrs'].append(self.curr_attr)
210 self.curr_attr = None
211 self.estado = E_ATTRS
212 dprint("E_ATTR -> E_ATTRS")
213 elif self.estado == E_OP:
214 self.curr['ops'].append(self.curr_op)
217 dprint("E_OP -> E_OPS")
218 elif self.estado == E_OP_PARAM:
219 self.curr_op['params'].append(self.curr_param)
220 self.curr_param = None
221 self.estado = E_OP_PARAMS
222 dprint("E_OP_PARAM -> E_OP_PARAMS")
224 def param2str(params):
227 ret.append('%s: %s' \
228 % (p['name'].encode('iso-8859-1', 'replace'),
229 p['type'].encode('iso-8859-1', 'replace')))
230 return ', '.join(ret)
235 print c['name'].encode('iso-8859-1', 'replace')
236 print c['comment'].encode('iso-8859-1', 'replace')
237 print 'Atributo\tTipo\tDescripción'
240 % (a['name'].encode('iso-8859-1', 'replace'),
241 a['type'].encode('iso-8859-1', 'replace'),
242 a['comment'].encode('iso-8859-1', 'replace'))
243 if metodos and c['ops']:
245 print 'Método %s(%s): %s' \
246 % (o['name'].encode('iso-8859-1', 'replace'),
247 param2str(o['params']),
248 o['type'].encode('iso-8859-1', 'replace'))
249 print o['comment'].encode('iso-8859-1', 'replace')
251 print 'Parámetro\tTipo\tDescripción'
252 for p in o['params']:
254 % (p['name'].encode('iso-8859-1', 'replace'),
255 p['type'].encode('iso-8859-1', 'replace'),
256 p['comment'].encode('iso-8859-1', 'replace'))
259 print '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">'
260 print '<html lang="es"><head><title>Especificación</title></head><body>'
261 # Recorro clases obtenidas
263 print '<table width="100%%" border="1" summary="Especificación de clase %s">' \
264 % c['name'].encode('iso-8859-1', 'replace')
265 print '<tr><th colspan="3">%s</th></tr>' % c['name'].encode('iso-8859-1', 'replace')
266 print '<tr><td colspan="3">%s</td></tr>' % c['comment'].encode('iso-8859-1', 'replace')
267 print '<tr><th>Atributo</th><th>Tipo</th><th>Descripción</th></tr>'
269 print '<tr><td>%s</td><td>%s</td><td>%s</td></tr>' \
270 % (a['name'].encode('iso-8859-1', 'replace'),
271 a['type'].encode('iso-8859-1', 'replace'),
272 a['comment'].encode('iso-8859-1', 'replace'))
273 if metodos and c['ops']:
275 print '<tr><th colspan="3">Método</th></tr>'
276 print '<tr><td colspan="3">%s(%s): %s</td></tr>' \
277 % (o['name'].encode('iso-8859-1', 'replace'),
278 param2str(o['params']),
279 o['type'].encode('iso-8859-1', 'replace'))
280 print '<tr><td colspan="3">%s</td></tr>' % \
281 o['comment'].encode('iso-8859-1', 'replace')
283 print '<tr><th>Parámetro</th><th>Tipo</th><th>Descripción</th></tr>'
284 for p in o['params']:
285 print '<tr><td>%s</td><td>%s</td><td>%s</td></tr>' \
286 % (p['name'].encode('iso-8859-1', 'replace'),
287 p['type'].encode('iso-8859-1', 'replace'),
288 p['comment'].encode('iso-8859-1', 'replace'))
290 print '</body></html>'
292 if __name__ == '__main__':
294 from xml.sax import make_parser
295 from xml.sax.handler import feature_namespaces
297 # Verifica parámetros
298 if len(sys.argv) < 2:
299 print >>sys.stderr, 'Uso:', sys.argv[0], 'archivo.dia [-n]'
300 print >>sys.stderr, '-n si no se quieren incluir los métodos'
304 parser = make_parser()
306 # Tell the parser we are not interested in XML namespaces
307 parser.setFeature(feature_namespaces, 0)
312 # Tell the parser to use our handler
313 parser.setContentHandler(dh)
316 parser.parse(sys.argv[1])
318 # Veo si hay que poner métodos
320 if len(sys.argv) > 2 and sys.argv[2] == '-n':
323 # Imprimo como txt feo para convertir a RTF
327 # vim: set et sw=4 sts=4 :