In processing an SVG file in preparation for display, I find myself in need of information from parent "g" tags as well as the global "style" tag. What do you think of this change that allows for exporting all that information to the caller?
diff --git a/svgpathtools/svg_to_paths.py b/svgpathtools/svg_to_paths.py
index 65591af..9edf200 100644
--- a/svgpathtools/svg_to_paths.py
+++ b/svgpathtools/svg_to_paths.py
@@ -3,7 +3,7 @@ The main tool being the svg2paths() function."""
# External dependencies
from __future__ import division, absolute_import, print_function
-from xml.dom.minidom import parse
+from xml.dom.minidom import parse, Node
import os
from io import StringIO
import re
@@ -136,6 +136,8 @@ def line2pathd(l):
def svg2paths(svg_file_location,
return_svg_attributes=False,
+ return_other_tags=None,
+ include_parent_info=False,
convert_circles_to_paths=True,
convert_ellipses_to_paths=True,
convert_lines_to_paths=True,
@@ -182,61 +184,86 @@ def svg2paths(svg_file_location,
doc = parse(svg_file_location)
- def dom2dict(element):
- """Converts DOM elements to dictionaries of attributes."""
- keys = list(element.attributes.keys())
- values = [val.value for val in list(element.attributes.values())]
+ def dom2dict(element, include_parents=False):
+ """Converts DOM elements to dictionaries of attributes, including parent information."""
+ if element.attributes is not None:
+ keys = list(element.attributes.keys())
+ values = [val.value for val in list(element.attributes.values())]
+ else:
+ keys = []
+ values = []
+ if include_parents:
+ keys.append('_tag')
+ values.append(element.tagName)
+ parent = element.parentNode
+ if parent is not None and parent.nodeType == Node.ELEMENT_NODE and parent.tagName != 'svg':
+ keys.append('_parent')
+ values.append(dom2dict(parent, True))
return dict(list(zip(keys, values)))
+ # Short name for all the dom2dict calls below
+ ip = include_parent_info
+
# Use minidom to extract path strings from input SVG
- paths = [dom2dict(el) for el in doc.getElementsByTagName('path')]
+ paths = [dom2dict(el,ip) for el in doc.getElementsByTagName('path')]
d_strings = [el['d'] for el in paths]
attribute_dictionary_list = paths
# Use minidom to extract polyline strings from input SVG, convert to
# path strings, add to list
if convert_polylines_to_paths:
- plins = [dom2dict(el) for el in doc.getElementsByTagName('polyline')]
+ plins = [dom2dict(el,ip) for el in doc.getElementsByTagName('polyline')]
d_strings += [polyline2pathd(pl) for pl in plins]
attribute_dictionary_list += plins
# Use minidom to extract polygon strings from input SVG, convert to
# path strings, add to list
if convert_polygons_to_paths:
- pgons = [dom2dict(el) for el in doc.getElementsByTagName('polygon')]
+ pgons = [dom2dict(el,ip) for el in doc.getElementsByTagName('polygon')]
d_strings += [polygon2pathd(pg) for pg in pgons]
attribute_dictionary_list += pgons
if convert_lines_to_paths:
- lines = [dom2dict(el) for el in doc.getElementsByTagName('line')]
+ lines = [dom2dict(el,ip) for el in doc.getElementsByTagName('line')]
d_strings += [('M' + l['x1'] + ' ' + l['y1'] +
'L' + l['x2'] + ' ' + l['y2']) for l in lines]
attribute_dictionary_list += lines
if convert_ellipses_to_paths:
- ellipses = [dom2dict(el) for el in doc.getElementsByTagName('ellipse')]
+ ellipses = [dom2dict(el,ip) for el in doc.getElementsByTagName('ellipse')]
d_strings += [ellipse2pathd(e) for e in ellipses]
attribute_dictionary_list += ellipses
if convert_circles_to_paths:
- circles = [dom2dict(el) for el in doc.getElementsByTagName('circle')]
+ circles = [dom2dict(el,ip) for el in doc.getElementsByTagName('circle')]
d_strings += [ellipse2pathd(c) for c in circles]
attribute_dictionary_list += circles
if convert_rectangles_to_paths:
- rectangles = [dom2dict(el) for el in doc.getElementsByTagName('rect')]
+ rectangles = [dom2dict(el,ip) for el in doc.getElementsByTagName('rect')]
d_strings += [rect2pathd(r) for r in rectangles]
attribute_dictionary_list += rectangles
+ path_list = [parse_path(d) for d in d_strings]
+ retval = [path_list, attribute_dictionary_list]
+
if return_svg_attributes:
svg_attributes = dom2dict(doc.getElementsByTagName('svg')[0])
- doc.unlink()
- path_list = [parse_path(d) for d in d_strings]
- return path_list, attribute_dictionary_list, svg_attributes
- else:
- doc.unlink()
- path_list = [parse_path(d) for d in d_strings]
- return path_list, attribute_dictionary_list
+ retval.append(svg_attributes)
+
+ if return_other_tags is not None:
+ other_tags = {}
+ for other in return_other_tags:
+ other_tags[other] = []
+ elements = doc.getElementsByTagName(other)
+ for el in elements:
+ taginfo = dom2dict(el,ip)
+ taginfo['_value'] = el.firstChild.nodeValue if el.firstChild is not None else None
+ other_tags[other].append(taginfo)
+ retval.append(other_tags)
+
+ doc.unlink()
+ return retval
def svg2paths2(svg_file_location,
@@ -262,6 +289,8 @@ def svg2paths2(svg_file_location,
def svgstr2paths(svg_string,
return_svg_attributes=False,
+ return_other_tags=None,
+ include_parent_info=False,
convert_circles_to_paths=True,
convert_ellipses_to_paths=True,
convert_lines_to_paths=True,
@@ -275,6 +304,8 @@ def svgstr2paths(svg_string,
svg_file_obj = StringIO(svg_string)
return svg2paths(svg_file_location=svg_file_obj,
return_svg_attributes=return_svg_attributes,
+ return_other_tags=return_other_tags,
+ include_parent_info=include_parent_info,
convert_circles_to_paths=convert_circles_to_paths,
convert_ellipses_to_paths=convert_ellipses_to_paths,
convert_lines_to_paths=convert_lines_to_paths,
I can create a pull request if you don't think any changes are necessary.
In processing an SVG file in preparation for display, I find myself in need of information from parent "g" tags as well as the global "style" tag. What do you think of this change that allows for exporting all that information to the caller?
I can create a pull request if you don't think any changes are necessary.