# How graphviz2drawio Converts Graphviz Clusters and Subgraphs to Draw.io

> Learn how graphviz2drawio converts Graphviz clusters and subgraphs to Draw.io. Discover the method of rendering DOT to SVG, parsing groups, and preserving visual layering for seamless diagramming.

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

---

**graphviz2drawio converts Graphviz clusters into rectangular container nodes in Draw.io by rendering the DOT file to SVG, parsing cluster groups, and inserting them before inner nodes to preserve visual layering.**

The `hbmartin/graphviz2drawio` library bridges the gap between Graphviz graph descriptions and Draw.io diagrams. When your Graphviz source contains **clusters** (subgraphs with the `cluster` attribute), the tool follows a specific pipeline to transform these grouped containers into properly layered Draw.io shapes.

## The Conversion Pipeline

The conversion process follows eight distinct steps to transform Graphviz clusters into Draw.io-compatible XML.

### 1. Load and Normalize the Graph

The pipeline begins in [`graphviz2drawio/graphviz2drawio.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/graphviz2drawio.py) within the `_load_pygraphviz_agraph` function. This step normalizes user input—whether a file path, string, or `pygraphviz.AGraph` object—into a consistent `pygraphviz.AGraph` instance.

### 2. Render to SVG

The `convert` function renders the normalized graph using the specified layout engine (defaulting to `dot`). This produces SVG bytes that encode the visual structure, including cluster boundaries as `<g class="cluster">` elements.

### 3. Parse SVG Elements

In [`graphviz2drawio/models/SvgParser.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/models/SvgParser.py), the `parse_nodes_edges_clusters` method walks the SVG tree. It identifies three classes of top-level `<g>` elements: `node`, `edge`, and **`cluster`**. The parser specifically looks for the `cluster` class attribute to distinguish containers from regular nodes.

### 4. Extract Cluster Titles

For each cluster group, the parser extracts titles from preceding XML comments or inner `<title>` elements. If neither exists, the code raises a `MissingTitleError` to enforce proper labeling.

### 5. Build Cluster Nodes

The `NodeFactory.from_svg` function in [`graphviz2drawio/mx/NodeFactory.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/NodeFactory.py) constructs a `Node` object for each cluster. It applies **`labelloc="t"`** to position the title at the top and derives the shape from the SVG geometry (typically a rectangle).

### 6. Store Collections Separately

The parser returns three distinct collections: `nodes`, `edges`, and **`clusters`** (stored as an `OrderedDict` of `Node` objects). This separation allows the assembly stage to handle clusters differently from regular graph elements.

### 7. Assemble the Draw.io Model

In [`graphviz2drawio/mx/MxGraph.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/MxGraph.py), the `__init__` method receives all three collections. Crucially, it adds **clusters first** to the model. This ensures they render underneath ordinary nodes, matching Graphviz's visual convention where containers appear behind their contents.

### 8. Emit Final XML

The `MxGraph.value` method generates the final XML string. After all objects are added with proper layering, this method produces the complete Draw.io diagram ready for import.

## How Clusters Become Containers

In Draw.io, every visual element is a **cell**. Graphviz clusters function as rectangular containers that group other nodes, but Draw.io lacks a native "cluster" primitive. The conversion treats each cluster as a regular node with a rectangular shape, but leverages the rendering order to create the container effect.

By inserting cluster nodes before their inner contents in the XML sequence, graphviz2drawio ensures that Draw.io draws the background rectangle first. The cluster title persists as the node's `gid` attribute, displayed at the top via the `labelloc="t"` setting applied during node construction.

## Handling Non-Cluster Subgraphs

Graphviz supports sub-graphs that lack the `cluster` attribute. These structural groupings do not generate `<g class="cluster">` elements in the SVG output. Consequently, the SVG parser ignores them entirely.

Only sub-graphs explicitly declared as **`cluster`** survive the conversion process. Ordinary sub-graphs flatten into their constituent nodes and edges, losing their grouping container in the final Draw.io output.

## Code Examples

Convert a `.gv` file containing clusters:

```python
from graphviz2drawio import convert

drawio_xml = convert("examples/cluster_demo.gv")
with open("cluster_demo.drawio", "w") as f:
    f.write(drawio_xml)

```

Convert from a DOT string directly:

```python
dot_source = """
digraph G {
    subgraph cluster_A {
        label="Group A";
        a1 -> a2;
    }
    subgraph cluster_B {
        label="Group B";
        b1 -> b2;
    }
    a1 -> b1;
}
"""
drawio_xml = convert(dot_source)  # layout performed with 'dot'

```

Both examples produce Draw.io XML where *Group A* and *Group B* appear as rectangular containers with top-aligned titles, with internal nodes drawn above the container backgrounds.

## Key Implementation Files

- **[`graphviz2drawio/graphviz2drawio.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/graphviz2drawio.py)**: Contains the public `convert` API, handles SVG generation via `_load_pygraphviz_agraph`, and orchestrates the parsing and graph assembly pipeline.
- **[`graphviz2drawio/models/SvgParser.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/models/SvgParser.py)**: Implements `parse_nodes_edges_clusters` to walk the SVG tree, identify `<g class="cluster">` elements, and extract titles from comments or `<title>` tags.
- **[`graphviz2drawio/mx/NodeFactory.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/NodeFactory.py)**: Defines `NodeFactory.from_svg` to construct `Node` objects for clusters, applying `labelloc="t"` for top-positioned titles and storing the cluster name as `gid`.
- **[`graphviz2drawio/mx/MxGraph.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/MxGraph.py)**: Builds the final Draw.io XML structure in `MxGraph.__init__`, ensuring clusters populate the model before inner nodes to maintain correct visual layering, and emits output via `MxGraph.value`.

## Summary

- **graphviz2drawio** renders Graphviz DOT files to SVG, then parses the output to identify cluster containers via `<g class="cluster">` elements.
- Clusters are converted to rectangular **Node** objects with top-aligned titles using `labelloc="t"` and stored in an `OrderedDict` to preserve order.
- The tool inserts clusters into the Draw.io model before their contents, creating the visual effect of background containers.
- Only sub-graphs with the explicit `cluster` attribute are preserved; non-cluster sub-graphs flatten into individual nodes and edges.
- The conversion raises `MissingTitleError` if a cluster lacks a label or title element in the SVG.

## Frequently Asked Questions

### How does graphviz2drawio handle cluster labels?

The parser extracts cluster labels from XML comments preceding the `<g>` element or from inner `<title>` tags. If neither exists, the code raises a `MissingTitleError`. The label is stored as the node's `gid` and displayed at the top using `labelloc="t"`.

### Why do clusters appear as nodes in the Draw.io output?

Draw.io represents all diagram elements as cells without a native grouping container concept. graphviz2drawio treats clusters as rectangular nodes but renders them before their contents, creating the visual appearance of a background container that groups related elements.

### Can I convert Graphviz sub-graphs that are not clusters?

No. The SVG parser specifically filters for `<g class="cluster">` elements. Sub-graphs lacking the `cluster` attribute do not generate this class in the SVG output and are ignored during conversion, resulting in flattened node and edge structures.

### Which layout engines does graphviz2drawio support for cluster conversion?

The tool supports any layout engine available through pygraphviz, defaulting to `dot`. You can specify alternatives like `neato` or `fdp` when calling the `convert` function, though `dot` is recommended for proper hierarchical cluster layouts.