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

Use the 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 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:

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

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

The extractor lives at skills/diagram-design/scripts/drawio_extract.py relative to the repository root.

Step 2: Extract to JSON

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

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

./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


# From repository root

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

Processing IR Programmatically

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


# 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 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 Core extractor with load_mxfile, parse_page, and classify_shape
commands/import-drawio.md User-facing command interface and orchestration
scripts/verify-drawio-import.py Test harness for validation against fixtures
skills/diagram-design/SKILL.md Visual diagram type definitions
skills/diagram-design/references/output-spec.md Size presets and format specifications

Summary

  • Primary tool: 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 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →