Dot language

Command to generate image with dot

dot -Tpng -o Output.png Input.dot

Frequently used attributes

digraph G {
  graph [
    label="Show general attributes\n that can be used",
    labelloc=t,    //t=top, b=bottom
    labeljust=r,   //r=right justified, l=left justified
    overlap=false, 
    center=true, 
    bgcolor=green, 
    fontcolor=red, 
    fontsize=24, 
    rankdir=TB,   // Orientation: TB=Top to Bottom, LR=Left to right
    URL="G.html",  // Need to generate as ismap to be clickable
    nodesep=3.0  // increases the separation between nodes
        ];
  node    [shape=circle, style=filled, fontname="Courier"];
  edge    [color=blue]; // dir="none"
 
  a [label="Node A", width=1.25, fillcolor=white, color=black, URL="A.html"];
 
  {rank=same; "b"; "c";}
 
  a -> b [ taillabel="Tail Label", labelangle=45, labeldistance=5, color=red, fontcolor=blue];
 
  b -> c [ headlabel="Head Label", 
    labeldistance=2, 
    color=transparent, 
    dir=back     // back=Revert arrow direction, both=arrow on both ends
    URL="b.html"       // Need to generate as ismap to be clickable
     ];
 
  external_image [label="", shape=box, style=invis, shapefile="image.png"];
}

References

Node, Edge and Graph Attributes http://www.graphviz.org/doc/info/attrs.html#k:arrowType http://www.graphviz.org/doc/info/arrows.html

Graphviz binaries depend on a few Visual Studio DLLs.

Need to install Microsoft Visual C++ 2005 Redistributable Package. Otherwise, Graphviz applications will not run. For example, if you are trying to run dot.exe in the Command Prompt, it will display the following message: "The system cannot execute the specified program."

Add spacer

digraph G
{
  // Add space using width and height attributes.
  //  Recognized units are in, px, pc, pt, cm and mm 
  //  for inches, pixels, picas, points, centimeters and millimeters, respectively. 
  //  The default unit is points.
  c[label="Empty spacer" shape="none", width="3px" height="6px"];
  d[label="Unhidden Empty spacer" shape="box", width="3px" height="6px"];
  a->b;
  b->c;
  b->d;
}

Debian Dependencies Graph

Command executed to generate debian application dependency graph using dot languge:

#!/bin/bash
xsltproc System.xsl System.xml > System.dot
dot -Tpng -o System.png System.dot

