# Understanding the Draw.io Import Pipeline: From XML Extraction to Semantic Redesign

> Explore the draw.io import pipeline. Learn how files are extracted, layout data is stripped, and content is transformed into a semantic model for rendering.

- Repository: [Cathryn Lavery/diagram-design](https://github.com/cathrynlavery/diagram-design)
- Tags: internals
- Published: 2026-08-15

---

**The draw.io import pipeline extracts files into a normalized intermediate representation, strips all layout-specific data like pixel coordinates and colors, and transforms the content into a semantic model suitable for the diagram-design skill's rendering engine.**

The `cathrynlavery/diagram-design` repository implements a deterministic import pipeline that converts draw.io files into a structured intermediate representation before regenerating them according to the skill's design system. Unlike simple format converters, this pipeline deliberately discards visual styling and positional data to focus on structural semantics. Understanding the draw.io import pipeline helps developers integrate custom diagrams while ensuring consistent output across different source formats.

## How the Draw.io Import Pipeline Works

The import process consists of seven distinct stages that progressively transform raw draw.io sources into a rendered diagram.

### Step 1: Extract the Intermediate Representation (IR)

In [`skills/diagram-design/scripts/drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/drawio_extract.py) (lines 1-9 and 55-80), the `load_mxfile` logic handles `.drawio`, [`.drawio.xml`](https://github.com/cathrynlavery/diagram-design/blob/main/.drawio.xml), `.drawio.png`, and `.drawio.svg` files. The extractor processes raw XML, compressed payloads, PNG-embedded `<mxfile>` chunks, and SVG-embedded content to produce either a compact Markdown digest or a full JSON IR. During this phase, the system normalizes geometry to absolute coordinates, classifies shapes, and builds node and edge objects.

### Step 2: Parse the IR into Pages

The `parse_file()` function selects the appropriate `<mxfile>` or `<diagram>` element, then `parse_page()` (lines 51-70) walks the XML model to create `Node` and `Edge` dataclasses (defined at lines 91-124). This stage resolves absolute geometry through the `resolve` method (lines 50-60) and establishes parent-child relationships within the document hierarchy.

### Step 3: Structural Analysis

The `analyze()` function (lines 80-129) computes structural signals including hub degrees, containers, cycles, shape families, and type candidates. Critically, it identifies **collapsible groups** (containers whose children are all leaves) at lines 34-48, which serve as the first compression targets when the node budget is exceeded.

### Step 4: Choose Diagram Type and Detail

The digest's `type_candidates` field guides the skill to load the appropriate `type-*.md` reference (e.g., [`type-architecture.md`](https://github.com/cathrynlavery/diagram-design/blob/main/type-architecture.md)). While users may override the suggestion, the chosen type dictates the layout rules applied downstream. This selection process is documented in [`import-drawio.md`](https://github.com/cathrynlavery/diagram-design/blob/main/import-drawio.md) (section **Step 3 – Pick the target type**, lines 43-59).

### Step 5: Build the Semantic Model

Using the digest, the skill names the story, applies the desired detail level (pruning according to the collapsible groups identified earlier), selects focal nodes using the `hubs` ranking, rewrites labels for the target audience, and drops unnecessary edges. These transformations are specified in [`import-drawio.md`](https://github.com/cathrynlavery/diagram-design/blob/main/import-drawio.md) (steps 4-5, lines 65-74).

### Step 6: Redraw with Fresh Layout

The rendering engine generates a fresh layout on a 4 px grid, deliberately discarding all source coordinates, color palettes, and shape vocabulary. Shapes map to the skill's visual vocabulary (e.g., cylinders become store boxes, icons map to monochrome glyphs). Connectors are re-routed with orthogonal elbows, and the viewBox is set according to the chosen output size. This step is detailed in [`import-drawio.md`](https://github.com/cathrynlavery/diagram-design/blob/main/import-drawio.md) (section **Step 6 – Redraw**, lines 77-89).

### Step 7: Final Delivery

The final HTML, SVG, or PNG is written after running the taste-gate and output-spec checklist. A fidelity ledger is attached to the response to document any transformations applied. See [`import-drawio.md`](https://github.com/cathrynlavery/diagram-design/blob/main/import-drawio.md) (section **Step 7 – Deliver**, lines 110-115).

## Key Transformations Applied to Draw.io Files

The pipeline applies several deterministic transformations to normalize input:

- **Payload decoding** – The functions `_png_embedded_xml`, `_svg_embedded_xml`, and `_inflate` (around lines 103-106) handle PNG `tEXt/zTXt` chunks, SVG `content` attributes, and base-64 + deflate payloads.
- **XML safety** – The `_reject_unsafe_xml` method (lines 55-60) rejects DTD and ENTITY declarations to prevent injection attacks.
- **Geometry normalisation** – The `resolve` method inside `parse_page` (lines 50-60) converts coordinates to absolute `x` and `y` values after walking the parent chain.
- **Shape classification** – `classify_shape` (lines 60-70) maps raw `shape` strings to canonical names like `rect` or `icon:aws`.
- **Label cleaning** – `clean_label` (lines 4-14) strips HTML tags, unescapes entities, and collapses whitespace.
- **Cycle detection** – `_has_cycle` (lines 38-66) performs depth-first search on the adjacency list to identify cycles.
- **Budget flagging** – The `digest` function (lines 20-22) triggers an "OVER" flag when nodes exceed 9 or edges exceed 12.
- **Collapsible groups** – The `analyze` function (lines 34-48) flags containers whose children are all leaves for potential compression.
- **Connector re-routing** – While way-point counts are retained for diagnostics only, the rendering engine generates new orthogonal routes independently of the original layout.

## Running the Extractor: Practical Examples

You can invoke the pipeline via command line or import the library directly in Python.

Extract the default page to a Markdown digest:

```bash
python3 skills/diagram-design/scripts/drawio_extract.py \
    scripts/fixtures/sample-architecture.drawio \
    --max-rows 30 > /tmp/digest.md

```

Export the full JSON intermediate representation for debugging:

```bash
python3 skills/diagram-design/scripts/drawio_extract.py \
    my-diagram.drawio --json > /tmp/ir.json

```

Use the library programmatically after adding the repository to your `PYTHONPATH`:

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

path = Path("my-diagram.drawio")
pages = parse_file(path)                # → List[Page]

selected = pages[:1]                    # pick first page

print(digest(path, pages, selected, max_rows=20))

```

## Summary

- The draw.io import pipeline in `cathrynlavery/diagram-design` processes files through seven deterministic stages from extraction to delivery.
- **Layout information is intentionally discarded**: pixel positions, colors, and exact shapes are stripped during normalization.
- The pipeline supports multiple input formats including raw XML, PNG with embedded chunks, and SVG with content attributes.
- Structural analysis identifies collapsible groups and hub nodes to manage complexity budgets.
- All coordinates are normalized to absolute values before the final redraw phase applies the skill's visual vocabulary.

## Frequently Asked Questions

### What file formats does the draw.io import pipeline support?

The pipeline supports `.drawio`, [`.drawio.xml`](https://github.com/cathrynlavery/diagram-design/blob/main/.drawio.xml), `.drawio.png`, and `.drawio.svg` files. The `load_mxfile` logic in [`drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/drawio_extract.py) handles raw XML, compressed payloads, PNG-embedded `<mxfile>` chunks extracted via `zTXt` or `tEXt` chunks, and SVG-embedded content attributes.

### Why does the pipeline discard original pixel coordinates and styling?

The pipeline deliberately strips layout-specific information to ensure diagrams conform to the skill's design system. By normalizing geometry and discarding original colors and coordinates, the system can apply consistent visual vocabularies (e.g., mapping cylinders to store boxes) and generate clean orthogonal layouts on a 4 px grid regardless of the source file's complexity or drawing style.

### How does the pipeline handle budget constraints for large diagrams?

When the node count exceeds 9 or the edge count exceeds 12, the `digest` function flags the diagram as "OVER". The system uses **collapsible groups** identified during structural analysis (containers with all leaf children) as the first candidates for compression, allowing the pipeline to reduce detail while preserving architectural intent.

### Where is the shape classification logic implemented?

Shape classification occurs in the `classify_shape` function located at lines 60-70 of [`skills/diagram-design/scripts/drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/drawio_extract.py). This function maps raw `shape` strings from the draw.io XML to canonical names such as `rect`, `icon:aws`, or other simplified identifiers used by the rendering engine.