#!/usr/bin/env python3

#simple script replacing style/class definition with fill attribute in SVG files
#in order to make SVG copmatible with Flash

import sys
#import xml.etree.ElementTree as ET
#using lxml instead of standard library for wildcard support in find() iter() as workaround for XML namespaces headache.
from lxml import etree as ET

#command line parameters
if len(sys.argv) != 3 or sys.argv[1][0] == '-':
    print ("Usage: ", sys.argv[0], "<inputfile> <outputfile>")
    sys.exit()

inputfile = sys.argv[1]
outputfile = sys.argv[2]

#----- file test -----
try:
    infile = open(inputfile, "r")
except IOError:
    print ("File",inputfile,"not found or can't be opened in read mode.")
    sys.exit()

#------ parse XML -----
tree = ET.parse(infile)
infile.close()
#there should be xml.etree.ElementTree.ParseError check and report
root = tree.getroot()
if root is None:
    print("XML parse failed, no root.")
else:
    print("XML parsed, root is", root.tag)

stylestring = ""
#search for style tag(s); could use itertext instead to get tag inner text directly
for styletag in root.itertext("{*}style"):
    stylestring += styletag

if len(stylestring) == 0:
    print("No style tag found.")
    sys.exit()

#------- parse style string into stylename:fill dictionary
#parse style string from format ".cls-1{fill:#666;}.cls-1,.cls-10,.cls-9{fill-rule:evenodd;}.cls-2{fill:#333;}.cls-3{fill:#828282;}" into cls-x : fill dictionary
stylecount = 0
styledict = {}
stylelist = stylestring.split('.cls-')
for style in stylelist:
    if "{fill:" in style:
        stylecount += 1
        stylebr = style.split("{fill:")
        stylename = "cls-" + stylebr[0]
        stylefill = stylebr[1].split(";")
        styledict[stylename] = stylefill[0]

print("Found", len(stylelist), "styles with", stylecount, "fills.")

#------ find all path tags with class attribute -----
pathcount = 0
pathclasscount = 0
classindict = 0
for path in root.iter("{*}path"):
    pathcount += 1
    if "class" in path.attrib:
        pathclasscount += 1
        cls = path.get("class")
        if cls in styledict:
            classindict += 1
            # replace class attribute with fill=%s fill-rule="evenodd" stroke="none" attribs
            path.set("fill", styledict[cls])
            path.set("fill-rule", "evenodd")
            path.set("stroke", "none")
            del path.attrib["class"]

print("Found", pathcount, "path tags, of which", pathclasscount, "had class attribute, of which", classindict, "has fill defined in style tag and were replaced with fill attribute.")

#------ defs cleanup -----
if classindict == pathclasscount:
    #style tag is unnecessary
    for defstag in root.iter("{*}defs"):
        for styletag in defstag.iter("{*}style"):
            defstag.remove(styletag)
        #Now delete defs tag, but I don't know how test that it has no other child nodes

#------ save file and exit -----
if classindict == 0:
    print ("Nothing replaced, no file written.")
    sys.exit()

#check output file in read mode first, ask for overwrite if it exists
try:
    outfile = open(outputfile, "r")

except IOError:
    #nothing to overwrite, skip warning
    print ("Output file to be created new.")

else:
    print ("File",outputfile,"already exists. Overwrite?")
    yesorno = input("(y/n) ")
    if yesorno[0] != 'y' and yesorno[0] != 'Y':
        sys.exit()
    outfile.close()

#now try to overwrite it
try:
    outfile = open(outputfile, "w")

except IOError:
    print ("Cannot open file",outputfile,"in write mode. Check valid file name and permissions.")
    sys.exit()

#close file for now because etree write() prefers to open it itself
outfile.close()
#lxml write() doesn't work with file parameter, using file name instead
tree.write(outputfile, encoding="UTF-8", pretty_print=True)
