39

I want to parse an SVG file using python to extract coordinates/paths (I believe this is listed under the "path" ID, specifically the d="..."/>). This data will eventually be used to drive a 2 axis CNC.

I've searched on SO and Google for libraries that can return the string of such paths so I can further parse it, but to no avail. Does such a library exist?

1
  • You could also have a look at VPYPE. Either as a stand-alone CLI, or maybe for the code (Python). Commented Jan 27, 2022 at 15:58

3 Answers 3

44

Ignoring transforms, you can extract the path strings from an SVG like so:

from xml.dom import minidom doc = minidom.parse(svg_file) # parseString also exists path_strings = [path.getAttribute('d') for path in doc.getElementsByTagName('path')] doc.unlink() 
Sign up to request clarification or add additional context in comments.

4 Comments

Do you have any suggestions for when transformations are important?
@Veech: If there is a transform, it is probably important. Unfortunately it takes a lot more code to handle them.
Yeah, I've come to realize that. I've found that cjlano's svg repo to be good enough (with some modifications).
Not every valid XML is a valid SVG.
15

Getting the d-string can be done in a line or two using svgpathtools.

from svgpathtools import svg2paths paths, attributes = svg2paths('some_svg_file.svg') 

paths is a list of svgpathtools Path objects (containing just the curve info, no colors, styles, etc.). attributes is a list of corresponding dictionary objects storing the attributes of each path.

To, say, print out the d-strings then...

for k, v in enumerate(attributes): print(v['d']) # print d-string of k-th path in SVG 

Comments

14

The question was about extracting the path strings, but in the end the line drawing commands were wanted. Based on the answer with minidom, I added the path parsing with svg.path to generate the line drawing coordinates:

#!/usr/bin/python3 # requires svg.path, install it like this: pip3 install svg.path # converts a list of path elements of a SVG file to simple line drawing commands from svg.path import parse_path from svg.path.path import Line from xml.dom import minidom # read the SVG file doc = minidom.parse('test.svg') path_strings = [path.getAttribute('d') for path in doc.getElementsByTagName('path')] doc.unlink() # print the line draw commands for path_string in path_strings: path = parse_path(path_string) for e in path: if isinstance(e, Line): x0 = e.start.real y0 = e.start.imag x1 = e.end.real y1 = e.end.imag print("(%.2f, %.2f) - (%.2f, %.2f)" % (x0, y0, x1, y1)) 

1 Comment

That is what I want! svg.path is more readable than svgpathtools, but svgpathtools packaged well. If you want to understand how to draw the curve by the SVG file then you can read svg.path, but use it with svgpathtools