Skip to content

Instantly share code, notes, and snippets.

@boutros
Last active July 24, 2018 07:00
Show Gist options
  • Save boutros/f99baa0c2d3c17b4a73f4fc26faa6119 to your computer and use it in GitHub Desktop.
Save boutros/f99baa0c2d3c17b4a73f4fc26faa6119 to your computer and use it in GitHub Desktop.
shacl2dot
@base <https://tjenester.deichman.no/ontology/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<ServiceShape>
a sh:NodeShape ;
sh:targetClass <Service> ;
sh:name "Tjeneste"@no ;
sh:property [
sh:name "Bilde"@no ;
sh:path <image> ;
sh:maxCount "1"^^xsd:integer ;
sh:nodeKind sh:IRI
] ;
sh:property [
sh:path <name> ;
sh:name "Navn"@no ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:name "Tjenestetype"@no ;
sh:path <serviceType> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:class <ServiceType>
] ;
sh:property [
sh:name "Tjenesteform"@no ;
sh:path <serviceForm> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:class <ServiceForm>
] ;
sh:property [
sh:name "Status"@no ;
sh:path <status> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:class <Status>
] ;
sh:property [
sh:name "Aldersgrupper"@no ;
sh:path <ageGroup> ;
sh:minCount "1"^^xsd:integer ;
sh:class <AgeGroup>
] ;
sh:property [
sh:name "Målgrupper"@no ;
sh:path <targetAudience> ;
sh:maxCount "1"^^xsd:integer ;
sh:class <TargetAudience>
] ;
sh:property [
sh:name "Beskrivelse eksternt"@no ;
sh:path <descriptionExternal> ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:name "Beskrivelse eksternt"@no ;
sh:path <descriptionInternal> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:path <recommendedFrequency> ;
sh:name "Anbefalt hyppighet"@no ;
sh:maxCount "1"^^xsd:integer ;
sh:class <Frequency>
] ;
sh:property [
sh:path <successCriteria> ;
sh:name "Suksesskriterier"@no ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:path <standard> ;
sh:name "Standard"@no ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:boolean
] ;
sh:property [
sh:name "Navn på lenke"@no ;
sh:path <link> ;
sh:class <Link>
] ;
sh:property [
sh:path <extendedUsage> ;
sh:name "Passer i spesialtid"@no ;
sh:class <ExtendedUsage>
] ;
sh:property [
sh:path <season> ;
sh:name "Sesong"@no ;
sh:class <Season>
] ;
sh:property [
sh:path <tag> ;
sh:name "Triggerord"@no ;
sh:datatype xsd:string
] ;
sh:property [
sh:path <contentElement> ;
sh:name "Innholdselementer"@no ;
sh:class <ContentElement>
] ;
sh:property [
sh:name "Hensikt, mål og ønsket effekt"@no ;
sh:path <expectedEffect> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:name "Innsatsområder"@no ;
sh:path <targetArea> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:class <TargetArea>
] ;
sh:property [
sh:name "Livsløp"@no ;
sh:path <lifecycle> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:class <Lifecycle>
] ;
sh:property [
sh:name "Tjenesteeier"@no ;
sh:path <serviceOwner> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:name "Produktansvarlig"@no ;
sh:path <productResponsibleStaff> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:name "Lokalansvarlig"@no ;
sh:description "Ansvarsperson(er) på filial"@no ;
sh:path <localResponsible> ;
sh:class <Responsible>
] ;
sh:property [
sh:name "Regi"@no ;
sh:path <direction> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:class <Direction>
] ;
sh:property [
sh:name "Samarbeidspartnere"@no ;
sh:path <partner> ;
sh:class <Partner>
] ;
sh:property [
sh:name "Finansiering"@no ;
sh:path <funding> ;
sh:datatype xsd:string
] ;
sh:property [
sh:name "Forbredelsestid (antall timer)"@no ;
sh:path <preparationHours> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:integer
] ;
sh:property [
sh:name "Gjennomføringsressurser (antall personer)"@no ;
sh:path <requiredStaff> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:integer
] ;
sh:property [
sh:name "Andre kostnader gjennomføring"@no ;
sh:path <costs> ;
sh:datatype xsd:string
] .
<ServiceTypeShape>
a sh:NodeShape ;
sh:name "Tjenestetype"@no ;
sh:targetClass <ServiceType> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] .
<ServiceFormShape>
a sh:NodeShape ;
sh:name "Tjenesteform"@no ;
sh:targetClass <ServiceForm> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] .
<StatusShape>
a sh:NodeShape ;
sh:name "Status"@no ;
sh:targetClass <Status> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] .
<AgeGroupShape>
a sh:NodeShape ;
sh:name "Aldersgruppe"@no ;
sh:targetClass <AgeGroup> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:name "Fra og med år"@no ;
sh:path <fromYear> ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:integer
] ;
sh:property [
sh:name "Til og med år"@no ;
sh:path <toYear> ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:integer
] .
<TargetAudienceShape>
a sh:NodeShape ;
sh:name "Målgruppe"@no ;
sh:targetClass <TargetAudience> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:name "Beskrivelse"@no ;
sh:path <description> ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] .
<FrequencyShape>
a sh:NodeShape ;
sh:name "Hyppighet"@no ;
sh:targetClass <Frequency> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] .
<LinkShape>
a sh:NodeShape ;
sh:name "Lenke"@no ;
sh:targetClass <Link> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] .
<ExtendedUsageShape>
a sh:NodeShape ;
sh:name "Spesialtid"@no ;
sh:targetClass <ExtendedUsage> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] .
<SeasonShape>
a sh:NodeShape ;
sh:name "Sesong"@no ;
sh:targetClass <Season> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] .
<ContentElementShape>
a sh:NodeShape ;
sh:name "Innholdselement"@no ;
sh:targetClass <ContentElement> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:name "Beskrivelse"@no ;
sh:path <description> ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:name "Bibliotek"@no ;
sh:path <branch> ;
sh:class <Branch>
] .
<BranchShape>
a sh:NodeShape ;
sh:name "Bibliotek"@no ;
sh:targetClass <Branch> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:name "Service"@no ;
sh:path <service> ;
sh:class <Service>
] .
<TargetAreaShape>
a sh:NodeShape ;
sh:name "Innsatsområde"@no ;
sh:targetClass <TargetArea> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] .
<LifecycleShape>
a sh:NodeShape ;
sh:name "Livsløp"@no ;
sh:targetClass <Lifecycle> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:name "Beskrivelse"@no ;
sh:path <description> ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] .
<ResponsibleShape>
a sh:NodeShape ;
sh:name "Ansvarlig ansatt"@no ;
sh:targetClass <Responsible> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:name "Bibliotek/avdeling"@no ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:path <branch> ;
sh:class <Branch>
] .
<DirectionShape>
a sh:NodeShape ;
sh:name "Regi"@no ;
sh:targetClass <Direction> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] .
<PartnerShape>
a sh:NodeShape ;
sh:name "Partner"@no ;
sh:targetClass <Partner> ;
sh:property [
sh:name "Navn"@no ;
sh:path <name> ;
sh:minCount "1"^^xsd:integer ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] ;
sh:property [
sh:name "Målgruppe"@no ;
sh:path <audience> ;
sh:maxCount "1"^^xsd:integer ;
sh:datatype xsd:string
] .
package main
import (
"fmt"
"io"
"log"
"os"
"strings"
"github.com/knakk/kbp/rdf"
)
var prefixes = strings.NewReplacer("http://www.w3.org/2001/XMLSchema#", "xsd:", "<", "", ">", "")
type NodeShape struct {
Class string
Name string
Literals []Literal
}
type Literal struct {
Name string
Path string
Datatype string
Class string
MustHaveOne bool
CanHaveMore bool
}
func (l Literal) String() string {
must := " "
can := " "
if l.MustHaveOne {
must = "*"
}
if l.CanHaveMore {
must = "+"
}
return fmt.Sprintf("%s%s <b>%s</b> (%s)", must, can, l.Name, l.Datatype)
}
type Link struct {
From string
To string
Name string
Path string
MustHaveOne bool
CanHaveMore bool
}
func (l Link) String() string {
must := " "
can := " "
if l.MustHaveOne {
must = "*"
}
if l.CanHaveMore {
must = "+"
}
return fmt.Sprintf("%s%s <b>%s</b>", must, can, l.Name)
}
func main() {
f, err := os.Open("schema.ttl")
if err != nil {
log.Fatal(err)
}
defer f.Close()
dec := rdf.NewDecoder(f)
nodes := make(map[rdf.Node]NodeShape)
var links []Link
var curNode rdf.Node
var curLiteral *Literal
for tr, err := dec.Decode(); err != io.EOF; tr, err = dec.Decode() {
if err != nil {
log.Fatal(err)
}
switch tr.Predicate {
case rdf.RDFtype:
if curLiteral != nil {
if curLiteral.Class == "" {
n := nodes[curNode]
n.Literals = append(n.Literals, *curLiteral)
nodes[curNode] = n
} else {
links = append(links, Link{Path: curLiteral.Path, From: nodes[curNode].Class, To: curLiteral.Class, Name: curLiteral.Name, MustHaveOne: curLiteral.MustHaveOne, CanHaveMore: curLiteral.CanHaveMore})
}
}
curLiteral = nil
curNode = tr.Subject
if _, ok := nodes[curNode]; !ok {
nodes[curNode] = NodeShape{}
}
case rdf.SHclass:
curLiteral.Class = tr.Object.String()
case rdf.SHpath:
curLiteral.Path = tr.Object.String()
case rdf.SHtargetClass:
n := nodes[curNode]
n.Class = tr.Object.String()
nodes[curNode] = n
case rdf.SHproperty:
if curLiteral != nil {
if curLiteral.Class == "" {
n := nodes[curNode]
n.Literals = append(n.Literals, *curLiteral)
nodes[curNode] = n
} else {
links = append(links, Link{Path: curLiteral.Path, From: nodes[curNode].Class, To: curLiteral.Class, Name: curLiteral.Name, MustHaveOne: curLiteral.MustHaveOne, CanHaveMore: curLiteral.CanHaveMore})
}
}
curLiteral = &Literal{
CanHaveMore: true,
}
case rdf.SHname:
if curLiteral == nil {
n := nodes[curNode]
n.Name = tr.Object.(rdf.Literal).ValueAsString()
nodes[curNode] = n
} else {
curLiteral.Name = tr.Object.(rdf.Literal).ValueAsString()
}
case rdf.SHminCount:
curLiteral.MustHaveOne = true
case rdf.SHMaxCount:
curLiteral.CanHaveMore = false
case rdf.SHdatatype:
curLiteral.Datatype = prefixes.Replace(tr.Object.String())
default:
}
}
//fmt.Println(nodes)
//fmt.Println("")
//fmt.Println(links)
if curLiteral != nil {
if curLiteral.Class == "" {
n := nodes[curNode]
n.Literals = append(n.Literals, *curLiteral)
nodes[curNode] = n
} else {
links = append(links, Link{From: nodes[curNode].Class, To: curLiteral.Class, Name: curLiteral.Name, MustHaveOne: curLiteral.MustHaveOne, CanHaveMore: curLiteral.CanHaveMore})
}
curLiteral = nil
}
fmt.Printf(`digraph Ontology {
graph [overlap=voronoi, ranksep=1.3, splines=curved]
node [shape=plaintext fontname="Sans serif" fontsize="8"];
edge [fontname="Sans serif", fontsize="8"];
`)
for _, node := range nodes {
fmt.Printf(` %s [label=<
<table border="1" cellborder="0" cellspacing="1" width="100">
<tr><td bgcolor='#e0e0e0'>%s</td><td bgcolor='#e0e0e0'><b>%s</b></td></tr>
`, strip(node.Class), escape(node.Class), node.Name)
for _, lit := range node.Literals {
fmt.Printf(` <tr><td align="left">%s</td><td align="left">%s</td></tr>
`, escape(lit.Path), lit.String())
}
fmt.Printf(`</table>>];
`)
}
for _, link := range links {
if link.From == "" || link.To == "" {
continue
}
fmt.Printf("%s -> %s [label=<%s>];\n", strip(link.From), strip(link.To), link.String())
}
fmt.Println(`}`)
}
func strip(s string) string {
return s[1 : len(s)-1]
}
func escape(s string) string {
return "&lt;" + strip(s) + "&gt;"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment