How to Customize the Output Draw.io XML Format in graphviz2drawio
You can customize the output Draw.io XML format in graphviz2drawio by modifying constants in MxConst.py for tag names, extending Styles.py for visual styling, and subclassing MxGraph.py to inject custom attributes or metadata into the generated <mxGraphModel> structure.
The graphviz2drawio library converts Graphviz DOT files into Draw.io-compatible XML by parsing an intermediate SVG representation and constructing an <mxGraphModel> document. If you need to customize the output Draw.io XML format—whether to rename XML tags, apply custom visual styles, or inject metadata—you must modify the library's three-layer architecture spanning constants, styles, and graph assembly logic.
Understanding the XML Generation Architecture
graphviz2drawio builds the Draw.io (mxGraph) XML by converting a Graphviz DOT description into an intermediate SVG, extracting nodes and edges, and then writing an <mxGraphModel> document with the help of the mx package located in graphviz2drawio/mx/. The XML generation is centralized across three primary layers:
MxConst.py– Defines XML tag names and default attributes (such asROOT,CELL,GEO,GRAPH)Styles.py– Manages visual styling enums and shape-to-style mappings for nodes and edgesMxGraph.py– Assembles the XML tree usingadd_node,add_edge, and geometry methods
Customizing XML Tags and Structure
Modifying Constants in MxConst.py
To rename tags or alter default attributes, edit the constants in graphviz2drawio/mx/MxConst.py. This file defines ROOT, CELL, GEO, POINT, and GRAPH, which determine the element names used throughout the generated XML.
For example, to change the root element from the default "root" to a custom tag:
# In graphviz2drawio/mx/MxConst.py
ROOT = "myRoot" # Changed from default "root"
Since all MxGraph methods reference MxConst.ROOT, this change propagates throughout the generated XML, resulting in output like:
<mxGraphModel grid="0">
<myRoot>
...
</myRoot>
</mxGraphModel>
Customizing Visual Styles
Defining Custom Styles in Styles.py
The graphviz2drawio/mx/Styles.py file contains the Styles enum that defines visual styling for nodes, edges, and labels. To add custom visual styles, extend this enum with new entries that specify mxGraph style strings using the format method.
For example, to create a branded node style with specific colors and borders:
# In graphviz2drawio/mx/Styles.py
from graphviz2drawio.mx.Shape import Shape
# Add new style to the enum
Styles.MY_BRAND = Styles.NODE.format(
vertical_align="middle",
stroke="#003366",
fill="#cce5ff",
stroke_width="2",
dashed="0",
)
Mapping Shapes to Custom Styles
To apply your custom style to specific Graphviz shapes, update the shape-to-style mapping in Styles.py. The _shape_to_style dictionary controls which style applies to which shape:
# In graphviz2drawio/mx/Styles.py
# Extend the shape-to-style map
_shape_to_style[Shape.CUSTOM] = Styles.MY_BRAND
When processing a DOT file with your custom shape, the generated XML will include the style string in the style attribute of the <mxCell> element:
<mxCell id="node1" value="Node A" style="verticalAlign=middle;strokeColor=#003366;fillColor=#cce5ff;strokeWidth=2;dashed=0;..." />
Injecting Custom Attributes and Metadata
Subclassing MxGraph for Custom Attributes
The graphviz2drawio/mx/MxGraph.py file handles the assembly of the XML tree through methods like add_node, add_edge, add_mx_geo, and add_mx_geo_with_points. To inject custom attributes into nodes or edges, subclass MxGraph and override these methods.
For example, to add a custom flag attribute to every edge:
from graphviz2drawio.mx.MxGraph import MxGraph
from graphviz2drawio.mx import MxConst
from xml.etree.ElementTree import SubElement
class MyMxGraph(MxGraph):
def add_edge(self, edge):
super().add_edge(edge) # Keep existing behavior
# Locate the created edge cell by its ID (edge.sid)
edge_cell = self.root.find(f".//mxCell[@id='{edge.sid}']")
if edge_cell is not None:
edge_cell.set("myCustomFlag", "true")
To use your subclass, modify the convert function in graphviz2drawio/graphviz2drawio.py to instantiate MyMxGraph instead of the base class:
# In graphviz2drawio/graphviz2drawio.py
# Replace: mx_graph = MxGraph(clusters, nodes, edges)
mx_graph = MyMxGraph(clusters, nodes, edges)
Adding Supplementary Metadata Cells
To insert additional <mxCell> elements for metadata purposes—such as tracking generation timestamps or source information—create helper functions that use SubElement after the graph construction:
from xml.etree.ElementTree import SubElement
def add_metadata(mx_graph):
meta = SubElement(
mx_graph.root,
MxConst.CELL,
attrib={
"id": "meta_1",
"value": "generated_by=graphviz2drawio",
"parent": "1"
},
)
mx_graph.add_mx_geo(meta) # Add simple geometry so Draw.io accepts the cell
# Usage after MxGraph construction
mx_graph = MxGraph(clusters, nodes, edges)
add_metadata(mx_graph)
This approach inserts a non-visual cell containing custom data that persists within the Draw.io file without affecting the diagram layout.
Summary
- Modify
graphviz2drawio/mx/MxConst.pyto change XML tag names (such asROOT,CELL, orGRAPH) and alter the basic structure of the generated document. - Extend
graphviz2drawio/mx/Styles.pyto define custom visual styles for nodes and edges, and map specific Graphviz shapes to these styles using the_shape_to_styledictionary. - Subclass
graphviz2drawio/mx/MxGraph.pyto overrideadd_node,add_edge, or geometry methods, enabling injection of custom attributes, metadata cells, or structural modifications into the XML tree. - Use the
convertfunction ingraphviz2drawio/graphviz2drawio.pyas the entry point to instantiate custom subclasses and retrieve the final XML string with your modifications applied.
Frequently Asked Questions
Can I change the root element tag name in the generated XML?
Yes, you can change the root element tag by modifying the ROOT constant in graphviz2drawio/mx/MxConst.py. Change ROOT = "root" to your desired tag name (such as myRoot), and the MxGraph class will use this constant when constructing the XML tree, resulting in <myRoot> instead of <root> in the output.
How do I add a custom style for specific node shapes?
To add a custom style, define a new entry in the Styles enum in graphviz2drawio/mx/Styles.py using the format method (for example, Styles.MY_STYLE = Styles.NODE.format(...)). Then map your Graphviz shape to this style in the _shape_to_style dictionary by adding an entry like _shape_to_style[Shape.CUSTOM] = Styles.MY_STYLE in the same file.
Is it possible to inject metadata into the generated XML?
Yes, you can inject metadata by subclassing MxGraph in graphviz2drawio/mx/MxGraph.py and overriding methods like add_node or add_edge to insert custom attributes into the attrib dictionary before creating SubElement instances. Alternatively, create a helper function that uses SubElement to append additional <mxCell> elements with metadata values after the graph construction is complete.
Can I subclass MxGraph to modify edge behavior?
Yes, subclassing MxGraph is the recommended approach for advanced customizations. Create a subclass that overrides add_edge(self, edge), call super().add_edge(edge) to preserve default behavior, then locate the created edge cell using self.root.find(f".//mxCell[@id='{edge.sid}']") to modify attributes or geometry. Instantiate your subclass in graphviz2drawio/graphviz2drawio.py instead of the base MxGraph class to apply your changes.
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 →