Understanding the Models Directory in graphviz2drawio: SVG-to-Domain Object Conversion

The models directory in graphviz2drawio serves as the core domain-model layer that transforms raw Graphviz SVG output into structured Python objects representing nodes, edges, and clusters for draw.io diagram generation.

The hbmartin/graphviz2drawio repository converts Graphviz DOT diagrams into draw.io-compatible XML. The models directory in graphviz2drawio acts as the critical abstraction layer between low-level SVG parsing and high-level diagram construction, encapsulating geometry, coordinate translation, and Graphviz attribute handling into clean, testable Python classes.

Core Responsibilities of the Models Layer

The models package isolates SVG complexity from the rest of the conversion pipeline. It handles three primary concerns: parsing Graphviz SVG output into semantic objects, managing geometric calculations for diagram elements, and providing utility modules for CLI interaction and error handling.

SVG Parsing and Element Extraction

graphviz2drawio/models/SvgParser.py contains the main entry point parse_nodes_edges_clusters(), which traverses the SVG tree to extract nodes, edges, and clusters. The module works in tandem with commented_tree_builder.py, which extends ElementTree.TreeBuilder to preserve XML comments as potential titles for diagram elements. Supporting utilities in SVG.py provide namespace-aware tag helpers like svg_tag(), get_title(), and is_tag() for robust XML traversal.

Geometric Primitives and Coordinate Systems

Diagram positioning relies on Rect.py and CoordsTranslate.py. The Rect class represents bounding rectangles for nodes and clusters, offering methods like closest_point_along_perimeter() to calculate edge attachment points. CoordsTranslate.py handles Graphviz-specific transform strings (e.g., translate(10 20)), converting them into usable coordinate offsets via from_svg_transform() and translate() methods.

Supporting Infrastructure

The directory includes several utility modules that support the conversion pipeline:

  • Arguments.py: Defines the CLI argument parser that feeds input files to the conversion pipeline
  • Errors.py: Centralizes custom exceptions including MissingTitleError and UnableToParseGraphError for meaningful error taxonomy
  • DotAttr.py: Holds string constants for Graphviz arrow styles, line styles, and other DOT attributes used when enriching nodes and edges

Key Files in the graphviz2drawio Models Directory

File Purpose
graphviz2drawio/models/SvgParser.py Main SVG-to-model conversion logic; exports parse_nodes_edges_clusters()
graphviz2drawio/models/SVG.py Namespace utilities and tag helpers for SVG traversal
graphviz2drawio/models/Rect.py Rectangle geometry for node/cluster bounds and perimeter calculations
graphviz2drawio/models/CoordsTranslate.py Coordinate transformation handling for Graphviz translate directives
graphviz2drawio/models/Arguments.py Command-line interface parsing
graphviz2drawio/models/Errors.py Custom exception hierarchy for error handling
graphviz2drawio/models/DotAttr.py Constants for DOT edge and node styling attributes
graphviz2drawio/models/commented_tree_builder.py XML comment preservation for title extraction

Working with the Models Layer

These Python classes operate between the raw SVG generation and the final draw.io XML output. The following examples demonstrate direct interaction with the models layer as implemented in the hbmartin/graphviz2drawio source code.

Parsing SVG Data into Model Objects

The primary entry point converts pygraphviz output into structured models:

from graphviz2drawio.models.SvgParser import parse_nodes_edges_clusters
from pygraphviz import AGraph

# Load a Graphviz file with pygraphviz

graph = AGraph("example.dot")
svg_bytes = graph.draw(prog="dot", format="svg")

# Transform SVG into model objects

nodes, edges, clusters = parse_nodes_edges_clusters(
    svg_data=svg_bytes,
    is_directed=graph.directed,
)

print("Nodes:", list(nodes.keys()))
print("Edges:", [e.key_for_label for e in edges])
print("Clusters:", list(clusters.keys()))

Calculating Geometry with Rect

Use the Rect class to compute boundary points for edge routing:

from graphviz2drawio.models.Rect import Rect

# Define a node rectangle at position (10, 20) with size 120×80

node_rect = Rect(x=10, y=20, width=120, height=80)

# Calculate closest perimeter point to external coordinate (100, 200)

px, py = node_rect.closest_point_along_perimeter(100, 200)
print(f"Closest perimeter point: ({px}, {py})")

Translating Graphviz Coordinates

Handle SVG transform attributes using the coordinate translation utility:

from graphviz2drawio.models.CoordsTranslate import CoordsTranslate

# Parse Graphviz transform string

coords = CoordsTranslate.from_svg_transform("translate(30 40)")

# Apply translation to a point (5, 7)

new_x, new_y = coords.translate(5, 7)
print(f"Translated point: ({new_x}, {new_y})")

Integration with the Conversion Pipeline

The models layer operates within the high-level flow defined in graphviz2drawio/graphviz2drawio.py. After pygraphviz generates SVG output, the models package transforms that raw XML into objects that the mx package (draw.io XML generator) consumes:


# Pipeline flow from graphviz2drawio.py

svg = graph.draw(prog=layout_prog, format="svg")          # pygraphviz output

nodes, edges, clusters = parse_nodes_edges_clusters(      # models layer

    svg_data=svg,
    is_directed=graph.directed,
)
mx_graph = MxGraph(clusters, nodes, edges)               # mx package builds draw.io XML

This architecture ensures the models directory remains the single source of truth for SVG interpretation, allowing the rest of the repository to manipulate diagram elements without managing XML minutiae directly.

Summary

  • The models directory in graphviz2drawio functions as the domain-model layer, bridging Graphviz SVG output and draw.io XML generation.
  • SvgParser.py serves as the primary entry point, extracting nodes, edges, and clusters while preserving XML comments as titles.
  • Geometric operations rely on Rect.py for bounding boxes and CoordsTranslate.py for coordinate system transformations.
  • Utility modules (Arguments.py, Errors.py, DotAttr.py) provide CLI parsing, error taxonomy, and DOT attribute constants.
  • All model objects feed into the mx package to produce the final draw.io-compatible XML structure.

Frequently Asked Questions

What is the main entry point for converting SVG to model objects in graphviz2drawio?

The function parse_nodes_edges_clusters() in graphviz2drawio/models/SvgParser.py serves as the primary entry point. It accepts SVG byte data and a boolean indicating graph direction, then returns tuples of parsed nodes, edges, and clusters as Python objects ready for draw.io XML generation.

How does graphviz2drawio preserve XML comments from Graphviz SVG output?

The module graphviz2drawio/models/commented_tree_builder.py extends ElementTree.TreeBuilder to intercept and preserve XML comments during parsing. The SvgParser treats these preserved comments as potential titles for nodes and clusters, ensuring diagram metadata survives the conversion process.

Which class handles coordinate transformations in the models directory?

The CoordsTranslate class in graphviz2drawio/models/CoordsTranslate.py manages coordinate transformations. It parses Graphviz-style transform strings like translate(30 40) via the from_svg_transform() factory method and applies offsets to points using the translate() method, ensuring accurate positioning in the draw.io canvas.

What exceptions does the models layer define for error handling?

The graphviz2drawio/models/Errors.py module defines a custom exception hierarchy including MissingTitleError for nodes lacking identifiers and UnableToParseGraphError for malformed SVG input. These specific exceptions allow calling code in graphviz2drawio.py to catch and handle distinct failure modes during the conversion pipeline.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →