Skip to content
SVG parser based on lxml.etree
Branch: develop
Clone or download
Pull request Compare This branch is even with miute:develop.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
licenses
svgpy
tests
.gitignore
Pipfile
Pipfile.lock
README.adoc
implementation-status-css.adoc
implementation-status-dom.adoc
implementation-status-svg.adoc
setup.py

README.adoc

[WIP] svg.py

SVG parser based on lxml.etree.

This project aims to implement an SVG 2 DOM API.

Usage

  1. Parsing from files

    >>> from svgpy import SVGParser
    >>> parser = SVGParser(remove_comments=True)
    >>> doc = parser.create_document('http://www.w3.org/2000/svg')
    >>> doc.location.assign('https://raw.githubusercontent.com/miute/svgpy/master/tests/svg/svg.svg')
    >>> print(doc.tostring(pretty_print=True).decode())
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="100" viewBox="0 0 100 100">
     <g id="gtop" stroke-width="12" stroke="#000">
       <g id="svgstar" transform="translate(50,50)">
         <path id="svgbar" d="M-27-5a7,7,0,1,0,0,10h54a7,7,0,1,0,0-10z"/>
         <use id="use1" xlink:href="#svgbar" transform="rotate(45)"/>
         <use id="use2" xlink:href="#svgbar" transform="rotate(90)"/>
         <use id="use3" xlink:href="#svgbar" transform="rotate(135)"/>
       </g>
     </g>
     <use id="usetop" xlink:href="#svgstar" fill="#FB4"/>
    </svg>
    
    >>> for element in doc.document_element.iter():
    ...     print((element.node_type, element.node_name, element.id))
    ...
    (1, 'svg', '')
    (1, 'g', 'gtop')
    (1, 'g', 'svgstar')
    (1, 'path', 'svgbar')
    (1, 'use', 'use1')
    (1, 'use', 'use2')
    (1, 'use', 'use3')
    (1, 'use', 'usetop')
    >>> element = doc.get_element_by_id('usetop')
    >>> element.attributes
    {'id': 'usetop', '{http://www.w3.org/1999/xlink}href': '#svgstar', 'fill': '#FB4'}
    >>> bbox = element.get_bbox()
    >>> bbox.x, bbox.y, bbox.width, bbox.height
    (11.101020514433644, 11.101020514433644, 77.79795897113272, 77.79795897113272)
    >>> element = doc.get_element_by_id('svgbar')
    >>> element.attributes
    {'id': 'svgbar', 'd': 'M-27-5a7,7,0,1,0,0,10h54a7,7,0,1,0,0-10z'}
    >>> bbox = element.get_bbox()
    >>> bbox.x, bbox.y, bbox.width, bbox.height
    (-38.89897948556636, -7.0000009993777565, 77.79795897113272, 14.000001998755515)
    >>> element.get_total_length()
    173.68771160294722
  2. Serialization

    >>> from svgpy import SVGParser
    >>> parser = SVGParser()
    >>> doc = parser.create_svg_document()
    >>> root = doc.document_element
    >>> root.attributes.update({'width': '10cm', 'height': '3cm', 'viewBox': '0 0 1000 300'})
    >>> text = doc.create_element_ns('http://www.w3.org/2000/svg', 'text')
    >>> root.append(text)
    >>> text.style.update({'font-family': 'Verdana', 'font-size': '55', 'fill': 'blue'})
    >>> tspan = doc.create_element_ns('http://www.w3.org/2000/svg', 'tspan')
    >>> text.append(tspan)
    >>> tspan.attributes.update({'x': '250', 'y': '150', 'rotate': '-30,0,30'})
    >>> tspan.text = 'Hello, out there'
    >>> print(doc.tostring(pretty_print=True).decode())
    <svg xmlns="http://www.w3.org/2000/svg" width="10cm" height="3cm" viewBox="0 0 1000 300">
      <text style="fill: blue; font-family: Verdana; font-size: 55;">
        <tspan x="250" y="150" rotate="-30,0,30">Hello, out there</tspan>
      </text>
    </svg>
    
    >>> tree = root.getroottree()
    >>> tree.write('output.svg', encoding='utf-8', pretty_print=True)
    $ cat output.svg
    <svg xmlns="http://www.w3.org/2000/svg" width="10cm" height="3cm" viewBox="0 0 1000 300">
      <text style="fill: blue; font-family: Verdana; font-size: 55;">
        <tspan x="250" y="150" rotate="-30,0,30">Hello, out there</tspan>
      </text>
    </svg>
  3. Path processing

    >>> from svgpy import PathParser, SVGParser, SVGPathSegment, formatter
    >>> parser = SVGParser()
    >>> path = parser.create_element_ns('http://www.w3.org/2000/svg', 'path')
    >>> path_data = list()
    >>> path_data.append(SVGPathSegment('M', 150, 10))
    >>> path_data.append(SVGPathSegment('B', 36))
    >>> path_data.append(SVGPathSegment('h', 47))
    >>> path_data.append(SVGPathSegment('b', 72))
    >>> path_data.append(SVGPathSegment('h', 47))
    >>> path_data.append(SVGPathSegment('b', 72))
    >>> path_data.append(SVGPathSegment('h', 47))
    >>> path_data.append(SVGPathSegment('b', 72))
    >>> path_data.append(SVGPathSegment('h', 47))
    >>> path_data.append(SVGPathSegment('z'))
    >>> path.set_path_data(path_data)
    >>> path.get_attribute('d')
    'M150,10 B36 h47 b72 h47 b72 h47 b72 h47 z'
    >>> bbox = path.get_bbox()
    >>> bbox.x, bbox.y, bbox.width, bbox.height
    (111.97620126437747, 10.0, 76.04759747124507, 72.32556312361845)
    >>> path.get_total_length()
    235.0
    >>> normalized = PathParser.normalize(path_data)  # convert to 'M', 'L', 'C' and 'Z' path command
    >>> path.set_path_data(normalized)
    >>> path.get_attribute('d')
    'M150,10 L188.023799,37.625907 173.5,82.325563 126.5,82.325563 111.976201,37.625907 Z'
    >>> formatter.precision
    6  # default precision for a floating point value
    >>> formatter.precision = 3
    >>> path.set_path_data(normalized)
    >>> path.get_attribute('d')
    'M150,10 L188.024,37.626 173.5,82.326 126.5,82.326 111.976,37.626 Z'
    >>> bbox = path.get_bbox()
    >>> bbox.x, bbox.y, bbox.width, bbox.height
    (111.976, 10.0, 76.048, 72.326)
    >>> path.get_total_length()
    235.00121335747357

License

This software is licensed under the Apache License 2.0.

You can’t perform that action at this time.