Search code examples
xmlperlgraphgraphml

graphml or dotml how to


For an assignment we have been told, for additional functionality output a graph, possible using GraphViz. That is all the info we have been given.

The assignment is perl outputting XML. I am pretty sure that I can ouput the code, I just need to know how to process it from there.

I have done some research i have been trying to test some simple code.

for DOTML I found this simple example from http://www.martin-loetzsch.de/DOTML/

<graph  file-name="graphs/nice_graph" rankdir="LR">

    <node   id="a" label="node1" fontsize="9" fontname="Arial"/>
    <node   id="b" label="node2" fontsize="9" fontname="Arial"/>
    <node   id="c" label="node3" fontsize="9" fontname="Arial"/>
    <node   id="d" label="node4" fontsize="9" fontname="Arial"/>
    <edge   from="a" to="b" fontname="Arial" fontsize="9" label="edge1"/>
    <edge   from="a" to="c" fontname="Arial" fontsize="9" label="edge2"/>
    <edge   from="b" to="c" fontname="Arial" fontsize="9" label="edge3"/>
    <edge   from="b" to="d" fontname="Arial" fontsize="9" label="edge4"/>
    <edge   from="c" to="d" fontname="Arial" fontsize="9" label="edge5"/>
</graph>

I tried to run it from the command line with this

dot -Tps graph1.dot -o graph1.ps 

and

dot -Tps graph1.dot -o graph

which throws this error

Error: graph_test.dotml:1: syntax error near line 1
context: <graph         file-name="graph" >>>  rankdir="LR"> <<<

I have also tried the same for a graphml file, here is the head of the file

<?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 id="G" edgedefault="undirected">

which basically throws the same error

Error: simple.graphml:1: syntax error near line 1
context: <?xml version="1.0" >>>  encoding="UTF-8"?> <<

If anyone could at least direct me where to get some good, basic instructions on how to implement it would be good. Cheers

EDIT: we are only able to use default CPAN modules


Solution

  • You need to convert GraphML to DOT. You can get a complete XSLT stylesheet that does that here:

    http://graphml.graphdrawing.org/download.html
    

    To convert the XML graph that you posted as an example, you can a XSLT stylesheet like this one (which is very limited and will work only with very simple graphs - I use it as a teaching example):

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:output method="text"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:template match="graph|digraph">
            <xsl:value-of select="name()"/>
            <xsl:text> {&#xa;</xsl:text>
            <xsl:apply-templates select="@rankdir|node()"/>
            <xsl:text>}</xsl:text>
        </xsl:template>
    
        <xsl:template match="@rankdir">
            <xsl:text>rankdir = </xsl:text>
            <xsl:value-of select="."/>
            <xsl:text>;&#xa;</xsl:text>
        </xsl:template>
    
        <xsl:template match="node">
            <xsl:value-of select="@id"/>
            <xsl:if test="@*[not(name()='id')]">
                <xsl:text> [</xsl:text>
                <xsl:for-each select="@*[not(name()='id')]">
                    <xsl:value-of select="name()"/>
                    <xsl:text>=&quot;</xsl:text>
                    <xsl:value-of select="."/>
                    <xsl:text>&quot;</xsl:text>
                    <xsl:if test="not(position()=last())">
                        <xsl:text>, </xsl:text>
                    </xsl:if>
                </xsl:for-each>
                <xsl:text>];&#xa;</xsl:text>
            </xsl:if>
        </xsl:template>
    
        <xsl:template match="edge">
            <xsl:value-of select="@from"/>
            <xsl:choose>
                <xsl:when test="parent::*[name()='graph']">
                    <xsl:text> -- </xsl:text>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text> -> </xsl:text>
                </xsl:otherwise>
            </xsl:choose>
            <xsl:value-of select="@to"/>
            <xsl:if test="@*[not(name()='from')][not(name()='to')]">
                <xsl:text> [</xsl:text>
                <xsl:for-each select="@*[not(name()='from')][not(name()='to')]">
                    <xsl:value-of select="name()"/>
                    <xsl:text>=&quot;</xsl:text>
                    <xsl:value-of select="."/>
                    <xsl:text>&quot;</xsl:text>
                    <xsl:if test="not(position()=last())">
                        <xsl:text>, </xsl:text>
                    </xsl:if>
                </xsl:for-each>
                <xsl:text>];&#xa;</xsl:text>
            </xsl:if>
        </xsl:template>
    
    </xsl:stylesheet>
    

    In this fiddle I used it to convert your GraphML document into a DOT document which you can use with the command-line DOT application:

    graph {
    rankdir = LR;
    a [label="node1", fontsize="9", fontname="Arial"];
    b [label="node2", fontsize="9", fontname="Arial"];
    c [label="node3", fontsize="9", fontname="Arial"];
    d [label="node4", fontsize="9", fontname="Arial"];
    a -- b [fontname="Arial", fontsize="9", label="edge1"];
    a -- c [fontname="Arial", fontsize="9", label="edge2"];
    b -- c [fontname="Arial", fontsize="9", label="edge3"];
    b -- d [fontname="Arial", fontsize="9", label="edge4"];
    c -- d [fontname="Arial", fontsize="9", label="edge5"];
    }
    

    Rename the code above to something.dot and run it using Graphviz or dot and it should generate a graph.

    You can run XSLT with the Lib::XSLT CPAN module.