Using python and networkx, you may create some beautiful graphs and store them as graphml file:
1 2 3 4 5 6 7 8 9 10 |
graph = nx.DiGraph() graph.add_node('Node1') graph.add_node('Node2') graph.add_node('Node3') graph.add_node('Node4') graph.add_edge('Node1', 'Node2') graph.add_edge('Node1', 'Node3') graph.add_edge('Node2', 'Node4') graph.add_edge('Node3', 'Node4') nx.write_graphml(graph, 'dependency.graphml') |
This will give us the following graphml:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?xml version='1.0' encoding='utf-8'?> <graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> <graph edgedefault="directed"> <node id="Node1" /> <node id="Node3" /> <node id="Node2" /> <node id="Node4" /> <edge source="Node1" target="Node3" /> <edge source="Node1" target="Node2" /> <edge source="Node3" target="Node4" /> <edge source="Node2" target="Node4" /> </graph> </graphml> |
Unfortunately, rendering them the standard way by using draw and Graphviz is producing a bitmap file that I do not want to include in my documentation.
For example:
1 2 3 4 |
graph = nx.read_graphml(path) pos = graphviz_layout(graph, prog='dot') nx.draw(graph, pos, with_labels=True) plt.show() |
Will look like:
Instead of a PNG file, I would rather have the graph as mermaid to include it into my markdown based documentation.
A quick conversion may be done in a bash script via:
1 2 3 4 5 6 7 8 9 |
function convert { echo 'graph TD;' xml_grep 'edge' ${1} | grep -P 'edge.*source' | sed -nr 's/.*=\"(.*)\".*\"(.*)\".*/\1-->\2/p' } echo '```mermaid' convert ${1} echo '```' |
The resulting graph and the representation rendered by mermaid will look like:
1 2 3 4 5 6 7 |
```mermaid graph TD; Node1-->Node3 Node1-->Node2 Node3-->Node4 Node2-->Node4 ``` |
To improve the script further, we will now add a view functionality by calling the mermaid-live-editor to present the diagram:
1 2 3 4 5 6 7 |
function view { local DATA DATA=$(echo -n '{"code":"';convert ${1} | sed -z 's/\n/\\n/g;s/\\n$/\n/' ;echo -n '","mermaid":{"theme":"default"}}') DATA=$(echo ${DATA} | base64 | tr '+' '-') xdg-open 'https://mermaidjs.github.io/mermaid-live-editor/#/view/'"${DATA}" } |
This will add the live-editor header and footer and encode it with base64 before calling the web browser. The translate replacing the plus to minus characters is necessary because + has a special meaning within a URL.
The resulting URL will look like:
1 |
https://mermaidjs.github.io/mermaid-live-editor/#/view/eyJjb2RlIjoiZ3JhcGggVEQ7XG5Ob2RlMS0tPk5vZGUzXG5Ob2RlMS0tPk5vZGUyXG5Ob2RlMy0tPk5vZGU0XG5Ob2RlMi0tPk5vZGU0ICIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0In19Cg== |
Which you can try here.
You can find the full example scripts with my GitHub repository.
Limitations:
Graphml usually contains a lot more elements like shapes and labels. This example completely ignores them and uses only the edge information displaying the node-id as the label.
This is fine for a quick result, but usually, the id is not meant to label something, only to identify the node. Most professional graphml tools will likely change your ids at some point within the workflow, so be warned.
Further reading:
Mike Bergmann
Latest posts by Mike Bergmann (see all)
- Rendering networkx graphs or graphml files via Mermaid - November 22, 2019
- Yocto recipe compiling Qt apps with cmake - July 21, 2019
- Check if your crross-compiler GCC toolchain is supporting hard-float - October 25, 2018