# How Importing from draw.io Files Works and What Data Is Preserved

> Import draw.io files into cathrynlavery/diagram-design. Discover how the three-stage pipeline preserves identifiers, geometry, styling, hierarchy, and connectivity.

- Repository: [Cathryn Lavery/diagram-design](https://github.com/cathrynlavery/diagram-design)
- Tags: how-to-guide
- Published: 2026-08-19

---

**The `cathrynlavery/diagram-design` repository imports draw.io diagrams through a deterministic three-stage pipeline—format detection by `load_mxfile`, XML parsing into `Node` and `Edge` objects by `parse_page`, and serialization via `digest` or `to_json`—that preserves identifiers, geometry, styling, hierarchy, and connectivity without altering design intent.**

Importing from draw.io files is a foundational feature of the `diagram-design` skill, enabling external diagrams to be normalized into a structured format for automated analysis. The entire workflow is implemented in [`skills/diagram-design/scripts/drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/drawio_extract.py), which accepts raw XML, compressed payloads, PNG, or SVG inputs and returns a complete structural model. This article explains the exact pipeline and details which attributes survive the import process.

## The Pipeline for Importing from draw.io Files

The import logic lives entirely in [`skills/diagram-design/scripts/drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/drawio_extract.py) and proceeds through three deterministic stages. Each stage is handled by a dedicated function that transforms raw draw.io artifacts into a structured, language-agnostic representation.

### Stage 1: Detect and Decode the Input Format with `load_mxfile`

The `load_mxfile` function recognises raw XML, `.drawio` archives, PNG or SVG images containing an embedded `mxfile` chunk, and compressed base-64 payloads. It safely inflates compressed data with enforced size limits and returns the raw `<mxfile>` or `<mxGraphModel>` XML string, as implemented near lines 55–81.

### Stage 2: Parse the XML into an Intermediate Representation with `parse_page`

`parse_file` iterates over every `<diagram>` element and delegates to `parse_page`, which walks the `<mxGraphModel>` tree. Vertices are converted into `Node` objects that capture id, label, shape, parent, absolute geometry, style attributes, links, and custom attributes, while edges become `Edge` objects storing source, target, label, dash and bidirectional flags, stroke colour, and waypoint counts. These transformations are defined around lines 51–70 and 368–406.

### Stage 3: Serialize the IR with `digest` and `to_json`

After the intermediate representation is built, the script can emit either a human-readable Markdown digest via the `digest` function or a complete JSON payload via `to_json`. Both outputs retain the full set of nodes and edges together with page-level metadata such as hierarchy depth, shape counts, and candidate diagram types. This serialization layer is defined near lines 11–16.

## What Data Is Preserved When Importing from draw.io Files

The intermediate representation preserves a comprehensive set of draw.io properties, mapping raw XML attributes directly to typed dataclass fields. Below is the exact mapping from draw.io source data to the IR fields in `Node` and `Edge` objects.

- **Element identifiers** — The `id` attribute of each `<mxCell>` is mapped to `Node.id` and `Edge.id`.
- **Text labels** — Cell `value` attributes (including HTML) are stored in `Node.label` and `Edge.label` with HTML stripped.
- **Shape types** — The `shape` key extracted from the `style` string becomes `Node.shape`.
- **Parent-child hierarchy** — The `parent` attribute drives `Node.parent` and `Node.children`.
- **Absolute geometry** — `mxGeometry` values (`x`, `y`, `width`, `height`) are resolved into absolute coordinates in `Node.x`, `Node.y`, `Node.w`, and [`Node.h`](https://github.com/cathrynlavery/diagram-design/blob/main/Node.h).
- **Visual styling** — Keys such as `fillColor`, `strokeColor`, `fontColor`, `dashed`, `rounded`, and `container` populate matching `Node` fields.
- **Hyperlinks and tooltips** — The `link` and `tooltip` attributes are preserved in `Node.link` and `Node.attrs`.
- **Edge connectivity** — `source` and `target` attributes map directly to `Edge.source` and `Edge.target`.
- **Edge waypoints** — `<mxPoint>` children inside edge geometry are counted in `Edge.waypoints`.
- **Edge directionality and dash** — `startArrow`, `endArrow`, and `dashed` style keys set `Edge.bidirectional`, `Edge.undirected`, and `Edge.dashed`.
- **Custom attributes** — Any remaining `key=value` pairs in the style string are collected in `Node.attrs`.

### `Node` Dataclass Fields

The `Node` dataclass, defined around lines 91–108 in [`drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/drawio_extract.py), stores geometric, visual, and structural data for every vertex in the diagram.

- **Geometric data**: `x`, `y`, `w`, `h` for absolute position and size.
- **Visual styling**: `fill`, `stroke`, `font_color`, `dashed`, `rounded`, and `container`.
- **Hierarchy**: `parent` reference and `children` list.
- **Connectivity metrics**: `in_degree` and `out_degree`.
- **Extras**: `link` and filtered custom attributes in `attrs`.

### `Edge` Dataclass Fields

The `Edge` dataclass, defined around lines 115–124 in [`drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/drawio_extract.py), stores connectivity and routing data for every connector.

- **Connectivity**: `source` and `target` node identifiers.
- **Labeling**: `label` text.
- **Visual style**: `dashed`, `bidirectional`, `undirected`, and `stroke`.
- **Routing**: Number of intermediate waypoints in `waypoints`.

## Code Examples for Importing from draw.io Files

The following examples demonstrate how to run the importer from the command line and integrate it into Python applications.

### Import a draw.io File from the CLI

```bash

# Produce a Markdown digest (default)

python3 drawio_extract.py examples/example.drawio

# Get the full JSON IR for further processing

python3 drawio_extract.py examples/example.drawio --json > diagram.json

```

### Import from Python and Serialize to JSON

```python
from pathlib import Path
from skills.diagram_design.scripts.drawio_extract import parse_file, to_json

# Load a .drawio (or .png/.svg) file

pages = parse_file(Path("examples/example.drawio"))

# Pick the first page (or use `select_pages` to choose another)

page = pages[0]

# Convert the page to JSON (full IR)

json_payload = to_json(Path("examples/example.drawio"), pages, [page])
print(json_payload)

```

### Inspect Individual Nodes in the IR

```python
node = page.nodes[0]                     # first node on the page

print(f"ID: {node.id}")
print(f"Label: {node.label}")
print(f"Shape: {node.shape}")
print(f"Position: ({node.x}, {node.y}) size ({node.w}×{node.h})")

```

## Key Files Supporting draw.io Import

The draw.io import capability is distributed across three files in the `diagram-design` skill.

- [`skills/diagram-design/scripts/drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/drawio_extract.py) — The full import pipeline including format detection, XML parsing, IR construction, and digest/JSON output.
- [`scripts/verify-drawio-import.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-drawio-import.py) — Integration tests that validate import behavior against known draw.io fixtures.
- [`scripts/test-verify-drawio-import.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/test-verify-drawio-import.py) — Unit tests exercising individual import functions.

## Summary

- The import pipeline in [`drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/drawio_extract.py) is deterministic and never makes design decisions; it only normalizes raw draw.io data into an absolute-position intermediate representation.
- `load_mxfile` handles multiple input formats—raw XML, `.drawio`, PNG, SVG, and compressed base-64—while enforcing size limits.
- Vertices become `Node` objects preserving geometry, style, hierarchy, and links; edges become `Edge` objects preserving connectivity, waypoints, and directionality.
- The final IR can be emitted as a human-readable Markdown digest or a complete JSON payload for downstream analysis by the `diagram-design` skill.

## Frequently Asked Questions

### Does the importer support PNG or SVG files exported from draw.io?

Yes. The `load_mxfile` function in [`drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/drawio_extract.py) detects embedded `mxfile` chunks inside PNG or SVG exports and extracts the compressed XML payload before parsing. This allows diagrams saved as images to be imported with the same fidelity as native `.drawio` files.

### Are absolute or relative coordinates preserved during import?

Absolute coordinates are preserved. During the `parse_page` stage, parent-relative geometries from `mxGeometry` are resolved into absolute positions, so every `Node` stores final `x`, `y`, `w`, and `h` values independent of container nesting.

### What happens to custom style attributes that do not map to standard fields?

Any additional `key=value` pairs in a cell's style string that are not mapped to dedicated dataclass fields are collected into `Node.attrs`. This ensures that custom visual properties or metadata from the original draw.io diagram are retained in the intermediate representation.

### Can I automate batch conversion of multiple draw.io files to JSON?

Yes. Because `parse_file` and `to_json` are pure Python functions exposed by `skills.diagram_design.scripts.drawio_extract`, you can script batch workflows that iterate over directories. Each file can be parsed and serialized to JSON for further downstream processing.