This is a Ruby implementation of SPARQL for RDF.rb.
- 100% free and unencumbered public domain software.
- SPARQL 1.1 Query parsing and execution (excluding Property Paths)
- SPARQL results as XML, JSON, CSV, TSV or HTML.
- SPARQL CONSTRUCT or DESCRIBE serialized based on Format, Extension of Mime Type using available RDF Writers (see Linked Data)
- SPARQL Client for accessing remote SPARQL endpoints.
- Rack and Sinatra middleware to perform HTTP content negotiation for result formats
- Compatible with any Rack or Sinatra application and any Rack-based framework.
- Helper method for describing SPARQL Service Description
- Compatible with Ruby >= 1.9.2.
- Compatible with older Ruby versions with the help of the Backports gem.
- Supports Unicode query strings both on all versions of Ruby.
The {SPARQL} gem implements SPARQL 1.1 Query, and provides Rack and Sinatra middleware to provide results using HTTP Content Negotiation.
- {SPARQL::Grammar} implements a SPARQL 1.1 Query parser generating SPARQL S-Expressions (SSE).
- Support for Property Paths is excluded. See the section on SPARQL 1.1 Query extensions and limitations for further detail.
- {SPARQL::Algebra} executes SSE against Any
RDF::Graph
orRDF::Repository
, including compliant RDF.rb repository adaptors such as RDF::DO and RDF::Mongo. - {Rack::SPARQL} and {Sinatra::SPARQL} provide middleware components to format results using an appropriate format based on HTTP content negotiation.
SPARQL 1.1 Query Extensions and Limitations
The {SPARQL} gem uses the SPARQL 1.1 Query {file:etc/sparql11.bnf EBNF grammar}, which provides much more capability than SPARQL 1.0, but has a few limitations:
- The format for decimal datatypes has changed in RDF 1.1; they may no longer have a trailing ".", although they do not need a leading digit.
- BNodes may now include extended characters, including ".".
The SPARQL gem now implements the following SPARQL 1.1 Query operations:
The only major area of SPARQL 1.1 Query missing is Property Paths, which will be in later release along with:
either in this, or related gems.
Starting with version 1.1.2, the SPARQL gem uses the 1.1 version of the RDF.rb, which adheres to RDF 1.1 Concepts rather than RDF 1.0. The main difference is that there is now no difference between a Simple Literal (a literal with no datatype or language) and a Literal with datatype xsd:string; this causes some minor differences in the way in which queries are understood, and when expecting different results.
Additionally, queries now take a block, or return an Enumerator
; this is in keeping with much of the behavior of RDF.rb methods, including Queryable#query
, and with version 1.1 or RDF.rb, Query#execute. As a consequence, all queries which used to be of the form query.execute(repository)
may equally be called as repository.query(query)
. Previously, results were returned as a concrete class implementing RDF::Queryable
or RDF::Query::Solutions
, these are now Enumerators
.
Extension functions may be defined, which will be invoked during query evaluation. For example:
# Register a function using the IRI <http://rubygems.org/gems/sparql#crypt>
crypt_iri = RDF::URI("http://rubygems.org/gems/sparql#crypt")
SPARQL::Algebra::Expression.register_extension(crypt_iri) do |literal|
raise TypeError, "argument must be a literal" unless literal.literal?
RDF::Literal(literal.to_s.crypt)
end
Then, use the function in a query:
PREFIX rsp: <http://rubygems.org/gems/sparql#>
PREFIX schema: <http://schema.org/>
SELECT ?crypted
{
[ schema:email ?email]
BIND(rsp:crypt(?email) AS ?crypted)
}
See {SPARQL::Algebra::Expression.register_extension} for details.
{Rack::SPARQL} is a superset of Rack::LinkedData to allow content negotiated results
to be returned any RDF::Enumerable
or an enumerator extended with RDF::Query::Solutions
compatible results.
You would typically return an instance of RDF::Graph
, RDF::Repository
or an enumerator extended with RDF::Query::Solutions
from your Rack application, and let the Rack::SPARQL::ContentNegotiation
middleware
take care of serializing your response into whatever format the HTTP
client requested and understands.
{Sinatra::SPARQL} is a thin Sinatra-specific wrapper around the {Rack::SPARQL} middleware, which implements SPARQL content negotiation for Rack applications. {Sinatra::SPARQL} also supports SPARQL 1.1 Service Description.
The middleware queries RDF.rb for the MIME content types of known RDF serialization formats, so it will work with whatever serialization extensions that are currently available for RDF.rb. (At present, this includes support for N-Triples, N-Quads, Turtle, RDF/XML, RDF/JSON, JSON-LD, RDFa, TriG and TriX.)
A SPARQL query containing FROM
or FROM NAMED
will load the referenced IRI unless the repository
already contains a context with that same IRI. This is performed using RDF.rb RDF::Util::File.open_file
passing HTTP Accept headers for various available RDF formats. For best results, require Linked Data to enable
a full set of RDF formats in the GET
request. Also, consider overriding RDF::Util::File.open_file
with
an implementation with support for HTTP Get headers (such as Net::HTTP
).
Queries using datasets are re-written to use the identified graphs for FROM
and FROM NAMED
by filtering the results, allowing the use of a repository that contains many graphs without confusing information.
SPARQL.serialize_results
may be used on it's own, or in conjunction with {Rack::SPARQL} or {Sinatra::SPARQL}
to provide content-negotiated query results. For basic SELECT
and ASK
this includes HTML, XML, CSV, TSV and JSON formats.
DESCRIBE
and CONSTRUCT
create an RDF::Graph
, which can be serialized through HTTP Content Negotiation
using available RDF writers. For best results, require Linked Data to enable
a full set of RDF formats.
require 'rubygems'
require 'sparql'
queryable = RDF::Repository.load("etc/doap.ttl")
sse = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
queryable.query(sse) do |result|
result.inspect
end
queryable = RDF::Repository.load("etc/doap.ttl")
sse = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
sse.execute(queryable) do |result|
result.inspect
end
queryable = RDF::Repository.load("etc/doap.ttl")
solutions = SPARQL.execute("SELECT * WHERE { ?s ?p ?o }", queryable)
solutions.to_json #to_xml #to_csv #to_tsv #to_html
sse = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
sse.to_sxp #=> (bgp (triple ?s ?p ?o))
sparql --default-graph etc/doap.ttl etc/from_default.rq
sparql -e "SELECT * FROM <etc/doap.ttl> WHERE { ?s ?p ?o }"
# Generate SPARQL Algebra Expression (SSE) format
sparql --to-sse etc/input.rq
sparql --to-sse -e "SELECT * WHERE { ?s ?p ?o }"
# Run query using SSE input
sparql --default-graph etc/doap.ttl --sse etc/input.sse
sparql --sse -e "(dataset (<etc/doap.ttl>) (bgp (triple ?s ?p ?o))))"
# config/application.rb
require 'rack/sparql'
class Application < Rails::Application
config.middleware.use Rack::SPARQL::ContentNegotiation
end
#!/usr/bin/env rackup
require 'rack/sparql'
repository = RDF::Repository.new do |graph|
graph << [RDF::Node.new, RDF::DC.title, "Hello, world!"]
end
results = SPARQL.execute("SELECT * WHERE { ?s ?p ?o }", repository)
use Rack::SPARQL::ContentNegotiation
run lambda { |env| [200, {}, results] }
# Sinatra example
#
# Call as http://localhost:4567/sparql?query=uri,
# where `uri` is the URI of a SPARQL query, or
# a URI-escaped SPARQL query, for example:
# http://localhost:4567/?query=SELECT%20?s%20?p%20?o%20WHERE%20%7B?s%20?p%20?o%7D
require 'sinatra'
require 'sinatra/sparql'
require 'uri'
get '/' do
settings.sparql_options.replace(:standard_prefixes => true)
repository = RDF::Repository.new do |graph|
graph << [RDF::Node.new, RDF::DC.title, "Hello, world!"]
end
if params["query"]
query = params["query"].to_s.match(/^http:/) ? RDF::Util::File.open_file(params["query"]) : ::URI.decode(params["query"].to_s)
SPARQL.execute(query, repository)
else
settings.sparql_options.merge!(:prefixes => {
:ssd => "http://www.w3.org/ns/sparql-service-description#",
:void => "http://rdfs.org/ns/void#"
})
service_description(:repo => repository)
end
end
Find more examples in {SPARQL::Grammar} and {SPARQL::Algebra}.
Full documentation available on Rubydoc.info
- {SPARQL}
- {SPARQL::Algebra}
- {SPARQL::Algebra::Expression}
- {SPARQL::Algebra::Query}
- {SPARQL::Algebra::Operator}
- {SPARQL::Grammar}
- {SPARQL::Grammar::Parser}
- {SPARQL::Algebra}
- {Sinatra::SPARQL}
- {Rack::SPARQL}
- {Rack::SPARQL::ContentNegotiation}
- Ruby (>= 1.9.2)
- RDF.rb (>= 1.0.7)
- SPARQL::Client (>= 1.0.3)
- SXP (>= 0.1.0)
- Builder (>= 3.0.0)
- JSON (>= 1.5.1)
- Soft dependency on Linked Data (>= 1.0)
- Soft dependency on Nokogiri (>= 1.5.0) Falls back to REXML for XML parsing Builder for XML serializing. Nokogiri is much more efficient
- Soft dependency on Equivalent XML (>= 0.3.0) Equivalent XML performs more efficient comparisons of XML Literals when Nokogiri is included
- Soft dependency on Rack (>= 1.4.4)
- Soft dependency on Sinatra (>= 1.3.3)
The recommended installation method is via RubyGems.
To install the latest official release of the SPARQL
gem, do:
% [sudo] gem install sparql
To get a local working copy of the development repository, do:
% git clone git://github.com/ruby-rdf/sparql.git
- Gregg Kellogg - http://greggkellogg.net/
- Arto Bendiken - http://ar.to/
- Pius Uzamere - http://pius.me/
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.
- Do your best to adhere to the existing coding conventions and idioms.
- Don't use hard tabs, and don't leave trailing whitespace on any line.
- Do document every method you add using YARD annotations. Read the tutorial or just look at the existing code for examples.
- Don't touch the
.gemspec
,VERSION
orAUTHORS
files. If you need to change them, do so on your private branch only. - Do feel free to add yourself to the
CREDITS
file and the corresponding list in the theREADME
. Alphabetical order applies. - Do note that in order for us to merge any non-trivial changes (as a rule of thumb, additions larger than about 15 lines of code), we need an explicit public domain dedication on record from you.
This is free and unencumbered public domain software. For more information, see http://unlicense.org/ or the accompanying {file:UNLICENSE} file.
A copy of the SPARQL EBNF and derived parser files are included in the repository, which are not covered under the UNLICENSE. These files are covered via the W3C Document License.
A copy of the SPARQL 1.0 tests and SPARQL 1.1 tests are also included in the repository, which are not covered under the UNLICENSE; see the references for test copyright information.