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

> Explore the models directory in graphviz2drawio. Learn how it converts Graphviz SVG to Python objects for draw.io diagram creation and unlocks seamless SVG-to-domain object conversion.

- Repository: [Harold Martin/graphviz2drawio](https://github.com/hbmartin/graphviz2drawio)
- Tags: deep-dive
- Published: 2026-03-03

---

**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`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/commented_tree_builder.py)**, which extends `ElementTree.TreeBuilder` to preserve XML comments as potential titles for diagram elements. Supporting utilities in **[`SVG.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/Rect.py)** and **[`CoordsTranslate.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/Arguments.py)**: Defines the CLI argument parser that feeds input files to the conversion pipeline
- **[`Errors.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/Errors.py)**: Centralizes custom exceptions including `MissingTitleError` and `UnableToParseGraphError` for meaningful error taxonomy
- **[`DotAttr.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/models/SvgParser.py) | Main SVG-to-model conversion logic; exports `parse_nodes_edges_clusters()` |
| [`graphviz2drawio/models/SVG.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/models/SVG.py) | Namespace utilities and tag helpers for SVG traversal |
| [`graphviz2drawio/models/Rect.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/models/Rect.py) | Rectangle geometry for node/cluster bounds and perimeter calculations |
| [`graphviz2drawio/models/CoordsTranslate.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/models/CoordsTranslate.py) | Coordinate transformation handling for Graphviz translate directives |
| [`graphviz2drawio/models/Arguments.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/models/Arguments.py) | Command-line interface parsing |
| [`graphviz2drawio/models/Errors.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/models/Errors.py) | Custom exception hierarchy for error handling |
| [`graphviz2drawio/models/DotAttr.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/models/DotAttr.py) | Constants for DOT edge and node styling attributes |
| [`graphviz2drawio/models/commented_tree_builder.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/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:

```python
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:

```python
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:

```python
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`](https://github.com/hbmartin/graphviz2drawio/blob/main/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:

```python

# 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`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/Rect.py)** for bounding boxes and **[`CoordsTranslate.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/CoordsTranslate.py)** for coordinate system transformations.
- Utility modules (**[`Arguments.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/Arguments.py)**, **[`Errors.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/Errors.py)**, **[`DotAttr.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio.py) to catch and handle distinct failure modes during the conversion pipeline.