# How to Customize the Output Draw.io XML Format in graphviz2drawio

> Customize Drawio XML output in graphviz2drawio by editing MxConst.py for tags, Styles.py for visuals, and MxGraph.py for custom attributes. Learn how to tailor your Graphviz exports.

- Repository: [Harold Martin/graphviz2drawio](https://github.com/hbmartin/graphviz2drawio)
- Tags: how-to-guide
- Published: 2026-03-03

---

**You can customize the output Draw.io XML format in graphviz2drawio by modifying constants in [`MxConst.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/MxConst.py) for tag names, extending [`Styles.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/Styles.py) for visual styling, and subclassing [`MxGraph.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/MxConst.py)** – Defines XML tag names and default attributes (such as `ROOT`, `CELL`, `GEO`, `GRAPH`)
- **[`Styles.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/Styles.py)** – Manages visual styling enums and shape-to-style mappings for nodes and edges
- **[`MxGraph.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/MxGraph.py)** – Assembles the XML tree using `add_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`](https://github.com/hbmartin/graphviz2drawio/blob/main/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:

```python

# 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:

```xml
<mxGraphModel grid="0">
  <myRoot>
    ...
  </myRoot>
</mxGraphModel>

```

## Customizing Visual Styles

### Defining Custom Styles in Styles.py

The [`graphviz2drawio/mx/Styles.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/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:

```python

# 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`](https://github.com/hbmartin/graphviz2drawio/blob/main/Styles.py). The `_shape_to_style` dictionary controls which style applies to which shape:

```python

# 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:

```xml
<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`](https://github.com/hbmartin/graphviz2drawio/blob/main/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:

```python
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`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/graphviz2drawio.py) to instantiate `MyMxGraph` instead of the base class:

```python

# 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:

```python
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.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/MxConst.py)** to change XML tag names (such as `ROOT`, `CELL`, or `GRAPH`) and alter the basic structure of the generated document.
- **Extend [`graphviz2drawio/mx/Styles.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/Styles.py)** to define custom visual styles for nodes and edges, and map specific Graphviz shapes to these styles using the `_shape_to_style` dictionary.
- **Subclass [`graphviz2drawio/mx/MxGraph.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/MxGraph.py)** to override `add_node`, `add_edge`, or geometry methods, enabling injection of custom attributes, metadata cells, or structural modifications into the XML tree.
- **Use the `convert` function** in [`graphviz2drawio/graphviz2drawio.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/graphviz2drawio.py) as 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`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/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`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/graphviz2drawio.py) instead of the base `MxGraph` class to apply your changes.