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

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 (lines 1-9 and 55-80), the load_mxfile logic handles .drawio, .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). While users may override the suggestion, the chosen type dictates the layout rules applied downstream. This selection process is documented in 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 (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 (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 (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:

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:

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:

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, .drawio.png, and .drawio.svg files. The load_mxfile logic in 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. 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.

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 →