xml_parser.py
Go to the documentation of this file.
00001 #!/usr/bin/python
00002 import re
00003 import pydot
00004 import xml.etree.ElementTree as ET
00005 from sys import stdout
00006 import ntpath
00007 from optparse import OptionParser
00008 import sys
00009 import os
00010 
00011 
00012 node_counter=0;
00013 def map_all_ids(xml):
00014         global node_counter
00015         map_ids = {}
00016         for node in xml.iter():
00017                 if "id" not in node.attrib: continue
00018                 map_ids[node.attrib["id"]]=str(node_counter)
00019                 node_counter+=1
00020         return map_ids
00021 
00022 def path_leaf(path):
00023         head, tail = ntpath.split(path)
00024         return tail or ntpath.basename(head)
00025         
00026 class NodeShape:
00027         def __init__(self, tag_name):
00028                 self.nshape=""
00029                 self.nfillcolor="#FFFFFF"
00030                 self.npenwidth="1"
00031                 if tag_name in ['tsk', 'task']:
00032                         self.nshape="box"
00033                         self.npenwidth="3"
00034                 elif tag_name in ['seq', 'plan', 'pln']:
00035                         self.nshape="rarrow"
00036                 elif tag_name=='par':
00037                         self.nshape="parallelogram"
00038                         self.nfillcolor="#FFCC99"
00039                 else:
00040                         self.nshape="ellipse"
00041 #                       print "###### TAG NAME = ", tag_name
00042         def set(self, node):
00043                 node.set_shape(self.nshape)
00044                 node.set_fillcolor(self.nfillcolor)
00045                 #node.set_penwidth(self.npenwidth)
00046 
00047 
00048 def get_tao_start(tao_node):
00049         return tao_node.attrib["start"]
00050 
00051 def get_plan_details(plan_node):
00052         
00053         start_condition = "none"
00054         stop_condition = "none"
00055         allocate_protocol = "empty"
00056         next_protocol = "empty"
00057         
00058         for subnode in plan_node:
00059                 if subnode.tag == "tao_start_condition":
00060                         start_condition = subnode.text
00061                 if subnode.tag == "tao_stop_condition":
00062                         stop_condition = subnode.text
00063                 if subnode.tag == "tao_allocate":
00064                         allocate_protocol = subnode.attrib["protocol"]
00065                 if subnode.tag == "tao_next":
00066                         next_protocol = subnode.attrib["protocol"]
00067                         
00068                          
00069         return (start_condition, stop_condition, allocate_protocol, next_protocol)
00070 
00071 
00072 def gen_tao(node, graph):
00073         graph.add_node(pydot.Node("tao_root", label=" ", shape="point"))
00074         gen_tao_nodes(node, graph)
00075         graph.add_edge(pydot.Edge("tao_root", get_tao_start(node)))
00076 
00077 def gen_tao_nodes(node, graph):
00078         plans = node[0]
00079         block = pydot.Subgraph('', rank="same")
00080         
00081         for plan in plans:
00082                 (start_condition, stop_condition, allocate_protocol, next_protocol) = get_plan_details(plan)
00083                 import cgi
00084                  
00085                 label_content = """<
00086                 
00087                 <table style="">
00088                         <tr>
00089                                 <td style="background-color: #23a4ff; color: #fff; font-weight: bold; padding: 5px; font-size: 12pt;" align="center">
00090                                         <b>{planName}</b>
00091                                 </td>
00092                         </tr>
00093                         <tr>
00094                                 <td style="padding: 0; maring: 0;">
00095 
00096                                         <table style="border-width: 1px; border-style: solid; border-color: #999;">
00097                                                 <tr>
00098                                                         <td style="padding: 4px; maring: 0;">
00099                                                 {startCondition}
00100                                         </td>
00101                                                         <td style="padding: 4px; maring: 0;">
00102                                                 {stopCondition}
00103                                         </td>
00104                                                 </tr>
00105                                                 <tr>
00106                                                         <td style="padding: 4px; maring: 0;">{allocateProtocol}</td>
00107                                                         <td style="padding: 4px; maring: 0;">{nextProtocol}</td>
00108                                                 </tr>
00109                                         </table>
00110 
00111                                 </td>
00112                         </tr>
00113                 </table>
00114                 >""".format(
00115                                 planName = plan.attrib["name"], 
00116                                 startCondition = cgi.escape(start_condition), 
00117                                 stopCondition = cgi.escape(stop_condition), 
00118                                 allocateProtocol = allocate_protocol, 
00119                                 nextProtocol = next_protocol)
00120                 
00121                 plan_node = pydot.Node(str(plan.attrib["id"]), shape="rectangle", label=label_content, URL=plan.attrib["id"])
00122                 block.add_node(plan_node)
00123         
00124         graph.add_subgraph(block)
00125         gen_tao_edges(node, graph)
00126         
00127         for plan in plans:
00128                 for plan_subnode in plan:
00129                         if plan_subnode.tag == 'tao_allocate':
00130                                 for subtao in plan_subnode:
00131                                         gen_tao_nodes(subtao, graph)
00132         
00133         
00134 def gen_tao_edges(node, graph):
00135         plans = node[0]
00136         
00137         #===========================================================================
00138         # Next edges
00139         #===========================================================================
00140         for plan in plans:
00141                 for plan_subnode in plan:
00142                         if plan_subnode.tag == 'tao_next':
00143                                 for next_op in plan_subnode:
00144                                         edge = pydot.Edge(plan.attrib["id"], next_op.attrib["name"])
00145                                         graph.add_edge(edge)
00146                                         
00147         #===========================================================================
00148         # Alloc edges
00149         #===========================================================================
00150         for plan in plans:
00151                 for plan_subnode in plan:
00152                         if plan_subnode.tag == 'tao_allocate':
00153                                 for subtao in plan_subnode:
00154                                         edge = pydot.Edge(plan.attrib["id"], get_tao_start(subtao))
00155                                         graph.add_edge(edge)
00156                 
00157 
00158 def graph_gen_nodes(xml, node, graph, elem, ids):
00159         #print 'proc',node.tag, node.attrib['name'] if 'name' in node.attrib else ""
00160         if node.tag in ['scxml']:
00161                 for chnode in node:
00162                         graph_gen_nodes(xml, chnode, graph, elem, ids)
00163         if node.tag in ['parallel']:
00164                 for chnode in node:
00165                         graph_gen_nodes(xml, chnode, graph, elem, ids)
00166         if node.tag in ['state', 'invoke']:
00167                 if len(node.findall('state')+node.findall('invoke')+node.findall('plan')+node.findall('parallel'))==0:
00168                         
00169                         if node.tag == 'invoke':
00170                                 gr_node=pydot.Node(ids[node.attrib["id"]],label=node.attrib["name"], URL=node.attrib["id"], penwidth="0")
00171                         else:
00172                                 gr_node=pydot.Node(ids[node.attrib["id"]],label=node.attrib["name"], URL=node.attrib["id"])
00173                         
00174                         elem.add_node(gr_node)
00175                 else:
00176                         has_init_state = 'initialstate' in node.attrib
00177                         lbl = node.attrib["name"]
00178                         if has_init_state : lbl = 'FSM['+lbl+']'
00179                         
00180                         
00181                         gr_cluster=pydot.Cluster(ids[node.attrib["id"]],label=lbl, URL=node.attrib["id"])
00182                         
00183                         elem.add_subgraph(gr_cluster)
00184                         if has_init_state:
00185                                 gr_st_node = pydot.Node(ids[node.attrib["id"]]+"start", shape="point")
00186                                 gr_cluster.add_node(gr_st_node)
00187                         for chnode in node:
00188                                 graph_gen_nodes(xml, chnode, graph, gr_cluster, ids)
00189         if node.tag in ['plan', 'par', 'seq', 'sel', 'dec', 'pln']:
00190                 nlabel = node.attrib["name"]
00191                 if node.tag in ['plan','pln']: nlabel='BT['+nlabel+']'
00192                 gr_node=pydot.Node(ids[node.attrib["id"]],label=nlabel, URL=node.attrib["id"])
00193                 shape = NodeShape(node.tag)
00194                 shape.set(gr_node)
00195                 elem.add_node(gr_node)
00196                 for chnode in node:
00197                         graph_gen_nodes(xml, chnode, graph, elem, ids)
00198         if node.tag in ['task','tsk']:
00199                 if len(node.findall('scxml'))==0:
00200                         gr_node=pydot.Node(ids[node.attrib["id"]],label=node.attrib["name"], URL=node.attrib["id"])
00201                         shape = NodeShape(node.tag)
00202                         shape.set(gr_node)
00203                         elem.add_node(gr_node)
00204                         for chnode in node:
00205                                 graph_gen_nodes(xml, chnode, graph, elem, ids)
00206 #                       for chnode in node.findall('task'):
00207 #                               graph_gen_nodes(xml, chnode, graph, elem, ids)
00208                 else:
00209                         gr_cluster=pydot.Cluster(ids[node.attrib["id"]],label=node.attrib["name"], URL=node.attrib["id"])
00210                         elem.add_subgraph(gr_cluster)
00211                         for chnode in node.findall('scxml'):
00212                                 graph_gen_nodes(xml, chnode, graph, gr_cluster, ids)
00213                                 
00214         #===========================================================================
00215         # TAO
00216         #===========================================================================
00217         
00218         if node.tag in ['tao']:
00219                 gen_tao(node, graph)
00220                 
00221 #       if node.tag in ['tao', 'tao_plans']:
00222 #               for chnode in node:
00223 #                       graph_gen_nodes(xml, chnode, graph, elem, ids)
00224 #                       
00225 #       if node.tag in ['tao_plan']:
00226 #               gr_node=pydot.Node(ids[node.attrib["id"]], label=node.attrib["name"], URL=node.attrib["id"])
00227 #               shape = NodeShape(node.tag)
00228 #               shape.set(gr_node)
00229 #               elem.add_node(gr_node)
00230                 
00231 
00232 def find_simple_node(state):
00233         if state.tag == "state" and len([x for x in state if x.tag!='transition'])==0 : return state.attrib["id"]
00234         if state.tag == "invoke" and len([x for x in state if x.tag!='transition'])==0 : return state.attrib["id"]
00235         if state.tag in ['plan','pln', 'par', 'dec', 'seq', 'sel' ] : return state.attrib["id"]
00236         if state.tag in ["task","tsk"] and len(state.findall('scxml'))==0 : return state.attrib["id"]
00237         for n in state.iter(): 
00238                 if n!=state:
00239                         r = find_simple_node(n)
00240                         if r!=None : return r
00241         return None
00242 
00243 def find_state(fsm, state_id):
00244         for s in fsm:
00245                 if "id" in s.attrib and s.attrib["id"]==state_id: return s
00246         return None
00247         
00248 def graph_gen_edges(xml, node, graph, elem, ids, fsm=None):
00249         #print 'proc-edge',node.tag, node.attrib['name'] if 'name' in node.attrib else ""
00250         if node.tag in ['scxml']:
00251                 for chnode in node:
00252                         graph_gen_edges(xml, chnode, graph, elem, ids, node)
00253         if node.tag in ['parallel']:
00254                 for chnode in node:
00255                         graph_gen_edges(xml, chnode, graph, elem, ids, fsm)
00256         if node.tag in ['task', 'tsk']:
00257                 for chnode in node:
00258 #                       print "############ SUBPLAN FOUND #################" 
00259                         if "id" in node.attrib and "id" in chnode.attrib:
00260                                 src_state_id = node.attrib["id"]
00261                                 dst_state_id = chnode.attrib['id']
00262                                 src = src_state_id
00263                                 dst = dst_state_id
00264         #                       print "{src} -> {dst}".format(src = ids[src], dst = ids[dst])
00265                                 gr_edge = pydot.Edge(ids[src], ids[dst])
00266                                 graph.add_edge(gr_edge)
00267                                         
00268 #               for chnode in node.findall('plan'):
00269 # #                     print "############ SUBTASK FOUND #################" 
00270 #                       src_state_id = node.attrib["id"]
00271 #                       dst_state_id = chnode.attrib['id']
00272 #                       src = src_state_id
00273 #                       dst = dst_state_id
00274 #                       print "{src} -> {dst}".format(src = ids[src], dst = ids[dst])
00275 #                       gr_edge = pydot.Edge(ids[src], ids[dst])
00276 #                       graph.add_edge(gr_edge) 
00277                         
00278                 for chnode in node:
00279                         graph_gen_edges(xml, chnode, graph, elem, ids, fsm)
00280                         
00281         if node.tag in ['state', 'invoke']:
00282                 has_init_state = 'initialstate' in node.attrib
00283                 if has_init_state:
00284                         src_state_id = ids[node.attrib["id"]]+'start'
00285                         dst_state_id = node.attrib["id"]+"/"+node.attrib['initialstate']
00286                         dst_state = find_state(node, dst_state_id)
00287                         dst = None
00288                         if dst_state == None:
00289                                 print "ERROR: dst_state == None", dst_state_id
00290                         else:
00291                                 dst = find_simple_node(dst_state)
00292                                 gr_edge = pydot.Edge(src_state_id, ids[dst])
00293                                 if dst!=dst_state_id: gr_edge.set_lhead('cluster_'+ids[dst_state_id])
00294                                 #gr_edge.set_ltail(src_state_id)
00295                                 gr_edge.set_fontsize("8")
00296                                 graph.add_edge(gr_edge) 
00297                 for t in [ t for t in node.findall('transition') if 'target' in t.attrib ]:
00298                         src_state_id = node.attrib["id"]
00299                         dst_state_id = t.attrib['target']
00300                         src = find_simple_node(node)
00301                         dst_state = find_state(fsm, dst_state_id)
00302                         dst = None
00303                         if dst_state == None:
00304                                 print "ERROR: dst_state == None"
00305                         else:
00306                                 dst = find_simple_node(dst_state)
00307                                 gr_edge = pydot.Edge(ids[src], ids[dst])
00308                                 gr_edge.set_label(t.attrib["event"])
00309                                 if dst!=dst_state_id: gr_edge.set_lhead('cluster_'+ids[dst_state_id])
00310                                 if src!=src_state_id: gr_edge.set_ltail('cluster_'+ids[src_state_id])
00311                                 gr_edge.set_fontsize("8")
00312                                 graph.add_edge(gr_edge)         
00313                 for chnode in node:
00314                         graph_gen_edges(xml, chnode, graph, elem, ids, node)
00315         if node.tag in ['plan', 'par', 'seq', 'sel', 'dec', 'pln']:
00316                 for chnode in node:
00317                         src_state_id = node.attrib["id"]
00318                         dst_state_id = chnode.attrib['id']
00319                         src = find_simple_node(node)
00320                         dst_state = chnode
00321                         dst = find_simple_node(dst_state)
00322                         gr_edge = pydot.Edge(ids[src], ids[dst])
00323                         
00324                         if dst!=dst_state_id: gr_edge.set_lhead('cluster_'+ids[dst_state_id])
00325 
00326 
00327                         #gr_edge.set_ltail(ids[src_state_id])
00328                         graph.add_edge(gr_edge)         
00329                         graph_gen_edges(xml, chnode, graph, elem, ids, fsm)
00330                         
00331                         
00332                         
00333         #===========================================================================
00334         # TAO
00335         #===========================================================================
00336         
00337         if node.tag in ['tao']:
00338                 for chnode in node:
00339                         graph_gen_edges(xml, chnode, graph, elem, ids, node)
00340                         
00341         if node.tag in ['tao_plans']:
00342                 for chnode in node:
00343                         graph_gen_edges(xml, chnode, graph, elem, ids, node)
00344                 
00345                                 
00346 
00347 if __name__ == '__main__':
00348 
00349         parser = OptionParser()
00350         parser.add_option("-v", "--verbose", dest="verbose",
00351                           help="verbose printouts", nargs=0)
00352         parser.add_option("-q", "--quiet", dest="quite",
00353                           help="quiet printouts", nargs=0)
00354         parser.add_option("-i", "--info", dest="info",
00355                           help="printouts just locations info", nargs=0)
00356         
00357         (options, args) = parser.parse_args()
00358         
00359         if len(sys.argv) < 2:
00360                 sys.exit('Usage: %s projectName destinationFolder [...xmlFiles]' % sys.argv[0])
00361 
00362         if options.verbose is () or options.info is ():
00363                 print "  -- project location is",args[0]
00364                 print "  -- share folder is",args[1]
00365         if options.verbose is ():
00366                 print "  -- FILES: ",'\n'.join(args[2:])
00367         print "-- Start decision making xml parsing"
00368         try:
00369                 for fileXML in args[2].split(";"):
00370                         fileName = path_leaf(fileXML)
00371                         filetype = fileXML[-len("XXxml"):]
00372                         if options.verbose is ():
00373                                 print fileXML, fileName,filetype
00374                         xml = ET.parse(fileXML).getroot()
00375                         graph = pydot.Dot(graph_type='digraph', compound='true')
00376                         graph.set_node_defaults(shape="box");
00377                         map_ids = map_all_ids(xml)
00378                         if options.verbose is ():
00379                                 for k,v in map_ids.items(): print k,":",v
00380                         graph_gen_nodes(xml, xml, graph, graph, map_ids)
00381                         graph_gen_edges(xml, xml, graph, graph, map_ids)
00382                         
00383                         (fname, fextension) = os.path.splitext(os.path.basename(fileName))
00384                         
00385                         graph.write_raw(args[1] + os.sep + fname + ".dot")
00386         except:
00387                 print "  -- Unexpected error (",fileXML,"):", sys.exc_info()
00388                 import traceback
00389                 traceback.print_exc()
00390         print "-- End decision making xml parsing"


decision_making_parser
Author(s):
autogenerated on Wed Aug 26 2015 11:16:57