This is a pure-Ruby library for working with the Shape Expressions Language to validate the shape of RDF graphs.
The ShEx gem implements a ShEx Shape Expression engine version 2.0.
ShEx::Parser
parses ShExC and ShExJ formatted documents generating executable operators which can be serialized as [S-Expressions][].ShEx::Algebra
executes operators against Any RDF::Graph
, including compliant RDF.rb.require 'rdf/turtle'
require 'shex'
shexc = %(
PREFIX doap: <http://usefulinc.com/ns/doap#>
PREFIX dc: <http://purl.org/dc/terms/>
PREFIX ex: <http://example.com/>
ex:TestShape EXTRA a {
a [doap:Project];
( doap:name Literal;
doap:description Literal
| dc:title Literal;
dc:description Literal)+;
doap:category IRI*;
doap:developer IRI+;
doap:implements [<http://shex.io/shex-semantics/>]
}
)
graph = RDF::Graph.load("etc/doap.ttl")
schema = ShEx.parse(shexc)
map = {
RDF::URI("https://rubygems.org/gems/shex") => RDF::URI("http://example.com/TestShape")
}
schema.satisfies?(graph, map)
# => true
require 'rubygems'
require 'rdf/turtle'
require 'shex'
shexj = %({
"@context": "http://www.w3.org/ns/shex.jsonld",
"type": "Schema",
"shapes": [{
"id": "http://example.com/TestShape",
"type": "Shape",
"extra": ["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"],
"expression": {
"type": "EachOf",
"expressions": [{
"type": "TripleConstraint",
"predicate": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
"valueExpr": {
"type": "NodeConstraint",
"values": ["http://usefulinc.com/ns/doap#Project"]
}
}, {
"type": "OneOf",
"expressions": [{
"type": "EachOf",
"expressions": [{
"type": "TripleConstraint",
"predicate": "http://usefulinc.com/ns/doap#name",
"valueExpr": {
"type": "NodeConstraint",
"nodeKind": "literal"
}
}, {
"type": "TripleConstraint",
"predicate": "http://usefulinc.com/ns/doap#description",
"valueExpr": {
"type": "NodeConstraint",
"nodeKind": "literal"
}
}]
}, {
"type": "EachOf",
"expressions": [{
"type": "TripleConstraint",
"predicate": "http://purl.org/dc/terms/title",
"valueExpr": {
"type": "NodeConstraint",
"nodeKind": "literal"
}
}, {
"type": "TripleConstraint",
"predicate": "http://purl.org/dc/terms/description",
"valueExpr": {
"type": "NodeConstraint",
"nodeKind": "literal"
}
}]
}],
"min": 1,
"max": -1
}, {
"type": "TripleConstraint",
"predicate": "http://usefulinc.com/ns/doap#category",
"valueExpr": {
"type": "NodeConstraint",
"nodeKind": "iri"
},
"min": 0,
"max": -1
}, {
"type": "TripleConstraint",
"predicate": "http://usefulinc.com/ns/doap#developer",
"valueExpr": {
"type": "NodeConstraint",
"nodeKind": "iri"
},
"min": 1,
"max": -1
}, {
"type": "TripleConstraint",
"predicate": "http://usefulinc.com/ns/doap#implements",
"valueExpr": {
"type": "NodeConstraint",
"values": [
"http://shex.io/shex-semantics/"
]
}
}
]
}
}
]})
graph = RDF::Graph.load("etc/doap.ttl")
schema = ShEx.parse(shexj, format: :shexj)
map = {
RDF::URI("https://rubygems.org/gems/shex") => RDF::URI("http://example.com/TestShape")
}
schema.satisfies?(graph, map)
# => true
ShEx has an extension mechanism using Semantic Actions. Extensions may be implemented in Ruby ShEx by sub-classing {ShEx::Extension} and implementing {ShEx::Extension#visit} and possibly {ShEx::Extension#initialize}, {ShEx::Extension#enter}, {ShEx::Extension#exit}, and {ShEx::Extension#close}. The #visit
method will be called as part of the #satisfies?
operation.
require 'shex'
class ShEx::Test < ShEx::Extension("http://shex.io/extensions/Test/")
# (see ShEx::Extension#initialize)
def initialize(schema: nil, logger: nil, depth: 0, **options)
...
end
# (see ShEx::Extension#visit)
def visit(code: nil, matched: nil, expression: nil, depth: 0, **options)
...
end
end
The #enter
method will be called on any {ShEx::Algebra::TripleExpression} that includes a {ShEx::Algebra::SemAct} referencing the extension, while the #exit
method will be called on exit, even if not satisfied.
The #initialize
method is called when {ShEx::Algebra::Schema#execute} starts and #close
called on exit, even if not satisfied.
To make sure your extension is found, make sure to require it before the shape is executed.
When the linkeddata
gem is installed, RDF.rb includes a rdf
executable which acts as a wrapper to perform a number of different
operations on RDF files, including ShEx. The commands specific to ShEx is
shex
: Validate repository given shapeUsing this command requires either a shex-input
where the ShEx schema is URI encoded, or shex
, which references a URI or file path to the schema. Other required options are shape
and focus
.
Example usage:
rdf shex https://raw.githubusercontent.com/ruby-rdf/shex/develop/etc/doap.ttl \
--schema https://raw.githubusercontent.com/ruby-rdf/shex/develop/etc/doap.shex \
--focus https://rubygems.org/gems/shex
https://ruby-rdf.github.io/shex
The ShExC parser uses the EBNF gem to generate a PEG parser.
The parser uses the executable [S-Expressions][] generated from the EBNF ShExC grammar to create a set of executable {ShEx::Algebra} Operators which are directly executed to perform shape validation.
The recommended installation method is via RubyGems. To install the latest official release of RDF.rb, do:
% [sudo] gem install shex
To get a local working copy of the development repository, do:
% git clone git://github.com/ruby-rdf/shex.git
Alternatively, download the latest development version as a tarball as follows:
% wget https://github.com/ruby-rdf/shex/tarball/master
This repository uses Git Flow to mange development and release activity. All submissions must be on a feature branch based on the develop branch to ease staging and integration.
git diff --check
to make sure of this..gemspec
or VERSION
files. If you need to change them,
do so on your private branch only.CREDITS
file and the
corresponding list in the the README
. Alphabetical order applies.AUTHORS
file. If your contributions are significant
enough, be assured we will eventually add you in there.This is free and unencumbered public domain software. For more information, see https://unlicense.org/ or the accompanying {file:LICENSE} file.