from __future__ import absolute_import
from __future__ import print_function
import os
import sys
import glob
import xml
from xml.sax import parse, handler
from optparse import OptionParser
from collections import defaultdict
a = {}
a['net'] = ('version', )
a['edge'] = ('id', 'from', 'to', 'name', 'priority',
'type', 'function', 'spread_type', 'shape')
a['lane'] = ('id', 'index', 'vclasses', 'allow', 'disallow',
'maxspeed', 'maxSpeed', 'length', 'endOffset', 'width', 'shape')
a['junction'] = ('id', 'type', 'x', 'y', 'incLanes', 'intLanes', 'shape')
a['logicitem'] = ('response', 'foes', 'cont')
a['succlane'] = ('via', 'tl', 'linkno', 'dir', 'state')
a['connection'] = (
'from', 'to', 'fromLane', 'toLane', 'via', 'tl', 'linkIdx', 'dir', 'state')
a['row-logic'] = a['ROWLogic'] = ('id', 'requestSize')
a['tl-logic'] = a['tlLogic'] = ('id', 'type', 'programID', 'offset')
a['location'] = ('netOffset', 'convBoundary', 'origBoundary', 'projParameter')
a['phase'] = ('duration', 'state', 'min_dur', 'max_dur')
a['district'] = ('id', 'shape', 'edges')
a['dsink'] = ('id', 'weight')
a['dsource'] = ('id', 'weight')
a['taz'] = ('id', 'shape', 'edges')
a['tazSink'] = ('id', 'weight')
a['tazSource'] = ('id', 'weight')
a['roundabout'] = ('nodes', 'dummy')
a['request'] = ('index', 'response', 'foes', 'cont')
a['succ'] = ('edge', 'lane', 'junction')
b = defaultdict(dict)
b['edge']['type'] = ''
b['edge']['function'] = 'normal'
b['succlane']['tl'] = ''
b['succlane']['linkno'] = ''
b['succlane']['linkIndex'] = ''
b['junction']['shape'] = ''
SINGLE = ('roundabout', 'logicitem', 'phase', 'succlane', 'dsource', 'dsink', 'location',
'lane', 'timed_event', 'connection', 'request')
REMOVED = ('lanes', 'logic', 'succ', 'row-logic', 'ROWLogic', 'logicitem')
RENAMED_TAGS = {'tl-logic': 'tlLogic',
'row-logic': 'ROWLogic',
'district': 'taz',
'dsource': 'tazSource',
'dsink': 'tazSink',
'succlane': 'connection'}
renamedAttrs = {'min_dur': 'minDur',
'max_dur': 'maxDur',
'spread_type': 'spreadType',
'maxspeed': 'speed',
'maxSpeed': 'speed',
'linkIdx': 'linkIndex',
'linkno': 'linkIndex'}
renamedValues = {'state': {'t': 'o'}, 'type': {'DEAD_END': 'dead_end'}}
def getBegin(file):
fd = open(file)
content = ""
for line in fd:
if '<net' in line or '<districts' in line or '<add' in line:
fd.close()
return content
if '<?xml version' in line:
continue
content = content + line
fd.close()
return ""
class NetConverter(handler.ContentHandler):
def __init__(self, outFileName, begin, has_no_destination):
self._out = open(outFileName, "w")
self._out.write('<?xml version="1.0" encoding="iso-8859-1"?>\n')
self._out.write(begin)
self._tree = []
self._content = ""
self._am_parsing_rowlogic = None
self._logicitems = defaultdict(list)
self._laneCount = 0
self._has_no_destination = has_no_destination
def isSingle(self, name):
if name in SINGLE:
return True
if name == "junction" and self._single_junction:
return True
return False
def remove(self, name):
if name == "succ" and self._has_no_destination:
return False
if name in REMOVED:
return True
else:
return False
def rename(self, name):
if name == "succlane" and self._has_no_destination:
return False
if name in RENAMED_TAGS:
return True
else:
return False
def checkWrite(self, what):
self._out.write(what.encode('iso-8859-1'))
def indent(self):
self._out.write(" " * (4 * len(self._tree)))
def endDocument(self):
self.checkWrite("\n")
self._out.close()
def startElement(self, name, attrs):
if name == "succ":
self._succ_from = attrs["edge"]
self._succ_fromIdx = attrs["lane"].split('_')[-1]
if name == "row-logic" or name == "ROWLogic":
self._am_parsing_rowlogic = attrs["id"]
if name == "logicitem":
self._logicitems[self._am_parsing_rowlogic].append(attrs)
if name == "edge":
self._laneCount = 0
if name == "junction":
self._single_junction = (attrs["id"][0] == ":" or
attrs["type"] == 'DEAD_END' or
attrs["type"] == 'dead_end')
if self.remove(name):
return
if self._content.find("\n\n") >= 0:
self.checkWrite("\n")
self._content = ""
self.indent()
if self.rename(name):
self.checkWrite("<" + RENAMED_TAGS[name])
else:
self.checkWrite("<" + name)
if name == "succlane":
if self._has_no_destination:
self.checkWrite(' lane="%s"' % attrs["lane"])
else:
self.checkWrite(' from="%s"' % self._succ_from)
sepIndex = attrs['lane'].rindex('_')
toEdge = attrs['lane'][:sepIndex]
toIdx = attrs['lane'][sepIndex + 1:]
self.checkWrite(' to="%s"' % toEdge)
self.checkWrite(' fromLane="%s"' % self._succ_fromIdx)
self.checkWrite(' toLane="%s"' % toIdx)
if name == "net":
self.checkWrite(
' version="0.13" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
'xsi:noNamespaceSchemaLocation="http://sumo.dlr.de/xsd/net_file.xsd"')
else:
if name in a:
for key in a[name]:
val = None
if key in renamedAttrs and renamedAttrs[key] in attrs:
key = renamedAttrs[key]
if key in attrs:
val = attrs[key]
if key in renamedValues:
val = renamedValues[key].get(val, val)
if name == "succlane" and (key == "linkno" or key == "linkIndex") and attrs["tl"] == '':
val = ''
if name not in b or key not in b[name] or val != b[name][key]:
self.checkWrite(
' ' + renamedAttrs.get(key, key) + '="%s"' % val)
elif name == "lane" and key == "index":
self.checkWrite(' %s="%s"' % (key, self._laneCount))
self._laneCount += 1
elif name == "connection" and key == "fromLane":
self.checkWrite(
' fromLane="%s" toLane="%s"' % tuple(attrs["lane"].split(":")))
if self.isSingle(name):
self.checkWrite("/>\n")
else:
self.checkWrite(">\n")
self._tree.append(name)
if name == "junction":
for logicitem_attrs in self._logicitems[attrs["id"]]:
self.indent()
self.checkWrite("<request")
self.checkWrite(' index="%s"' % logicitem_attrs["request"])
for key in a["logicitem"]:
if key in logicitem_attrs:
self.checkWrite(' ' + key + '="%s"' %
logicitem_attrs[key])
self.checkWrite("/>\n")
def endElement(self, name):
if name == "row-logic" or name == "ROWLogic":
self._am_parsing_rowlogic = None
if self.remove(name):
return
self._tree.pop()
if name == "net":
self.checkWrite("\n")
if not self.isSingle(name):
self.indent()
if self.rename(name):
self.checkWrite("</" + RENAMED_TAGS[name] + ">")
else:
self.checkWrite("</" + name + ">")
if name != "net":
self.checkWrite("\n")
def characters(self, content):
self._content += content
def processingInstruction(self, target, data):
self.checkWrite('<?%s %s?>' % (target, data))
def changeFile(fname):
if options.verbose:
print("Patching " + fname + " ...")
if (("_deprecated_" in fname and "net.netconvert" not in fname) or
(os.path.join('tools', 'net', '0') in fname)):
print(
"Skipping file (looks like intentionally deprecated input): " + fname)
return
has_no_destination = False
if "SUMO_NO_DESTINATION" in open(fname).read():
print(
"Partial conversion (cannot convert SUMO_NO_DESTINATION): " + fname)
has_no_destination = True
net = NetConverter(fname + ".chg", getBegin(fname), has_no_destination)
try:
parse(fname, net)
except xml.sax._exceptions.SAXParseException:
print("Could not parse '%s' maybe it contains non-ascii chars?" %
fname)
if options.inplace:
os.remove(fname)
os.rename(fname + ".chg", fname)
def changeEdgeFile(fname):
if options.verbose:
print("Patching " + fname + " ...")
out = open(fname + ".chg", 'w')
for line in open(fname):
if "<lane" in line:
line = line.replace(" id", " index")
if "<edge" in line:
line = line.replace(" fromnode", " from").replace(" tonode", " to")
line = line.replace(" spread_type", " spreadType").replace(
" maxspeed", " maxSpeed")
line = line.replace(" nolanes", " numLanes")
out.write(line)
out.close()
if options.inplace:
os.remove(fname)
os.rename(fname + ".chg", fname)
def changeConnectionFile(fname):
if options.verbose:
print("Patching " + fname + " ...")
out = open(fname + ".chg", 'w')
for line in open(fname):
if "<connection" in line and "lane" in line:
line = line.replace(" lane", " fromLane")
for i in range(10):
line = line.replace(':%s"' % i, '" toLane="%s"' % i)
out.write(line)
out.close()
if options.inplace:
os.remove(fname)
os.rename(fname + ".chg", fname)
def walkDir(srcRoot):
for root, dirs, files in os.walk(srcRoot):
for name in files:
if name.endswith(".net.xml") or name in ["net.netconvert", "net.netgen",
"tls.scenario", "net.scenario"]:
changeFile(os.path.join(root, name))
if options.edges and name.endswith(".edg.xml"):
changeEdgeFile(os.path.join(root, name))
elif options.connections and name.endswith(".con.xml"):
changeConnectionFile(os.path.join(root, name))
for ignoreDir in ['.svn', 'foreign']:
if ignoreDir in dirs:
dirs.remove(ignoreDir)
optParser = OptionParser()
optParser.add_option("-v", "--verbose", action="store_true",
default=False, help="tell me what you are doing")
optParser.add_option("-i", "--inplace", action="store_true",
default=False, help="replace original files")
optParser.add_option("-e", "--edges", action="store_true",
default=False, help="include edge XML files")
optParser.add_option("-c", "--connections", action="store_true",
default=False, help="include connection XML files")
(options, args) = optParser.parse_args()
if len(args) == 0:
print("Usage: " + sys.argv[0] + " <net>+")
sys.exit()
for arg in args:
for fname in glob.glob(arg):
if os.path.isdir(fname):
walkDir(fname)
else:
if options.edges and fname.endswith(".edg.xml"):
changeEdgeFile(fname)
elif options.connections and fname.endswith(".con.xml"):
changeConnectionFile(fname)
else:
changeFile(fname)