System.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--System.xml
Exception: Node can't contain &.
-->
<System xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="C:\Xuan_Temp\del\System.xsd">
    <Distribution Version="4.0r1" Name="Debian Etch">
        <Application Id="Debian" Version="??" Name="Debian Etch" PackageName="Debian">
            <Description>GNU/Linux OS</Description>
        </Application>
 
        <Application Id="x-window-system" Version="??" Name="x-window-system" PackageName="x-window-system">
            <Description>x-window-system</Description>
        </Application>
 
        <Application Id="wmaker" Version="0.90" Name="Windowmaker" PackageName="wmaker">
            <Description>A window manager</Description>
        </Application>
 
        <Application Id="leafpad" Version="??" Name="leafpad" PackageName="leafpad">
            <Description>A simple graphic text editor</Description>
        </Application>
 
        <Application Id="iceweasel" Version="??" Name="Firefox" PackageName="iceweasel">
            <Description>An internet browser</Description>
        </Application>
 
        <Application Id="xtightvncviewer" Version="??" Name="xtightvncviewer" PackageName="xtightvncviewer">
            <Description>Remote control viewer</Description>
        </Application>
 
        <Application Id="k3b" Version="??" Name="k3b" PackageName="k3b">
            <Description>Burning CD/DVD</Description>
        </Application>
 
        <Application Id="dia" Version="??" Name="dia" PackageName="dia">
            <Description>AVisio like application</Description>
        </Application>
 
        <Application Id="mplayer" Version="??" Name="mplayer" PackageName="mplayer">
            <Description>Media player</Description>
            <!--
            head -n22 /usr/share/mplayer/scripts/binary_codecs.sh
            mkdir /usr/lib/codecs
            cp *codecs /usr/lib/codecs
            -->     
        </Application>
 
        <Application Id="gkrellm" Version="??" Name="gkrellm" PackageName="gkrellm">
            <Description>A single process stack of system monitors</Description>
        </Application>
 
        <Application Id="gqivew" Version="??" Name="gqivew" PackageName="gqivew">
            <Description>Picture viewer</Description>
        </Application>
 
        <Application Id="alsa" Version="??" Name="alsa" PackageName="alsa">
            <Description>Sound driver configurator</Description>
        </Application>
 
        <Application Id="hwinfo" Version="??" Name="hwinfo" PackageName="hwinfo">
            <Description>Hardware Info</Description>
        </Application>
 
        <Application Id="graphviz" Version="??" Name="graphviz" PackageName="graphviz">
            <Description>??</Description>
        </Application>
 
        <Application Id="gawk" Version="??" Name="gawk" PackageName="gawk">
            <Description>??</Description>
        </Application>
 
        <Application Id="sed" Version="??" Name="sed" PackageName="sed">
            <Description>??</Description>
        </Application>
 
        <Application Id="ntfs-3g" Version="??" Name="ntfs-3g" PackageName="ntfs-3g">
            <Description>??</Description>
        </Application>
 
        <Application Id="xsltproc" Version="??" Name="xsltproc" PackageName="xsltproc">
            <Description>??</Description>
        </Application>
 
        <Application Id="docbook" Version="??" Name="docbook" PackageName="docbook">
            <Description>??</Description>
        </Application>
 
        <Application Id="rar" Version="??" Name="rar" PackageName="rar">
            <Description>??</Description>
        </Application>
 
        <Application Id="unzip" Version="??" Name="unzip" PackageName="unzip">
            <Description>??</Description>
        </Application>
 
        <Application Id="lxsplit" Version="??" Name="lxsplit" PackageName="lxsplit">
            <Description>??</Description>
        </Application>
 
        <Application Id="acroread" Version="??" Name="Adobe Acrobat Reader" PackageName="acroread">
            <Description>PDF file viewer</Description>
        </Application>
 
        <Dependency>
            <Package Id="Debian">
                <Package Id="x-window-system">
                    <Package Id="wmaker">
                        <Package Id="leafpad"/>
                        <Package Id="iceweasel"/>
                        <Package Id="xtightvncviewer"/>
                        <Package Id="k3b"/>
                        <Package Id="dia"/>
                        <Package Id="mplayer"/>
                        <Package Id="gkrellm"/>
                        <Package Id="gqivew"/>
                        <Package Id="acroread"/>
                    </Package>
                </Package>
 
                <Package Id="alsa"/>
                <Package Id="hwinfo"/>
                <Package Id="graphviz"/>
                <Package Id="gawk"/>
                <Package Id="sed"/>
                <Package Id="ntfs-3g"/>
                <Package Id="xsltproc">
                    <Package Id="docbook">
                    </Package>
                </Package>
                <Package Id="rar"/>
                <Package Id="unzip"/>
                <Package Id="lxsplit"/>
 
            </Package>
        </Dependency>
 
    </Distribution>
</System>

