"""
A commandline tool for drawing RDFS Class diagrams in Graphviz DOT
format
You can draw the graph of an RDFS file directly:
.. code-block: bash
rdf2dot my_rdfs_file.rdf | dot -Tpng | display
"""
import collections
import itertools
import sys
import rdflib.extras.cmdlineutils
from rdflib import RDF, RDFS, XSD
XSDTERMS = [
XSD[x]
for x in (
"anyURI",
"base64Binary",
"boolean",
"byte",
"date",
"dateTime",
"decimal",
"double",
"duration",
"float",
"gDay",
"gMonth",
"gMonthDay",
"gYear",
"gYearMonth",
"hexBinary",
"ID",
"IDREF",
"IDREFS",
"int",
"integer",
"language",
"long",
"Name",
"NCName",
"negativeInteger",
"NMTOKEN",
"NMTOKENS",
"nonNegativeInteger",
"nonPositiveInteger",
"normalizedString",
"positiveInteger",
"QName",
"short",
"string",
"time",
"token",
"unsignedByte",
"unsignedInt",
"unsignedLong",
"unsignedShort",
)
]
EDGECOLOR = "blue"
NODECOLOR = "black"
ISACOLOR = "black"
[docs]def rdfs2dot(g, stream, opts={}):
"""
Convert the RDFS schema in a graph
writes the dot output to the stream
"""
fields = collections.defaultdict(set)
nodes = {}
def node(nd):
if nd not in nodes:
nodes[nd] = "node%d" % len(nodes)
return nodes[nd]
def label(xx, grf):
lbl = grf.value(xx, RDFS.label)
if lbl is None:
try:
lbl = grf.namespace_manager.compute_qname(xx)[2]
except Exception:
pass # bnodes and some weird URIs cannot be split
return lbl
stream.write('digraph { \n node [ fontname="DejaVu Sans" ] ; \n')
for x in g.subjects(RDF.type, RDFS.Class):
n = node(x)
for x, y in g.subject_objects(RDFS.subClassOf):
x = node(x)
y = node(y)
stream.write("\t%s -> %s [ color=%s ] ;\n" % (y, x, ISACOLOR))
for x in g.subjects(RDF.type, RDF.Property):
for a, b in itertools.product(
g.objects(x, RDFS.domain), g.objects(x, RDFS.range)
):
if b in XSDTERMS or b == RDFS.Literal:
l_ = label(b, g)
if b == RDFS.Literal:
l_ = "literal"
fields[node(a)].add((label(x, g), l_))
else:
# if a in nodes and b in nodes:
stream.write(
'\t%s -> %s [ color=%s, label="%s" ];\n'
% (node(a), node(b), EDGECOLOR, label(x, g))
)
for u, n in nodes.items():
stream.write("# %s %s\n" % (u, n))
f = [
"<tr><td align='left'>%s</td><td>%s</td></tr>" % x
for x in sorted(fields[n])
]
opstr = (
"%s [ shape=none, color=%s label=< <table color='#666666'"
+ " cellborder='0' cellspacing='0' border='1'><tr>"
+ "<td colspan='2' bgcolor='grey'><B>%s</B></td>"
+ "</tr>%s</table> > ] \n"
)
stream.write(opstr % (n, NODECOLOR, label(u, g), "".join(f)))
stream.write("}\n")
def _help():
sys.stderr.write(
"""
rdfs2dot.py [-f <format>] files...
Read RDF files given on STDOUT, writes a graph of the RDFS schema in
DOT language to stdout
-f specifies parser to use, if not given,
"""
)
[docs]def main():
rdflib.extras.cmdlineutils.main(rdfs2dot, _help)
if __name__ == "__main__":
main()