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 pipelineErrors.py: Centralizes custom exceptions includingMissingTitleErrorandUnableToParseGraphErrorfor meaningful error taxonomyDotAttr.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.pyserves as the primary entry point, extracting nodes, edges, and clusters while preserving XML comments as titles.- Geometric operations rely on
Rect.pyfor bounding boxes andCoordsTranslate.pyfor 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
mxpackage 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →