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

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, 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 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.
  • 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, 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, 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


# 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

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

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.

Summary

  • The import pipeline in 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 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.

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 →