Mercurial > hg > graphML2RDF
comparison dottoxml/src/dottoxml.py @ 4:4fa7bf58e914
first release
author | dwinter |
---|---|
date | Mon, 23 Jul 2012 09:58:50 +0200 |
parents | d45d5c75afaa |
children |
comparison
equal
deleted
inserted
replaced
3:c97d43ac8fa6 | 4:4fa7bf58e914 |
---|---|
1 # coding: latin-1 | |
2 # Copyright (c) 2009,2010,2011,2012 Dirk Baechle. | |
3 # www: http://www.mydarc.de/dl9obn/programming/python/dottoxml | |
4 # mail: dl9obn AT darc.de | |
5 # | |
6 # This program is free software; you can redistribute it and/or modify it under | |
7 # the terms of the GNU General Public License as published by the Free Software | |
8 # Foundation; either version 2 of the License, or (at your option) any later | |
9 # version. | |
10 # | |
11 # This program is distributed in the hope that it will be useful, but WITHOUT | |
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
13 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
14 # | |
15 # You should have received a copy of the GNU General Public License along with | |
16 # this program; if not, write to the Free Software Foundation, Inc., | |
17 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
18 """ | |
19 %dottoxml.py [options] <infile.dot> <outfile.graphml> | |
20 | |
21 convert a DOT file to Graphml XML (and various other formats) | |
22 """ | |
23 | |
24 import sys | |
25 import locale | |
26 import optparse | |
27 | |
28 import dot | |
29 | |
30 # Usage message | |
31 usgmsg = "Usage: dottoxml.py [options] infile.dot outfile.graphml" | |
32 | |
33 def usage(): | |
34 print "dottoxml 1.3, 2012-04-04, Dirk Baechle\n" | |
35 print usgmsg | |
36 print "Hint: Try '-h' or '--help' for further infos!" | |
37 | |
38 def exportDot(o, nodes, edges, options): | |
39 o.write("graph [\n") | |
40 | |
41 for k,nod in nodes.iteritems(): | |
42 nod.exportDot(o,options) | |
43 for el in edges: | |
44 el.exportDot(o,nodes,options) | |
45 | |
46 def exportGML(o, nodes, edges, options): | |
47 o.write("graph [\n") | |
48 o.write(" comment \"Created by dottoxml.py\"\n") | |
49 o.write(" directed 1\n") | |
50 o.write(" IsPlanar 1\n") | |
51 | |
52 for k,nod in nodes.iteritems(): | |
53 nod.exportGML(o,options) | |
54 for el in edges: | |
55 el.exportGML(o,nodes,options) | |
56 | |
57 o.write("]\n") | |
58 | |
59 def exportGraphml(o, nodes, edges, options): | |
60 import xml.dom.minidom | |
61 doc = xml.dom.minidom.Document() | |
62 root = doc.createElement(u'graphml') | |
63 root.setAttribute(u'xmlns',u'http://graphml.graphdrawing.org/xmlns/graphml') | |
64 root.setAttribute(u'xmlns:xsi',u'http://www.w3.org/2001/XMLSchema-instance') | |
65 root.setAttribute(u'xmlns:y',u'http://www.yworks.com/xml/graphml') | |
66 root.setAttribute(u'xsi:schemaLocation',u'http://graphml.graphdrawing.org/xmlns/graphml http://www.yworks.com/xml/schema/graphml/1.0/ygraphml.xsd') | |
67 doc.appendChild(root) | |
68 key = doc.createElement(u'key') | |
69 key.setAttribute(u'for',u'node') | |
70 key.setAttribute(u'id',u'd0') | |
71 key.setAttribute(u'yfiles.type',u'nodegraphics') | |
72 root.appendChild(key) | |
73 | |
74 key = doc.createElement(u'key') | |
75 key.setAttribute(u'attr.name',u'description') | |
76 key.setAttribute(u'attr.type',u'string') | |
77 key.setAttribute(u'for',u'node') | |
78 key.setAttribute(u'id',u'd1') | |
79 root.appendChild(key) | |
80 | |
81 key = doc.createElement(u'key') | |
82 key.setAttribute(u'for',u'edge') | |
83 key.setAttribute(u'id',u'd2') | |
84 key.setAttribute(u'yfiles.type',u'edgegraphics') | |
85 root.appendChild(key) | |
86 | |
87 key = doc.createElement(u'key') | |
88 key.setAttribute(u'attr.name',u'description') | |
89 key.setAttribute(u'attr.type',u'string') | |
90 key.setAttribute(u'for',u'edge') | |
91 key.setAttribute(u'id',u'd3') | |
92 root.appendChild(key) | |
93 | |
94 key = doc.createElement(u'key') | |
95 key.setAttribute(u'for',u'node') | |
96 key.setAttribute(u'id',u'd4') | |
97 key.setAttribute(u'attr.name',u'url') | |
98 key.setAttribute(u'attr.type',u'string') | |
99 root.appendChild(key) | |
100 | |
101 graph = doc.createElement(u'graph') | |
102 graph.setAttribute(u'edgedefault',u'directed') | |
103 graph.setAttribute(u'id',u'G') | |
104 graph.setAttribute(u'parse.edges',u'%d' % len(edges)) | |
105 graph.setAttribute(u'parse.nodes',u'%d' % len(nodes)) | |
106 graph.setAttribute(u'parse.order', u'free') | |
107 | |
108 for k,nod in nodes.iteritems(): | |
109 nod.exportGraphml(doc, graph, options) | |
110 for el in edges: | |
111 el.exportGraphml(doc, graph, nodes, options) | |
112 | |
113 root.appendChild(graph) | |
114 | |
115 data = doc.createElement(u'data') | |
116 data.setAttribute(u'key',u'd4') | |
117 res = doc.createElement(u'y:Resources') | |
118 data.appendChild(res) | |
119 root.appendChild(data) | |
120 | |
121 o.write(doc.toxml(encoding="utf-8")) | |
122 | |
123 def exportGDF(o, nodes, edges, options): | |
124 o.write("nodedef> name\n") | |
125 for k,nod in nodes.iteritems(): | |
126 nod.exportGDF(o, options) | |
127 for el in edges: | |
128 el.exportGDF(o,nodes,options) | |
129 o.write("edgedef> node1,node2\n") | |
130 | |
131 def main(): | |
132 parser = optparse.OptionParser(usage=usgmsg) | |
133 parser.add_option('-f', '--format', | |
134 action='store', dest='format', default='Graphml', | |
135 help='selects the output format (Graphml|GML|GDF) [default : %default]') | |
136 parser.add_option('-v', '--verbose', | |
137 action='store_true', dest='verbose', default=False, | |
138 help='enables messages (infos, warnings)') | |
139 parser.add_option('-s', '--sweep', | |
140 action='store_true', dest='sweep', default=False, | |
141 help='sweep nodes (remove nodes that are not connected)') | |
142 parser.add_option('--nn', '--no-nodes', | |
143 action='store_false', dest='NodeLabels', default=True, | |
144 help='do not output any node labels [Graphml]') | |
145 parser.add_option('--ne', '--no-edges', | |
146 action='store_false', dest='EdgeLabels', default=True, | |
147 help='do not output any edge labels [Graphml]') | |
148 parser.add_option('--nu', '--no-uml', | |
149 action='store_false', dest='NodeUml', default=True, | |
150 help='do not output any node methods/attributes in UML [Graphml]') | |
151 parser.add_option('--na', '--no-arrows', | |
152 action='store_false', dest='Arrows', default=True, | |
153 help='do not output any arrows [Graphml]') | |
154 parser.add_option('--nc', '--no-colors', | |
155 action='store_false', dest='Colors', default=True, | |
156 help='do not output any colors [Graphml]') | |
157 parser.add_option('--la', '--lump-attributes', | |
158 action='store_true', dest='LumpAttributes', default=False, | |
159 help='lump class attributes/methods together with the node label [Graphml]') | |
160 parser.add_option('--sc', '--separator-char', | |
161 action='store', dest='SepChar', default='_', metavar='SEPCHAR', | |
162 help='default separator char when lumping attributes/methods [default : "_"]') | |
163 parser.add_option('--ae', '--auto-edges', | |
164 action='store_true', dest='EdgeLabelsAutoComplete', default=False, | |
165 help='auto-complete edge labels') | |
166 parser.add_option('--ah', '--arrowhead', | |
167 action='store', dest='DefaultArrowHead', default='none', metavar='TYPE', | |
168 help='sets the default appearance of arrow heads for edges (normal|diamond|dot|...) [default : %default]') | |
169 parser.add_option('--at', '--arrowtail', | |
170 action='store', dest='DefaultArrowTail', default='none', metavar='TYPE', | |
171 help='sets the default appearance of arrow tails for edges (normal|diamond|dot|...) [default : %default]') | |
172 parser.add_option('--cn', '--color-nodes', | |
173 action='store', dest='DefaultNodeColor', default='#CCCCFF', metavar='COLOR', | |
174 help='default node color [default : "#CCCCFF"]') | |
175 parser.add_option('--ce', '--color-edges', | |
176 action='store', dest='DefaultEdgeColor', default='#000000', metavar='COLOR', | |
177 help='default edge color [default : "#000000"]') | |
178 parser.add_option('--cnt', '--color-nodes-text', | |
179 action='store', dest='DefaultNodeTextColor', default='#000000', metavar='COLOR', | |
180 help='default node text color for labels [default : "#000000"]') | |
181 parser.add_option('--cet', '--color-edges-text', | |
182 action='store', dest='DefaultEdgeTextColor', default='#000000', metavar='COLOR', | |
183 help='default edge text color for labels [default : "#000000"]') | |
184 parser.add_option('--ienc', '--input-encoding', | |
185 action='store', dest='InputEncoding', default='', metavar='ENCODING', | |
186 help='override encoding for input file [default : locale setting]') | |
187 parser.add_option('--oenc', '--output-encoding', | |
188 action='store', dest='OutputEncoding', default='', metavar='ENCODING', | |
189 help='override encoding for text output files [default : locale setting]') | |
190 | |
191 options, args = parser.parse_args() | |
192 | |
193 if len(args) < 2: | |
194 usage() | |
195 sys.exit(1) | |
196 | |
197 infile = args[0] | |
198 outfile = args[1] | |
199 | |
200 options.DefaultNodeColor = dot.colorNameToRgb(options.DefaultNodeColor, '#CCCCFF') | |
201 options.DefaultEdgeColor = dot.colorNameToRgb(options.DefaultEdgeColor, '#000000') | |
202 options.DefaultNodeTextColor = dot.colorNameToRgb(options.DefaultNodeTextColor, '#000000') | |
203 options.DefaultEdgeTextColor = dot.colorNameToRgb(options.DefaultEdgeTextColor, '#000000') | |
204 | |
205 preferredEncoding = locale.getpreferredencoding() | |
206 if options.InputEncoding == "": | |
207 options.InputEncoding = preferredEncoding | |
208 if options.OutputEncoding == "": | |
209 options.OutputEncoding = preferredEncoding | |
210 | |
211 if options.verbose: | |
212 print "Input file: %s " % infile | |
213 print "Output file: %s " % outfile | |
214 print "Output format: %s" % options.format.lower() | |
215 print "Input encoding: %s" % options.InputEncoding | |
216 if options.format.lower() == "graphml": | |
217 print "Output encoding: utf-8 (fix for Graphml)" | |
218 else: | |
219 print "Output encoding: %s" % options.OutputEncoding | |
220 | |
221 # Collect nodes and edges | |
222 nodes = {} | |
223 edges = [] | |
224 default_edge = None | |
225 default_node = None | |
226 nid = 1 | |
227 eid = 1 | |
228 f = open(infile, 'r') | |
229 for l in f.readlines(): | |
230 l = unicode(l, options.InputEncoding) | |
231 if l.find('->') >= 0: | |
232 # Process edge | |
233 e = dot.Edge() | |
234 e.initFromString(l) | |
235 e.id = eid | |
236 eid += 1 | |
237 if default_edge: | |
238 e.complementAttributes(default_edge) | |
239 edges.append(e) | |
240 elif (l.find('[') > 0 and | |
241 l.find(']') > 0 and | |
242 l.find(';') > 0): | |
243 # Process node | |
244 n = dot.Node() | |
245 n.initFromString(l) | |
246 lowlabel = n.label.lower() | |
247 if (lowlabel != 'graph' and | |
248 lowlabel != 'edge' and | |
249 lowlabel != 'node'): | |
250 n.id = nid | |
251 nid += 1 | |
252 if default_node: | |
253 n.complementAttributes(default_node) | |
254 nodes[n.label] = n | |
255 else: | |
256 if lowlabel == 'edge': | |
257 default_edge = n | |
258 elif lowlabel == 'node': | |
259 default_node = n | |
260 elif l.find('charset=') >=0: | |
261 # Pick up input encoding from DOT file | |
262 li = l.strip().split('=') | |
263 if len(li) == 2: | |
264 ienc = li[1].strip('"') | |
265 if ienc != "": | |
266 options.InputEncoding = ienc | |
267 if options.verbose: | |
268 print "Info: Picked up input encoding '%s' from the DOT file." % ienc | |
269 | |
270 f.close() | |
271 | |
272 # Add single nodes, if required | |
273 for e in edges: | |
274 if not nodes.has_key(e.src): | |
275 n = dot.Node() | |
276 n.label = e.src | |
277 n.id = nid | |
278 nid += 1 | |
279 nodes[e.src] = n | |
280 if not nodes.has_key(e.dest): | |
281 n = dot.Node() | |
282 n.label = e.dest | |
283 n.id = nid | |
284 nid += 1 | |
285 nodes[e.dest] = n | |
286 nodes[e.src].referenced = True | |
287 nodes[e.dest].referenced = True | |
288 | |
289 if options.verbose: | |
290 print "\nNodes: %d " % len(nodes) | |
291 print "Edges: %d " % len(edges) | |
292 | |
293 if options.sweep: | |
294 rnodes = {} | |
295 for key, n in nodes.iteritems(): | |
296 if n.referenced: | |
297 rnodes[key] = n | |
298 nodes = rnodes | |
299 if options.verbose: | |
300 print "\nNodes after sweep: %d " % len(nodes) | |
301 | |
302 # Output | |
303 o = open(outfile, 'w') | |
304 format = options.format.lower() | |
305 if format == 'dot': | |
306 exportDot(o, nodes, edges, options) | |
307 elif format == 'graphml': | |
308 exportGraphml(o, nodes, edges, options) | |
309 elif format == 'gdf': | |
310 exportGDF(o, nodes, edges, options) | |
311 else: # GML | |
312 exportGML(o, nodes, edges, options) | |
313 o.close() | |
314 | |
315 if options.verbose: | |
316 print "\nDone." | |
317 | |
318 if __name__ == '__main__': | |
319 main() | |
320 |