View on GitHub


Ruby SPARQL library

Download this project as a .zip file Download this project as a tar.gz file


This is a Ruby implementation of SPARQL for RDF.rb.

Gem Version

Build Status



The {SPARQL} gem implements SPARQL 1.1 Query, and provides Rack and Sinatra middleware to provide results using 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 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.

Updates for RDF 1.1

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.

SPARQL Extension Functions

Extension functions may be defined, which will be invoked during query evaluation. For example:

# Register a function using the IRI <>
crypt_iri = RDF::URI("")
SPARQL::Algebra::Expression.register_extension(crypt_iri) do |literal|
  raise TypeError, "argument must be a literal" unless literal.literal?

Then, use the function in a query:

PREFIX rsp: <>
PREFIX schema: <>
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 plugins 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.)

Remote datasets

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.

Result formats

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'

Querying a repository with a SPARQL query

queryable = RDF::Repository.load("etc/doap.ttl")
sse = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
queryable.query(sse) do |result|

Executing a SPARQL query against a repository

queryable = RDF::Repository.load("etc/doap.ttl")
sse = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
sse.execute(queryable) do |result|

Rendering solutions as JSON, XML, CSV, TSV or HTML

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

Parsing a SPARQL query string to SSE

sse = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
sse.to_sxp #=> (bgp (triple ?s ?p ?o))

Command line processing

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))))"

Adding SPARQL content negotiation to a Rails 3.x application

# config/application.rb
require 'rack/sparql'

class Application < Rails::Application
  config.middleware.use Rack::SPARQL::ContentNegotiation

Adding SPARQL content negotiation to a Rackup application

#!/usr/bin/env rackup
require 'rack/sparql'

repository = do |graph|
  graph << [, RDF::DC.title, "Hello, world!"]
results = SPARQL.execute("SELECT * WHERE { ?s ?p ?o }", repository)

use Rack::SPARQL::ContentNegotiation
run lambda { |env| [200, {}, results] }

Adding SPARQL content negotiation to a classic Sinatra application

# 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 = do |graph|
    graph << [, RDF::DC.title, "Hello, world!"]
  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)
    settings.sparql_options.merge!(:prefixes => {
      :ssd => "",
      :void => ""
    service_description(:repo => repository)

Find more examples in {SPARQL::Grammar} and {SPARQL::Algebra}.


Full documentation available on

Principle Classes



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://

Mailing List



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.


This is free and unencumbered public domain software. For more information, see 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.