SvgElement

SvgElement is the base wrapper used by pyDreamplet SVG objects. It owns an xml.etree.ElementTree.Element, normalizes Python-friendly attribute names, and provides the shared API for attributes, children, search, copying, and output.

Most users meet this API through concrete classes such as SVG, G, Rect, Circle, Path, and Text. Use SvgElement directly when pyDreamplet does not ship a specialized wrapper for an SVG tag.

Import

import pydreamplet as dp

Signature

dp.SvgElement(tag: str, **kwargs)
filter_node = dp.SvgElement("feDropShadow", dx=0, dy=4, stdDeviation=3)

Constructor Parameters

ParameterTypeRequiredDescription
tagstryesLocal SVG tag name, without the SVG namespace.
**kwargsAnynoSVG attributes. Names are normalized in the same way as attrs().

Type Names

The signatures on this page use the same type names as the current source:

TypeMeaning
Realint | float
AttributeValuestr | int | float | None
PointLikeVector | tuple[Real, Real] | list[Real]
SelfThe concrete element type the method was called on.

SvgElement creates namespaced SVG elements, so serializing an element includes the root SVG namespace when needed.

node = dp.SvgElement("rect", x=10, y=20, width=80, height=40)

print(str(node))
# <rect xmlns="http://www.w3.org/2000/svg" x="10" y="20" width="80" height="40" />

The pydreamplet.core module also exposes namespace constants and helpers used by the wrapper layer:

NameMeaning
SVG_NSSVG namespace URI.
XML_NSXML namespace URI.
XLINK_NSXLink namespace URI.
qname(tag)Expands an SVG tag name to ElementTree namespace form.
ns_attr(prefix, name)Expands an XML or XLink attribute name.

These helpers are useful when mixing pyDreamplet wrappers with raw xml.etree.ElementTree elements.

Attribute Names

Keyword and dictionary attribute names use Python identifiers. pyDreamplet maps common Python names to SVG names:

Python nameSVG attribute
class_nameclass
stroke_widthstroke-width
font_sizefont-size
preserve_aspect_ratiopreserve-aspect-ratio
xml_spaceXML namespaced space attribute
xlink_hrefXLink namespaced href attribute
rect = dp.Rect(
    x=20,
    y=20,
    width=120,
    height=70,
    class_name="panel",
    stroke_width=3,
)

print(rect.class_name)    # panel
print(rect.stroke_width)  # 3

Dynamic attribute reads convert simple numeric strings to int or float. id is always returned as a string so leading zeroes are preserved.

mark = dp.Circle(id="001", cx=50, cy=50, r=12, opacity=0.75)

print(mark.id)       # 001
print(mark.opacity)  # 0.75

Assigning None removes an attribute.

mark.fill = "#14b8a6"
mark.fill = None

print(mark.has_attr("fill"))  # False

Attribute Methods

attrs

element.attrs(attributes: dict[str, object]) -> Self

Sets several attributes and returns the same object for chaining.

rect = dp.Rect().attrs({
    "x": 24,
    "y": 32,
    "width": 160,
    "height": 90,
    "fill": "#14b8a6",
    "stroke_width": 4,
})

Values set to None remove the corresponding attribute.

rect.attrs({"stroke_width": None})

set_attr

element.set_attr(name: str, value: AttributeValue) -> Self

Sets or removes one attribute.

rect.set_attr("data-state", "active")
rect.set_attr("data-state", None)

Convenience Setters

element.set_id(value: str | None) -> Self
element.set_class(value: str | None) -> Self
element.set_fill(value: AttributeValue) -> Self
element.set_stroke(value: AttributeValue, width: AttributeValue = None, linecap: str | None = None, linejoin: str | None = None) -> Self
element.set_style(value: str | Mapping[str, AttributeValue] | None) -> Self
element.set_position(x: PointLike | Real, y: Real | None = None) -> Self
element.set_size(width: AttributeValue, height: AttributeValue) -> Self

set_position() writes cx and cy for circles and ellipses. For other tags, it writes x and y.

circle = dp.Circle(r=18).set_position((40, 50))
rect = dp.Rect().set_position(20, 30).set_size(120, 80)

set_style() accepts either a CSS string or a dictionary. Dictionary keys use the same underscore-to-hyphen convention as SVG attributes.

rect.set_style({
    "paint_order": "stroke",
    "vector_effect": "non-scaling-stroke",
})

normalize_attrs

dp.SvgElement.normalize_attrs(attrs: dict[str, object]) -> dict[str, object]

Returns a new attribute dictionary with Python-friendly names converted to SVG attribute names. It is the same normalization used by constructors, attrs(), and set_attr().

attrs = dp.SvgElement.normalize_attrs({
    "stroke_width": 2,
    "class_name": "mark",
    "xlink_href": "#shape",
})

print(attrs)
# {'stroke-width': 2, 'class': 'mark', '{http://www.w3.org/1999/xlink}href': '#shape'}

Children

append

element.append(*children) -> Self

Appends one or more children and returns the parent.

group = dp.G(id="marks").append(
    dp.Circle(cx=40, cy=40, r=12),
    dp.Circle(cx=80, cy=40, r=12),
)

Children can be pyDreamplet wrappers or raw ElementTree elements.

remove

element.remove(*children) -> Self

Removes one or more children from the element.

circle = dp.Circle(cx=40, cy=40, r=12)
group.append(circle)
group.remove(circle)

find

element.find(tag: str, nested: bool = False, id: str | None = None)

Returns the first matching child, or None.

svg = dp.SVG(200, 100)
svg.append(dp.G(id="marks").append(dp.Circle(cx=40, cy=40, r=12)))

group = svg.find("g", id="marks")
circle = svg.find("circle", nested=True)

find_all

element.find_all(tag: str, nested: bool = False, class_name: str | None = None) -> list[SvgElement]

Returns every matching child.

marks = svg.find_all("circle", nested=True, class_name="mark")

Known tags are wrapped in their specialized pyDreamplet classes, so searching for "rect" returns Rect objects, searching for "g" returns G objects, and so on. Returned wrappers are live views over the existing tree.

Output

to_string

element.to_string(pretty_print: bool = True) -> str

Serializes the element. str(element) uses compact output.

pretty = group.to_string()
compact = str(group)

copy

element.copy() -> Self

Creates a deep copy of the wrapper and its XML subtree.

original = dp.Rect(x=10, y=10, width=80, height=40)
variant = original.copy()
variant.fill = "#f83898"

Mutating variant does not change original.

Extending The Registry

dp.SvgElement.register(tag: str, subclass: type[SvgElement]) -> None
dp.SvgElement.from_element(element: xml.etree.ElementTree.Element) -> SvgElement

pyDreamplet registers its built-in SVG classes at import time. You only need register() when you create your own wrapper class and want find() or find_all() to return that class for a custom tag.