System.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output encoding="UTF-8" method="text"/>
 
    <xsl:template match="/">
        <xsl:text>digraph System {&#xa;&#xa;</xsl:text>
 
        <xsl:for-each select="System/Distribution">
 
            <!-- Subgraph name -->
            <xsl:variable name="vSubgraphName">
                <xsl:call-template name="ReplaceCharsInString">
                    <xsl:with-param name="stringIn" select="@Name"/>
                    <xsl:with-param name="charsIn" select="'&amp;'"/>
                    <xsl:with-param name="charsOut" select="''"/>
                </xsl:call-template>                     
            </xsl:variable>                 
            <xsl:text>subgraph "cluster</xsl:text>
            <xsl:value-of select="$vSubgraphName"/><xsl:text>" {&#xa;</xsl:text>
            <xsl:text>node [style=filled];&#xa;</xsl:text>
 
            <!-- Subgraph info -->
            <xsl:text>label = "Dependency graph of </xsl:text>
            <xsl:value-of select="@Name"/><xsl:text> [</xsl:text>
            <xsl:value-of select="@Version"/><xsl:text>]";&#xa;</xsl:text>
            <!-- <xsl:value-of select="Description"/><xsl:text>&#xa;</xsl:text><xsl:text>&#xa;</xsl:text> -->
            <xsl:text>color=blue;&#xa;&#xa;</xsl:text>
 
            <!-- Application info -->            
            <xsl:for-each select="Application">
 
                <!-- Escape spaces in label-->
                <xsl:variable name="vName">
                    <xsl:call-template name="ReplaceCharsInString">
                        <xsl:with-param name="stringIn" select="@Name"/>
                        <xsl:with-param name="charsIn" select="' '"/>
                        <xsl:with-param name="charsOut" select="'\ '"/>
                    </xsl:call-template>                     
                </xsl:variable>                  
                <xsl:variable name="vVersion">
                    <xsl:call-template name="ReplaceCharsInString">
                        <xsl:with-param name="stringIn" select="@Version"/>
                        <xsl:with-param name="charsIn" select="' '"/>
                        <xsl:with-param name="charsOut" select="'\ '"/>
                    </xsl:call-template>                     
                </xsl:variable>
                <xsl:variable name="vPackageName">
                    <xsl:call-template name="ReplaceCharsInString">
                        <xsl:with-param name="stringIn" select="@PackageName"/>
                        <xsl:with-param name="charsIn" select="' '"/>
                        <xsl:with-param name="charsOut" select="'\ '"/>
                    </xsl:call-template>                     
                </xsl:variable>
                <xsl:variable name="vDescription">
                    <xsl:call-template name="ReplaceCharsInString">
                        <xsl:with-param name="stringIn" select="Description"/>
                        <xsl:with-param name="charsIn" select="' '"/>
                        <xsl:with-param name="charsOut" select="'\ '"/>
                    </xsl:call-template>                     
                </xsl:variable>
 
                <!-- Escape & in node name-->
                <xsl:variable name="vId">
                    <xsl:call-template name="ReplaceCharsInString">
                        <xsl:with-param name="stringIn" select="@Id"/>
                        <xsl:with-param name="charsIn" select="'&amp;'"/>
                        <xsl:with-param name="charsOut" select="''"/>
                    </xsl:call-template>                     
                </xsl:variable>
 
                <!-- Write application info -->
                <xsl:text>"</xsl:text>
                <xsl:value-of select="$vId"/><xsl:text>" [shape=Mrecord, style=filled, color=green, label = "{</xsl:text>
                <xsl:value-of select="$vName"/><xsl:text> [</xsl:text>
                <xsl:value-of select="$vVersion"/><xsl:text>] | </xsl:text>
                <xsl:value-of select="$vPackageName"/><xsl:text> | </xsl:text>
                <xsl:value-of select="$vDescription"/><xsl:text>}"];&#xa;</xsl:text>
            </xsl:for-each>
 
            <xsl:text>&#xa;</xsl:text>
 
            <!-- Dependency -->            
            <xsl:for-each select="Dependency">
                <xsl:for-each select="Package"><!-- Skip the first node -->
                    <xsl:for-each select="descendant::*">
                            <!-- Escape & in node name-->
                            <xsl:variable name="vPrevId">
                                <xsl:call-template name="ReplaceCharsInString">
                                    <xsl:with-param name="stringIn" select="../@Id"/>
                                    <xsl:with-param name="charsIn" select="'&amp;'"/>
                                    <xsl:with-param name="charsOut" select="''"/>
                                </xsl:call-template>                     
                            </xsl:variable>
                            <xsl:variable name="vCurrId">
                                <xsl:call-template name="ReplaceCharsInString">
                                    <xsl:with-param name="stringIn" select="@Id"/>
                                    <xsl:with-param name="charsIn" select="'&amp;'"/>
                                    <xsl:with-param name="charsOut" select="''"/>
                                </xsl:call-template>                     
                            </xsl:variable>
 
                            <xsl:text>"</xsl:text><xsl:value-of select="$vPrevId"/><xsl:text>" -&gt; "</xsl:text><xsl:value-of select="$vCurrId"/><xsl:text>";&#xa;</xsl:text>
                    </xsl:for-each>
                </xsl:for-each>
            </xsl:for-each>
 
            <xsl:text>}&#xa;</xsl:text>
        </xsl:for-each>
 
        <xsl:text>}</xsl:text>
    </xsl:template>
 
 
 
    <!-- Template to Replace char in String -->
    <xsl:template name="ReplaceCharsInString">
        <xsl:param name="stringIn"/>
        <xsl:param name="charsIn"/>
        <xsl:param name="charsOut"/>
        <xsl:choose>
            <xsl:when test="contains($stringIn,$charsIn)">
                <xsl:value-of select="concat(substring-before($stringIn,$charsIn),$charsOut)"/>
                <xsl:call-template name="ReplaceCharsInString">
                    <xsl:with-param name="stringIn" select="substring-after($stringIn,$charsIn)"/>
                    <xsl:with-param name="charsIn" select="$charsIn"/>
                    <xsl:with-param name="charsOut" select="$charsOut"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$stringIn"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

