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
idattribute of each<mxCell>is mapped toNode.idandEdge.id. - Text labels — Cell
valueattributes (including HTML) are stored inNode.labelandEdge.labelwith HTML stripped. - Shape types — The
shapekey extracted from thestylestring becomesNode.shape. - Parent-child hierarchy — The
parentattribute drivesNode.parentandNode.children. - Absolute geometry —
mxGeometryvalues (x,y,width,height) are resolved into absolute coordinates inNode.x,Node.y,Node.w, andNode.h. - Visual styling — Keys such as
fillColor,strokeColor,fontColor,dashed,rounded, andcontainerpopulate matchingNodefields. - Hyperlinks and tooltips — The
linkandtooltipattributes are preserved inNode.linkandNode.attrs. - Edge connectivity —
sourceandtargetattributes map directly toEdge.sourceandEdge.target. - Edge waypoints —
<mxPoint>children inside edge geometry are counted inEdge.waypoints. - Edge directionality and dash —
startArrow,endArrow, anddashedstyle keys setEdge.bidirectional,Edge.undirected, andEdge.dashed. - Custom attributes — Any remaining
key=valuepairs in the style string are collected inNode.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,hfor absolute position and size. - Visual styling:
fill,stroke,font_color,dashed,rounded, andcontainer. - Hierarchy:
parentreference andchildrenlist. - Connectivity metrics:
in_degreeandout_degree. - Extras:
linkand filtered custom attributes inattrs.
Edge Dataclass Fields
The Edge dataclass, defined around lines 115–124 in drawio_extract.py, stores connectivity and routing data for every connector.
- Connectivity:
sourceandtargetnode identifiers. - Labeling:
labeltext. - Visual style:
dashed,bidirectional,undirected, andstroke. - 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.
skills/diagram-design/scripts/drawio_extract.py— The full import pipeline including format detection, XML parsing, IR construction, and digest/JSON output.scripts/verify-drawio-import.py— Integration tests that validate import behavior against known draw.io fixtures.scripts/test-verify-drawio-import.py— Unit tests exercising individual import functions.
Summary
- The import pipeline in
drawio_extract.pyis deterministic and never makes design decisions; it only normalizes raw draw.io data into an absolute-position intermediate representation. load_mxfilehandles multiple input formats—raw XML,.drawio, PNG, SVG, and compressed base-64—while enforcing size limits.- Vertices become
Nodeobjects preserving geometry, style, hierarchy, and links; edges becomeEdgeobjects 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-designskill.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →