- SVG parsing, manipulation, and writing
- Support for all SVG 1.1 elements and attributes
- Support for special XML elements (
CDATA
, comments, text) - Attributes are parsed into native Python types for easy manipulation
- Highly configurable formatting options:
- indentation level
- maximum precision for floating-point numbers
- color mode (
rgb
,rgba
,hsl
,hex
,named
) - relative/absolute path commands
- scientific notation for small/large numbers
- and many more...
- Strong type safety:
- one class per distinct SVG element
- typed attributes
- runtime validation thanks to pydantic
- Support for all beautifulsoup4 parsers (e.g.,
html.parser
,lxml
,html5lib
)
---
title: Element hierarchy
---
graph TD
Element:::abc --> TextElement
Element --> Tag
Tag:::abc --> PairedTag
PairedTag:::abc --> G
PairedTag --> Svg
PairedTag --> etc1[...]
Tag --> Rect
Tag --> Circle
Tag --> etc2[...]
TextElement:::abc --> RawText
TextElement --> Comment
TextElement --> CData
etc1:::etc
etc2:::etc
classDef abc stroke:white,stroke-width:2px;
classDef etc stroke:gray,stroke-width:2px;
classDef default stroke:orange,stroke-width:2px;
From PyPi:
pip install svglab
From source:
# Via HTTPS
pip install git+/~https://github.com/reznakt/svglab.git
# Via SSH
pip install git+ssh://git@github.com/reznakt/svglab.git
from svglab import (
CData,
Comment,
G,
Path,
Polyline,
RawText,
Rect,
parse_svg,
)
from svglab.attrparse import Color, D, Length, Point, SkewX, Translate
from svglab.serialize import Formatter, set_formatter
# Configure custom formatting options
set_formatter(Formatter(indent=4, max_precision=2, color_mode="rgb"))
# Parse an existing SVG file
svg = parse_svg(
"""
<svg xmlns="http://www.w3.org/2000/svg">
<g>
<rect
id="background"
width="100cm"
height="100%"
transform="rotate(45)"
stroke="red"
/>
<rect color="hsl(0, 100%, 100%)"/>
<!-- This is a comment -->
<![CDATA[.background { fill: blue; }]]>
Hello SVG!
<path d="M 10,10 L 100,100 Q 100,100 50,50 Z"/>
<polygon points="0,0 100,0 100,100 0,100"/>
</g>
</svg>
"""
)
print(svg)
# Create an element programmatically
group = G().add_children(
Rect(
width=Length(15, "px"),
height=Length(20),
transform=[SkewX(45.123), Translate(10, 20)],
color=Color("#ff0000"),
),
Comment("This is a comment"),
CData(".background { fill: blue; }"),
RawText("Hello SVG!"),
Path(
d=D()
.move_to(Point(10, 10))
.line_to(Point(100, 100))
.quadratic_bezier_to(Point(100, 100), Point(50, 50))
.move_to(Point(50, 50))
.cubic_bezier_to(
Point(100, 100), Point(100, 100), Point(10, 10)
)
.arc_to(
Point(50, 50), 90, Point(100, 100), large=True, sweep=False
)
.close()
),
Polyline(
points=[
Point(0, 0),
Point(100, 0),
Point(100, 100),
Point(0, 100),
],
stroke_linecap="square",
opacity=0.5,
),
)
# Add the element to the SVG
svg.add_child(group)
# Manipulate attributes
print(svg.xmlns) # http://www.w3.org/2000/svg
svg.x = Length(10, "px")
# Save to a file
svg.save("output.svg")
# Search the element tree
print(svg.find(G).find(Rect).width)
print(*svg.find_all(Rect), sep="\n")
# Install dependencies
poetry install
# Activate the virtual environment
poetry shell
# Optional: Install pre-commit hooks
pre-commit install
# Run tests
poe test
# Run type checker
poe typecheck
# Run linter
poe lint
# Fix linting errors
poe lint-fix
# Run formatter
poe format
# Fix formatting errors
poe format-fix
This software is distributed under the MIT License. See LICENSE
for more information.