Skip to content
Snippets Groups Projects
normalize_svg.py 2.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • Pregmodder's avatar
    Pregmodder committed
    #!/usr/bin/env python3
    
    '''
    Application for "fixing" SVGs edited with Inkscape
    
    These problems are addressed:
    
    * Inkscape notoriously copies class styles into the object definitions.
    https://bugs.launchpad.net/inkscape/+bug/167937
    
    * Inkscape uses labels on layers. Layers are basically named groups. 
      Inkscape does not sync the group id with the layer label.
      
    Usage Example:
    python3 inkscape_svg_fixup.py vector_source.svg
    '''
    
    import lxml.etree as etree
    import sys
    
    
    Pregmodder's avatar
    Pregmodder committed
    def fix(tree):
      # know namespaces
      ns = {
        'svg' : 'http://www.w3.org/2000/svg',
        'inkscape' : 'http://www.inkscape.org/namespaces/inkscape'
      }
    
    Pregmodder's avatar
    Pregmodder committed
      
    
    Pregmodder's avatar
    Pregmodder committed
      # find document global style definition
      # mangle it and interpret as python dictionary
      style_element = tree.find('./svg:style',namespaces=ns)
      style_definitions = style_element.text
      pythonic_style_definitions = '{'+style_definitions.\
      replace('\t.','"').replace('{','":"').replace('}','",').\
      replace('/*','#')+'}'
      styles = eval(pythonic_style_definitions)
    
      # go through all SVG elements
      for elem in tree.iter():
        if (elem.tag == etree.QName(ns['svg'], 'g')):
          # compare inkscape label with group element ID
          l = elem.get(etree.QName(ns['inkscape'], 'label'))
          if l:
            i = elem.get('id')
            if (i != l):
              print("Overwriting ID %s with Label %s..."%(i, l))
              elem.set('id', l)
        
        # remove all offending style attributes
        s = elem.get('style')
        c = elem.get('class')
        if (c and s):
          s = s.lower()
          c = c.split(' ')[0] # regard main style only
          cs = ''
          if c in styles:
            cs = styles[c].strip('; ').lower()
          if (c not in styles):
            print("Object id %s references unknown style class %s."%(i,c))
          else:
            if (cs != s.strip('; ')):
              print("Style %s removed from object id %s differed from class %s style %s."%(s,i,c,cs))
            del elem.attrib["style"]
    
    Pregmodder's avatar
    Pregmodder committed
    
    
    Pregmodder's avatar
    Pregmodder committed
    if __name__ == "__main__":
      input_file = sys.argv[1]
      tree = etree.parse(input_file)
      fix(tree)
      # store SVG into file (input file is overwritten)
      svg = etree.tostring(tree, pretty_print=True)
      with open(input_file, 'wb') as f:
        f.write('<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'.encode("utf-8"))
        f.write(svg)