# How to Convert .drawio Files to Diagram-Design Structured IR: A Complete Guide

> Convert drawio files to diagram-design structured IR using the drawio_extract.py script. Easily parse XML, PNG, or SVG files into JSON or Markdown.

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

---

**Use the [`drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/drawio_extract.py) script to parse any `.drawio` file—XML, PNG, or SVG—and emit a normalized intermediate representation (IR) as JSON or Markdown.**

The diagram-design repository provides a dedicated extraction pipeline that transforms draw.io diagrams into a structured, portable format. Whether your source is raw XML, a PNG with embedded diagram data, or an SVG export, the [`drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/drawio_extract.py) script handles format detection, safe parsing, and canonical shape classification automatically.

## Understanding the Conversion Pipeline

The extraction process follows four distinct phases, each implemented in [`skills/diagram-design/scripts/drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/drawio_extract.py):

### 1. Format Detection and Loading

The `load_mxfile` function inspects incoming bytes to determine the source type:

- **Raw XML** – direct `<mxGraphModel>` or `<mxfile>` content
- **PNG with embedded XML** – scans for `zTXt` chunks via `_png_embedded_xml`
- **SVG with embedded XML** – extracts from XML comments via `_svg_embedded_xml`
- **Base64 + deflate payload** – decompresses via `_inflate` with zip-bomb protection

The implementation guards against oversized payloads by raising `PayloadTooLarge` when decompression exceeds safety limits.

### 2. XML Parsing and Object Construction

The `parse_page` function walks the `<mxGraphModel>` tree and constructs three core dataclasses:

- **`Node`** – represents shapes with resolved absolute geometry, parent-child depth, and classified shape type
- **`Edge`** – represents connectors with source/target references and waypoint data
- **`Page`** – container for nodes and edges with diagram metadata

Shape classification happens via `classify_shape`, which normalizes draw.io styles to a closed vocabulary including `rect`, `ellipse`, `icon:aws`, and other canonical types.

### 3. Optional Structural Analysis

The `analyze` function performs supplementary computations—cycle detection, hub node identification, shape distribution counts—without modifying the core IR structure.

### 4. Output Generation

Two output formats are available:

- **Markdown digest** (default) – human-readable summary for quick inspection
- **Full JSON** (`--json` flag) – complete machine-readable IR for downstream processing

## Running the Extractor: Step-by-Step

### Step 1: Locate the Script

```bash
cd $(git rev-parse --show-toplevel)/skills/diagram-design/scripts

```

The extractor lives at [`skills/diagram-design/scripts/drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/drawio_extract.py) relative to the repository root.

### Step 2: Extract to JSON

```bash
python3 drawio_extract.py path/to/diagram.drawio --json > diagram.ir.json

```

Omit `--json` to receive the Markdown digest instead.

### Step 3: Inspect the Generated IR

```python
import json

with open('diagram.ir.json', encoding='utf-8') as f:
    ir = json.load(f)

# Navigate the structure

first_page = ir['pages'][0]
nodes = first_page['nodes']
edges = first_page['edges']

print(f"Page '{first_page['name']}': {len(nodes)} nodes, {len(edges)} edges")

```

### Step 4: Use with the `import-drawio` Command

```bash
./commands/import-drawio.md path/to/diagram.drawio \
    --detail=balanced \
    --size=doc-inline \
    --format=html \
    --output=out/diagram

```

This command orchestrates the full pipeline: extraction, layout, styling, and final rendering.

## Complete Code Examples

### Extracting Architecture Diagrams

```bash

# From repository root

python3 ./skills/diagram-design/scripts/drawio_extract.py \
    ./scripts/fixtures/sample-architecture.drawio \
    --json > architecture.ir.json

```

### Processing IR Programmatically

```python
import json
from pathlib import Path

ir_path = Path("architecture.ir.json")
data = json.loads(ir_path.read_text(encoding="utf-8"))

# Access page metadata and entities

for page in data["pages"]:
    print(f"\nPage: {page['name']}")
    print(f"  Bounds: {page.get('width')} x {page.get('height')}")
    print(f"  Nodes: {[n['shape'] for n in page['nodes'][:5]]}...")
    print(f"  Edges: {len(page['edges'])} connections")

```

### Integrating with Rendering Pipeline

```bash

# Full workflow: extract, transform, render

./commands/import-drawio.md ./my-system.drawio \
    --detail=minimal \
    --size=presentation \
    --format=svg \
    --output=./exports/system-diagram

```

## Safety and Normalization Features

The [`drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/drawio_extract.py) implementation includes several protective measures:

- **XML security** – rejects `<!DOCTYPE>` and `<!ENTITY>` declarations before parsing to prevent XXE attacks
- **Decompression limits** – caps inflate operations to prevent zip-bomb resource exhaustion
- **Canonical shapes** – all draw.io styles map to normalized types, ensuring consistent downstream rendering

These safeguards operate automatically without user configuration.

## Key Files and References

| File | Purpose |
|------|---------|
| [`skills/diagram-design/scripts/drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/drawio_extract.py) | Core extractor with `load_mxfile`, `parse_page`, and `classify_shape` |
| [`commands/import-drawio.md`](https://github.com/cathrynlavery/diagram-design/blob/main/commands/import-drawio.md) | User-facing command interface and orchestration |
| [`scripts/verify-drawio-import.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-drawio-import.py) | Test harness for validation against fixtures |
| [`skills/diagram-design/SKILL.md`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/SKILL.md) | Visual diagram type definitions |
| [`skills/diagram-design/references/output-spec.md`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/references/output-spec.md) | Size presets and format specifications |

## Summary

- **Primary tool**: [`drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/drawio_extract.py) in `skills/diagram-design/scripts/`
- **Input formats**: raw XML, PNG with embedded data, SVG with embedded data, base64+deflate payloads
- **Core dataclasses**: `Node`, `Edge`, `Page` with resolved geometry and canonical shapes
- **Output options**: Markdown digest (default) or full JSON (`--json`)
- **Safety features**: XXE prevention, zip-bomb protection, shape normalization
- **Integration path**: use directly for IR extraction, or via `import-drawio` command for full rendering

## Frequently Asked Questions

### What input formats does the extractor support?

The `load_mxfile` function accepts raw `.drawio` XML files, PNG images with embedded `mxfile` data, SVG exports with diagram comments, and base64-encoded deflate-compressed payloads. The script auto-detects the format by inspecting magic bytes and structure.

### How do I prevent extraction from hanging on corrupted files?

The extractor implements explicit safeguards: XML entities and DOCTYPE declarations are rejected before parsing, and decompression operations enforce size limits via `PayloadTooLarge` exceptions. These protections trigger automatically without configuration.

### Can I use the IR without the `import-drawio` command?

Yes. The JSON output from [`drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/drawio_extract.py) is a self-contained intermediate representation. Parse it with standard JSON libraries and feed `pages`, `nodes`, and `edges` into custom tooling, visualization libraries, or documentation generators.

### Where are the shape classification rules defined?

The `classify_shape` function in [`drawio_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/drawio_extract.py) maps draw.io style strings to canonical types. The closed vocabulary includes geometric primitives (`rect`, `ellipse`), cloud service icons (`icon:aws`, `icon:gcp`), and connector styles, ensuring downstream renderers receive consistent identifiers.