Dot Output

digraph System {
 
    subgraph "clusterDebian Etch" {
        node [style=filled];
        label = "Dependency graph of Debian Etch [4.0r1]";
        color=blue;
 
        "Debian" [shape=Mrecord, style=filled, color=green, label = "{Debian\ Etch [??] | Debian | GNU/Linux\ OS}"];
        "x-window-system" [shape=Mrecord, style=filled, color=green, label = "{x-window-system [??] | x-window-system | x-window-system}"];
        "wmaker" [shape=Mrecord, style=filled, color=green, label = "{Windowmaker [0.90] | wmaker | A\ window\ manager}"];
        "leafpad" [shape=Mrecord, style=filled, color=green, label = "{leafpad [??] | leafpad | A\ simple\ graphic\ text\ editor}"];
        "iceweasel" [shape=Mrecord, style=filled, color=green, label = "{Firefox [??] | iceweasel | An\ internet\ browser}"];
        "xtightvncviewer" [shape=Mrecord, style=filled, color=green, label = "{xtightvncviewer [??] | xtightvncviewer | Remote\ control\ viewer}"];
        "k3b" [shape=Mrecord, style=filled, color=green, label = "{k3b [??] | k3b | Burning\ CD/DVD}"];
        "dia" [shape=Mrecord, style=filled, color=green, label = "{dia [??] | dia | AVisio\ like\ application}"];
        "mplayer" [shape=Mrecord, style=filled, color=green, label = "{mplayer [??] | mplayer | Media\ player}"];
        "gkrellm" [shape=Mrecord, style=filled, color=green, label = "{gkrellm [??] | gkrellm | A\ single\ process\ stack\ of\ system\ monitors}"];
        "gqivew" [shape=Mrecord, style=filled, color=green, label = "{gqivew [??] | gqivew | Picture\ viewer}"];
        "alsa" [shape=Mrecord, style=filled, color=green, label = "{alsa [??] | alsa | Sound\ driver\ configurator}"];
        "hwinfo" [shape=Mrecord, style=filled, color=green, label = "{hwinfo [??] | hwinfo | Hardware\ Info}"];
        "graphviz" [shape=Mrecord, style=filled, color=green, label = "{graphviz [??] | graphviz | ??}"];
        "gawk" [shape=Mrecord, style=filled, color=green, label = "{gawk [??] | gawk | ??}"];
        "sed" [shape=Mrecord, style=filled, color=green, label = "{sed [??] | sed | ??}"];
        "ntfs-3g" [shape=Mrecord, style=filled, color=green, label = "{ntfs-3g [??] | ntfs-3g | ??}"];
        "xsltproc" [shape=Mrecord, style=filled, color=green, label = "{xsltproc [??] | xsltproc | ??}"];
        "docbook" [shape=Mrecord, style=filled, color=green, label = "{docbook [??] | docbook | ??}"];
        "rar" [shape=Mrecord, style=filled, color=green, label = "{rar [??] | rar | ??}"];
        "unzip" [shape=Mrecord, style=filled, color=green, label = "{unzip [??] | unzip | ??}"];
        "lxsplit" [shape=Mrecord, style=filled, color=green, label = "{lxsplit [??] | lxsplit | ??}"];
        "acroread" [shape=Mrecord, style=filled, color=green, label = "{Adobe\ Acrobat\ Reader [??] | acroread | PDF\ file\ viewer}"];
 
        "Debian" -> "x-window-system";
        "x-window-system" -> "wmaker";
        "wmaker" -> "leafpad";
        "wmaker" -> "iceweasel";
        "wmaker" -> "xtightvncviewer";
        "wmaker" -> "k3b";
        "wmaker" -> "dia";
        "wmaker" -> "mplayer";
        "wmaker" -> "gkrellm";
        "wmaker" -> "gqivew";
        "wmaker" -> "acroread";
        "Debian" -> "alsa";
        "Debian" -> "hwinfo";
        "Debian" -> "graphviz";
        "Debian" -> "gawk";
        "Debian" -> "sed";
        "Debian" -> "ntfs-3g";
        "Debian" -> "xsltproc";
        "xsltproc" -> "docbook";
        "Debian" -> "rar";
        "Debian" -> "unzip";
        "Debian" -> "lxsplit";
        }
}

