-
Notifications
You must be signed in to change notification settings - Fork 89
SPARQLScript
Many RDF toolkits provide SPARQL/Update functionality and move from simple query operations to more powerful data manipulation. SPARQLScript goes another step further and enables or simplifies the implementation of
- semantic Mashups,
- custom, portable rule and inference scripts using a SPARQL-based syntax
- Output templates for RDF data and SPARQL query results
- RDF/SPARQL-driven Yahoo! Pipes-like systems
SPARQLScript is meant to
- look and feel like a simple scripting language (i.e. it's not purely declarative)
- re-use SPARQL syntax where possible (ARC feedback suggests that SPARQL is probably the most intuitive SemWeb syntax for Not-Yet-SemWeb developers. Many ARC users never studied the SPARQL spec and still find their way around with SQL knowledge and some examples)
- allow the intuitive combination and processing of native SPARQL result types such as record sets (SELECT), RDF graphs (CONSTRUCT, DESCRIBE), and TRUE/FALSE (ASK)
SPARQLScript allows the specification of target SPARQL/SPARUL/SPARQL+ endpoints which should be used for queries. A SPARQLScript processor may fall back to a default endpoint or local SPARQL store if no endpoint is defined in the script.
ENDPOINT <http://dbpedia.org/sparql>
SELECT ...
SPARQLScript allows the sequential execution of SPARQL queries.
LOAD <http://example.com/g1>
LOAD <http://example.com/g2>
SELECT * WHERE { ... }
...
PREFIX declarations have a script-wide scope and can be shared by multiple queries.
PREFIX foaf: <http://...>
SELECT ?name WHERE { ?s foaf:name ?name}
SELECT ?nick WHERE { ?s foaf:nick ?nick}
Variables can be used to combine the results from one operation with those from another one.
$doc := CONSTRUCT ...
$bool := ASK ...
$rows := SELECT ...
$text := "foo bar baz"
$text2 := $text
(Assignments work with either ":=" or just "=".)
It is possible to merge the values of two variables:
$rows1 = SELECT ...
$rows2 = SELECT ...
$rows = $rows1 + $rows2
SPARQLScript re-uses a simple and widely deployed notation for placeholder definitions that can be injected in scripts and strings. Property paths and extended syntax is supported for certain structures such as dates (via NOW), GET/POST arguments, or string manipulation.
# very simple
$foo := "Foo"
$bar := ${foo} # $bar is now "Foo" (and yes, we could have simply used $bar = $foo)
# query placeholder
$name := "John Doe"
SELECT * WHERE {?person foaf:name "${name}"} # ${name} will be replaced with "John Doe" before the query is evaluated
# pre-defined constant NOW with offset functionality
SELECT * WHERE {?s dc:date ?date . FILTER ($date < "${NOW - 2h}") }
# access to GET and POST
$my_arg = ${GET.my_arg}
# property paths
$items = SELECT * WHERE {?item a rss:item ; rss:title ?title . };
$first_title = ${items.0.title}
# string concatenation
$str = "Hello"
$str = "${str} World"
# string manipulation (1st argument = regular expression)
$str = ${str.replace("/world/i", "Mom")}
# URL-encoding
$str = ${str.urlEncode("get")} # space to "+"
$str = ${str.urlEncode("post")} # space to "%20" etc.
SPARQLScript supports conditional evaluation of script blocks:
$exists := ASK ...
IF ($exists) {
DELETE FROM ...
}
ELSE {
INSERT INTO ...
}
SPARQLScript supports iterating through query result sets:
$items := SELECT * WHERE {?item a rss:item ; rss:title ?title . };
FOR ($row in $items) {
$title := ${row.title}
$uri := ${row.item}
}
Stand-alone SPARQL/Turtle literals are added to the SPARQLScript processor's output buffer. This simple method to create custom results can be combined with the other features such as loops and placeholders:
$items = SELECT * WHERE {?item a rss:item ; rss:title ?title . };
$size = ${items.size}
IF ($size) {
""" I found ${items.size} items: <ul> """
FOR ($item in $items) {
"<li>${item.title}</li>"
}
" </ul> "
}
ELSE { " no items found "}
If a recordset or array is used in a template, the SPARQLScript processor will try to auto-detect the target format and serialize the given array.
$res = DESCRIBE <http://example.com/foaf.rdf#self>
# generate an RDF document
# (JSON, XML, Turtle, depending on Accept headers or GET parameter "format")
"${res}"
Script ::= (Query | EndpointDecl | PrefixDecl | Assignment | IFBlock | FORBlock | String | FunctionCall)*
EndpointDecl ::= 'ENDPOINT' IRI_REF
Assignment ::= Var (':=' | '=') ( Query | String | Var | Placeholder | VarMerge) ';'?
IFBlock ::= 'IF' BrackettedExpression '{' Script '}' ( 'ELSE' '{' Script '}')?
FORBlock ::= 'FOR' '(' Var 'IN' Var ')' '{' Script '}'
Placeholder ::= ('$' | '?') '{' [^}]* '}'
VarMerge ::= Var '+' Var
ARC's SPARQLScript processor is instantiated like the RDF Store component. If you are going to work with external SPARQL endpoints only, you don't need to define a store (or database connection). The number of queries or general script operation can be limited (see snippet below).
/* ARC2 static class inclusion */
include_once('path/to/arc/ARC2.php');
/* configuration */
$config = array(
/* db */
...
/* store name */
...
/* sparqlscript */
'sparqlscript_default_endpoint' => 'http://...|local', /* uses defined store if set to "local" */
'sparqlscript_max_operations' => 100, /* queries, assignments, endpoint declarations */
'sparqlscript_max_queries' => 10 /* restricts the allowed number of queries */
);
/* instantiation */
$ssp = ARC2::getSPARQLScriptProcessor($config);
/* script evaluation */
$scr = '
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dbpedia2: <http://dbpedia.org/property/>
ENDPOINT <http://dbpedia.org/sparql>
$rows = SELECT ?person ?name ?birth WHERE {
?person dbpedia2:birthPlace <http://dbpedia.org/resource/Berlin> .
?person dbpedia2:birth ?birth .
?person foaf:name ?name .
}
LIMIT 10
...
';
$ssp->processScript($scr);
echo $ssp->env['output'];