+#!/usr/bin/env python
+# -*- coding: iso-8859-1 -*-
+
+from xml.sax import saxutils
+
+# Estados
+E_CLASS = 1
+E_CLASS_NAME = 2
+E_CLASS_COMMENT = 3
+E_ATTRS = 4
+E_ATTR = 5
+E_ATTR_NAME = 6
+E_ATTR_COMMENT = 7
+E_ATTR_TYPE = 8
+
+# Caracteres a eliminar
+STRIPCHARS = '#\t\n '
+
+class ObjFinder(saxutils.DefaultHandler):
+ def __init__(self):
+ self.estado = None
+ self.clases = []
+ self.curr = None
+ self.curr_attr = None
+ def startElement(self, name, attrs):
+ #print " #### Start <%s %s>" % (name, dict(attrs))
+ if name == 'dia:object': # Comienzo de una clase
+ if attrs.get('type', None) == 'UML - Class':
+ self.curr = {}
+ self.estado = E_CLASS
+ elif name == 'dia:attribute':
+ name = attrs.get('name', None)
+ if self.estado == E_CLASS: # Datos de la clase
+ if name == 'name': # Nombre de la clase
+ self.curr['name'] = ''
+ self.estado = E_CLASS_NAME
+ elif name == 'comment': # Es la descripción de la clase
+ self.curr['comment'] = ''
+ self.estado = E_CLASS_COMMENT
+ elif name == 'attributes': # Paso empezó a encontrar atributos
+ self.curr['attrs'] = []
+ self.estado = E_ATTRS
+ elif self.estado == E_ATTR: # Datos del atributo
+ if name == 'name': # Nombre del atributo
+ self.curr_attr['name'] = ''
+ self.estado = E_ATTR_NAME
+ elif name == 'type': # Es el tipo del atributo
+ self.curr_attr['type'] = ''
+ self.estado = E_ATTR_TYPE
+ elif name == 'comment': # Es la descripción del atributo
+ self.curr_attr['comment'] = ''
+ self.estado = E_ATTR_COMMENT
+ elif name == 'dia:composite': # Comienzo de attributos de clase
+ if self.estado == E_ATTRS: # Si estoy en una clase
+ self.curr_attr = {}
+ self.estado = E_ATTR # Paso a buscar sus atributos
+ def characters(self, data):
+ if self.estado == E_CLASS_NAME:
+ self.curr['name'] += data.strip(STRIPCHARS)
+ elif self.estado == E_CLASS_COMMENT:
+ self.curr['comment'] += data.strip(STRIPCHARS)
+ elif self.estado == E_ATTR_NAME:
+ self.curr_attr['name'] += data.strip(STRIPCHARS)
+ elif self.estado == E_ATTR_TYPE:
+ self.curr_attr['type'] += data.strip(STRIPCHARS)
+ elif self.estado == E_ATTR_COMMENT:
+ self.curr_attr['comment'] += data.strip(STRIPCHARS)
+ def endElement(self, name):
+ #print " #### Endt </%s>" % name
+ if name == 'dia:object':
+ if self.estado == E_CLASS:
+ self.clases.append(self.curr)
+ self.estado = None
+ self.curr = None
+ elif name == 'dia:attribute':
+ if self.estado == E_CLASS_NAME:
+ self.estado = E_CLASS
+ if self.estado == E_CLASS_COMMENT:
+ self.estado = E_CLASS
+ if self.estado == E_ATTR_NAME:
+ self.estado = E_ATTR
+ if self.estado == E_ATTR_TYPE:
+ self.estado = E_ATTR
+ if self.estado == E_ATTR_COMMENT:
+ self.estado = E_ATTR
+ if self.estado == E_ATTRS:
+ self.estado = E_CLASS
+ elif name == 'dia:composite':
+ if self.estado == E_ATTR:
+ self.curr['attrs'].append(self.curr_attr)
+ self.curr_attr = None
+ self.estado = E_ATTRS
+
+
+if __name__ == '__main__':
+ import sys
+ from xml.sax import make_parser
+ from xml.sax.handler import feature_namespaces
+
+ # Verifica parámetros
+ if len(sys.argv) < 2:
+ print >>sys.stderr, 'Uso:', sys.argv[0], 'archivo.dia'
+ sys.exit(1)
+
+ # Create a parser
+ parser = make_parser()
+
+ # Tell the parser we are not interested in XML namespaces
+ parser.setFeature(feature_namespaces, 0)
+
+ # Create the handler
+ dh = ObjFinder()
+
+ # Tell the parser to use our handler
+ parser.setContentHandler(dh)
+
+ # Parse the input
+ parser.parse(sys.argv[1])
+
+ # Recorro clases obtenidas
+ for c in dh.clases:
+ print
+ print 'Clase:', c['name']
+ print 'Descripción:', c['comment']
+ print 'Atributos:'
+ for a in c['attrs']:
+ print ' %(name)s (%(type)s): %(comment)s' % a
+
+
+# vim: set et sw=4 sts=4 :