Diagram perserved while adding annotations

digraph simple_hierarchy {
    a->b->c;
    b->d;
    a->e->f;
    e->g;
 
    // Drawing edges while preserving the tree layout with constraint=none
    // Very good for annotations.
    edge [color=red,arrowhead=none,constraint=none];
    b->f
    b->g
    d->f
    g->c
}

Hide edge

digraph G
{
  // Hide edge using white color.
  a->b;
  b->c[color="white"];
}

Label Alignment

Label left justified

digraph G {
  label="a\nabc\nabcde";
  labeljust=l; // Left justified label
  someVeryVeryWideNode;
}

Label right justified

digraph G {
  label="a\nabc\nabcde";
  labeljust=r; // Right justified label
  someVeryVeryWideNode;
}

Label extends outside of node

Forcing text to extend outside of the node

digraph G {
  // Use fixedsize=true to fix the size of node.
  // Warning: The label will be cut if there is not enough space for the graph.
  //      Change width=3 to width=0.75, label will be cut.
  node [shape=circle, fixedsize=true];
 
  a [label="A", width=3];
  b [label="Long label extending outside of node", width=0.75];
  a->b;
}

Node without label

digraph G {
    bgcolor=green;
    node [shape=circle, style=filled, label=""]; // Assign empty string to label attribute
 
    a->b->c;
}

Separate Subgraphs

Subgraph must starts with cluster.

Original Graph

digraph G {
 
  subgraph cluster_0 {
    label = "process #1";
    style=filled;
    color=lightgrey;
    node [style=filled,color=white];
    a0 -> a1;
  }
  subgraph cluster_1 {
    label = "process #2";
    color=blue
    node [style=filled];
    b0 -> b1
  }
 
 
  // Link start node to the subgraphs
  start [shape=Mdiamond];
  start->a0;
  start->b0;
}

Separate subgraphs with invisible subgraphs

digraph G {
  // Recursively encapsulate the real subgraph with an invisible subgraph to create space.
 
  // Red color so that you can see.
  subgraph cluster_AddSpaceA1{
    color=red;
    subgraph cluster_AddSpaceA2{
      color=red;
      subgraph cluster_A {
        label = "process #1";
        style=filled;
        color=lightgrey;
        node [style=filled,color=white];
        a0 -> a1;
      }
    }
  }
 
  // Since I set the color to transparent, you will not see the *AddSpaceB* subgraphs.
  subgraph cluster_AddSpaceB1{
    color=transparent;
    subgraph cluster_AddSpaceB2{
      color=transparent;
      subgraph cluster_B {
        label = "process #2";
        color=blue
        node [style=filled];
        b0 -> b1
      }
    }
  }
 
  // Link start node to the subgraphs
  start [shape=Mdiamond];
  start->a0;
  start->b0;
}

Stack Record

digraph StackingRecord 
{
  graph [
    label="Stacking Record",
    labelloc=t,    //t=top, b=bottom
    center=true, 
    rankdir=LR,
 
        ];
 
  node [shape="record"];
  customer [label="Customer | <c0>cID | First Name | Last Name"];
  product [label="Product | pID | <p0>cID | Name | Quantity" ];
 
  customer:c0->product:p0;
 
}

Ticket workflow

digraph G {
  rankdir=LR;
  node [shape=circle];
//  edge [fontsize=8];
 
  "Start"-> "Open" [label="Create"];
  "Open"-> "Fixed" [label="Fix"];
  "Fixed"-> "Closed" [label="Verify"];
  "Fixed"-> "Reopen" [label="Verify"];
  "Reopen"-> "Fixed" [label="Fix"];
  "Closed"-> "Open" [label="Verify"];
 
  "Open"->"Open" [label="Assign"];
 
  // Make start node invisible
  Start[color=white, fontcolor=white];
 
  //{rank=same; "Reopen"; "Fixed";}
}