You are on page 1of 80

User Guide for Sesame

Updated for Sesame release 1.2.6


Copyright 2002-2006 Aduna B.V., Sirma AI Ltd.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU
Free Documentation License, Version 1.1 or any later version published by the Free Software
Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the
license is included in GNU Free Documentation License.

Table of Contents

Preface: Open, Sesame


1. Introduction: what is Sesame?
1.1. The Sesame library
1.2. The Sesame Server
1.3. Repositories and Inferencing
1.4. An Overview of the Sesame Architecture
2. Installing Sesame
2.1. Library installation
2.2. Server installation
2.2.1. Required software
2.2.2. Installation under Tomcat 4 or 5
2.2.3. Installation under Tomcat 3
2.2.4. Installation under Oracle Container for Java (OC4J)
2.3. Testing Your Installation
2.4. More on the RDBMS
2.4.1. Notes on PostgreSQL
2.4.2. Notes on MySQL
2.4.3. Notes on Oracle
3. Server administration
3.1. Changing the system configuration
3.2. Loading a system configuration
3.3. Storing a system configuration
3.4. Setting the admin password
3.5. Adding and removing user accounts
3.6. Configuring repositories
3.6.1. Editing an existing repository configuration
3.6.2. Adding new repositories
3.6.3. Removing repositories
4. Advanced repository configuration
4.1. Basic setup
4.1.1. The repository id and title
4.1.2. The Sail stack
4.2. Native Sail Indexing
4.3. Custom inferencing
4.3.1. XML syntax
4.3.2. Example

4.3.3. Configuration
4.3.4. Notes and Hints
4.4. Change Tracking
5. The web interface

5.1. Logging in
5.2. Adding data to a repository
6. The SeRQL query language (revision 1.2)
6.1. Revisions
6.1.1. revision 1.1
6.1.2. revision 1.2
6.2. Introduction
6.3. URIs, literals and variables
6.3.1. Variables
6.3.2. URIs
6.3.3. Literals
6.3.4. Blank Nodes (R1.2)
6.4. Path expressions
6.4.1. Basic path expressions
6.4.2. Path expression short cuts
6.4.3. Optional path expressions
6.5. Select- and construct queries
6.6. Select queries
6.7. Construct queries
6.8. The WHERE clause
6.8.1. Boolean constants
6.8.2. Value (in)equality
6.8.3. Numerical comparisons
6.8.4. The LIKE operator (R1.2)
6.8.5. isResource() and isLiteral()
6.8.6. isURI() and isBNode() (R1.2)
6.8.7. AND, OR, NOT
6.8.8. Nested WHERE clauses (R1.2)
6.9. Other functions
6.9.1. label(), lang() and datatype()
6.9.2. namespace() and localName() (R1.2)
6.10. The LIMIT and OFFSET clauses
6.11. The USING NAMESPACE clause
6.12. Built-in predicates
6.13. Set combinatory operations
6.13.1. UNION (R1.2)
6.13.2. INTERSECT (R1.2)
6.13.3. MINUS (R1.2)
6.14. NULL values
6.15. Query Nesting
6.15.1. The IN operator (R1.2)
6.15.2. ANY and ALL (R1.2)
6.15.3. EXISTS (R1.2)
6.16. Example SeRQL queries
6.16.1. Query 1
6.16.2. Query 2
6.16.3. Query 3
6.17. Comments/feedback
6.18. References
6.19. SeRQL grammar

7. The Sesame API

7.1. An Overview of the Sesame Architecture


7.2. The Repository API
7.2.1. Accessing a repository
7.2.2. Querying a repository
7.2.3. Adding RDF data to a repository
7.3. The Graph API
7.3.1. Creating an empty Graph and adding statements to it
7.3.2. Adding/removing a Graph to/from a repository
7.3.3. Creating a Graph for an existing repository
7.3.4. Creating a graph using graph queries
7.3.5. Using graphs and graph queries for updates
8. Communication protocols
8.1. Communicating over HTTP
8.1.1. Logging in
8.1.2. Logging out
8.1.3. Requesting a list of available repositories
8.1.4. Evaluating a SeRQL-select, RQL or RDQL query
8.1.5. Evaluating a SeRQL-construct query
8.1.6. Extracting RDF from a repository
8.1.7. Uploading data to a repository
8.1.8. Adding data from the web to a repository
8.1.9. Clearing a repository
8.1.10. Removing statements
9. Frequently Asked Questions
9.1. General Questions
9.1.1. I've got a Sesame-related question, where can I get an answer?
9.1.2. Something goes wrong when I use Sesame, what do I do?
9.1.3. How do I report a bug?
9.1.4. Why doesn't Sesame support $FEATURE?
9.1.5. I need $FEATURE right now!
9.1.6. Can you keep me informed of any Sesame-related news?
9.1.7. Is this user guide the only documentation for Sesame?
9.2. Troubleshooting
9.2.1. I get a "HTTP error 500" message in the toolbar frame
9.2.2. I get a "HTTP error 500" message in the main frame
9.2.3. I get "error while adding new triples: Invalid byte 2 of 3-byte UTF-8
sequence"
9.2.4. I get a warning: "Unable to set namespace prefix 'foo' for
namespace ..."
9.2.5. My in-memory repository is very slow and/or runs out of memory
9.2.6. On upload I get an error "java.lang.IllegalStateException: Post too
large"
9.2.7. Can not evaluate directSubClassOf on a non-inferencing repository
A. GNU Free Documentation License
A.1. PREAMBLE
A.2. APPLICABILITY AND DEFINITIONS
A.3. VERBATIM COPYING
A.4. COPYING IN QUANTITY
A.5. MODIFICATIONS
A.6. COMBINING DOCUMENTS
A.7. COLLECTIONS OF DOCUMENTS
A.8. AGGREGATION WITH INDEPENDENT WORKS
A.9. TRANSLATION

A.10. TERMINATION
A.11. FUTURE REVISIONS OF THIS LICENSE
A.12. How to use this License for your documents

Preface: Open, Sesame


When they were out of sight Ali Baba came down, and, going up to the rock, said, "Open, Sesame."
The door at once opened, and Ali Baba, entering, found himself in a large cave, lighted from a hole in
the top, and full of all kinds of treasure--rich silks and carpets, gold and silver ware, and great bags of
money. He loaded his three asses with as many of the bags of gold as they could carry; and, after
closing the door by saying, "Shut, Sesame," made his way home.
--Tales of 1001 Nights
In February 2000 the European IST project On-To-Knowledge kicked off. The goal of this project was
to provide tools and a methodology for content-driven knowledge management through evolving
ontologies.
In this project, the Dutch company Aduna (then known as Aidministrator Nederland b.v.) developed
Sesame. Sesame fullfills the role of storage and retrieval middleware for ontologies and metadata
expressed in RDF and RDF Schema. Another tool developed in On-To-Knowledge is OMM, the
Ontology Middleware Module, which was developed by OntoText. OMM is an extension of Sesame
that adds features such as change tracking and improved security.
Currently, Sesame and OMM are being further developed as an open source software product, by
Aduna in cooperation with and partially funded by the NLNet Foundation, and by OntoText. The goal
is to provide a stable, efficient and scalable middleware platform for storing, retrieving, manipulating
and managing ontologies and metadata stored in RDF, RDF Schema and more expressive
languages like OWL.
We aren't there yet, but it's looking good, we hope. This document is here to provide you, the
Sesame user, with helpful information on how to deploy Sesame in various contexts, such as a
database add-on in a client-server setting, or as a Java library to add functionality to stand-alone
applications.
We hope this document will get you started, and of course we hope that you find Sesame easy to use
and, well, good. Being an open source product in development also means that we are very keen on
receiving feedback from our users. If you have questions, comments, if you think something is wrong
with Sesame, or you have a good idea on how to improve it, please let us know. Contact us through
the forums and/or issue tracker that are available on the Sesame website: www.openrdf.org.
We wish to conclude with a big thank you to all of you who have been (and indeed still are)
supportive of this project, in particular Teus Hagen, Wytze van der Raay, Frank van Harmelen, Andy
Seaborne, Peter Mika and Jacco van Ossenbruggen. Special thanks go to Holger Lausen for
providing the Oracle implementation of the RDF Sail.
The Sesame and OMM development teams.

Chapter 1. Introduction: what is Sesame?


Table of Contents
6

1.1. The Sesame library

1.2. The Sesame Server


1.3. Repositories and Inferencing
1.4. An Overview of the Sesame Architecture
Sesame is an open source Java framework for storing, querying and reasoning with RDF and RDF
Schema. It can be used as a database for RDF and RDF Schema, or as a Java library for
applications that need to work with RDF internally. For example, suppose you need to read a big RDF
file, find the relevant information for your application, and use that information. Sesame provides you
with the necessary tools to parse, interpret, query and store all this information, embedded in your
own application if you want, or, if you prefer, in a seperate database or even on a remote server.
More generally: Sesame provides application developers a toolbox that contains useful hammers,
screwdrivers etc. for doing 'Do-It-Yourself' with RDF.
In the next sections, we will take a closer look at Sesame.

1.1. The Sesame library


The Sesame library consists of a set of java archives:

sesame.jar. The Sesame core classes.


rio.jar. Rio (RDF I/O) is a set of parsers

openrdf-model.jar.

openrdf-util.jar.

and writers for different RDF


serialization formats (RDF/XML, Turtle, N-Triples).
Shared interfaces and classes for the RDF model.

Shared utility classes.

These archives (which are located in the lib/ directory) contain Java classes ready for use in your
own application. In Chapter 7, The Sesame API, you can find instructions and examples on how to
use Sesame in your own code: how to do queries, how to add and remove data, etc.

1.2. The Sesame Server


Sesame can be used as a Server with which client applications (or human users) can communicate
over HTTP (see Figure 1.1, Sesame Server). Sesame can be deployed as a Java Servlet
Application in Apache Tomcat, a webserver that supports Java Servlets and JSP technology.
Figure 1.1. Sesame Server

In Chapter 2, Installing Sesame, you will find detailed information on how to install Sesame as a
server.

1.3. Repositories and Inferencing


A central concept in the Sesame framework is the repository. A repository is a storage container for
RDF. This can simply mean a Java object (or set of Java objects) in memory, or it can mean a
relational database. Whatever way of storage is chosen however, it is important to realize that almost
every operation in Sesame happens with respect to a repository: when you add RDF data, you add it
to a repository. When you do a query, you query a particular repository.
Sesame, as mentioned, supports RDF Schema inferencing. This means that given a set of RDF
and/or RDF Schema, Sesame can find the implicit information in the data. Sesame supports this by
simply adding all implicit information to the repository as well when data is being added.
It is important to realize that inferencing in Sesame is associated with the type of repository that you
use. Sesame supports several different types of repositories (see Chapter 4, Advanced repository
configuration for details). Some of these support inferencing, others do not. Whether you want
Sesame to do inferencing for you is a choice that depends very much on your application.

1.4. An Overview of the Sesame Architecture


In Figure 1.2, The Sesame architecture an overview of Sesame's overall architecture is given.
Figure 1.2. The Sesame architecture

Starting at the bottom, the Storage And Inference Layer, or SAIL API, is an internal Sesame API that
abstracts from the storage format used (i.e. whether the data is stored in an RDBMS, in memory, or
in files, for example), and provides reasoning support. SAIL implementations can also be stacked on
top of each other, to provide functionality such as caching or concurrent access handling. Each
Sesame repository has its own SAIL object to represent it.

On top of the SAIL, we find Sesame's functional modules, such as the SeRQL, RQL and RDQL query
engines, the admin module, and RDF export. Access to these functional modules is available through
Sesame's Access APIs, consisting of two seperate parts: the Repository API and the Graph API. The
Repository API provides high-level access to Sesame repositories, such as querying, storing of rdf
files, extracting RDF, etc. The Graph API provides more fine-grained support for RDF manipulation,
such as adding and removing individual statements, and creation of small RDF models directly from
code. The two APIs complement each other in functionality, and are in practice often used together.

The Access APIs provide direct access to Sesame's functional modules, either to a client program
(for example, a desktop application that uses Sesame as a library), or to the next component of
Sesame's architecture, the Sesame server. This is a component that provides HTTP-based access to
Sesame's APIs. Then, on the remote HTTP client side, we again find the access APIs, which can
again be used for communicating with Sesame, this time not as a library, but as a server running on a
remote location.
While each part of the Sesame code is publicly available and extensible, most developers will be
primarily interested in the Access APIs, for communicating with a Sesame RDF model or a Sesame
repository from their application. In Chapter 7, The Sesame API, these APIs are described in more
detail, through several code examples.

Chapter 2. Installing Sesame


Table of Contents
2.1. Library installation
2.2. Server installation
2.2.1. Required software
2.2.2. Installation under Tomcat 4 or 5
2.2.3. Installation under Tomcat 3
2.2.4. Installation under Oracle Container for Java (OC4J)
2.3. Testing Your Installation
2.4. More on the RDBMS
2.4.1. Notes on PostgreSQL
2.4.2. Notes on MySQL
2.4.3. Notes on Oracle
Sesame can deployed in several ways. The two most common scenarios include deployment as a
java library, or deployment as a server. In this chapter, both installation scenarios are explained.

2.1. Library installation


To use Sesame as a library in a java application, one needs the Sesame jar files. These are:

sesame.jar. The Sesame core classes.


rio.jar. Rio (RDF I/O) is a set of parsers

openrdf-model.jar.

openrdf-util.jar.

and writers for different RDF


serialization formats (RDF/XML, Turtle, N-Triples).
Shared interfaces and classes for the RDF model.

Shared utility classes.

These files can be found in the lib directory of the binary download. Simply including them in your
classpath will allow you to use the functionality of Sesame in your own Java application.
Sesame requires Java 2, version 1.4 or newer, to function properly.
If you intend to use client/server communication over HTTP, then you will additionally need the
following third-party libraries:
Jakarta Commons FileUpload, release 1.2.
Jakarta Commons IO, release 1.3.
6

These third-party libraries can be found in the ext/ directory of the source distribution of Sesame,
and are also included in the library directory of the Sesame Web Archive ( sesame.war). More
information about these libraries, including license information, can be found in the file
doc/thirdparty.txt.
For more information on how to use Sesame as a library, see Chapter 7, The Sesame API

2.2. Server installation


2.2.1. Required software
The Sesame server requires the following software:

Sesame itself
A Java servlet container (running Java 2, version 1.4 or newer) for running
the Sesame servlets

Sesame should be able to run on any Java servlet container that supports the Servlet 2.2 and JSP
1.1 specifications, or newer. So far, it has been tested with Tomcat and, in the case of Oracle, with
OC4J. It has also been reported to work without problems on BEA WebLogic 8.1 SP2 and Jetty.
Please post any reports about compatibility with other servlet containers to our forums.
Sesame has several options for storage of RDF data: it can store data in main-memory (optionally
with a dump to file for persistence), it can store data on disk in a dedicated file structure, or it can
store data in a relational database. See section More on the RDBMS for more info about the last
option.

2.2.2. Installation under Tomcat 4 or 5


The following steps describe the easiest procedure to install Sesame on Tomcat 4.x or 5.x. The
described procedure doesn't require any reconfiguration of Tomcat itself, but it might not be the best
option for you. Please see the documentation that came with your copy of Tomcat if you want more
fine-grained control over where and how Sesame should be installed.
1. Install Tomcat. This usually consists of downloading the binary Tomcat
distribution from http://jakarta.apache.org/tomcat and installing it in an
appropriate location on your disk (we will refer to this location as
[TOMCAT_DIR] here). Please see the Tomcat documentation for more
information on how to get it up and running.
2. Go to the web applications directory ([TOMCAT_DIR]/webapps/ by default)
and create a directory 'sesame' there.
3. Extract the sesame.war file (which can be found in the lib directory of the
binary Sesame distribution) to the newly created 'sesame' directory. You can
do this on the command line by changing directories to the new 'sesame'
directory and executing the command jar -xf [PATH/TO/]sesame.war. You
can also use a program like WinZip or unzip to extract the archive. We will
refer to the directory where you have extracted the sesame.war file as
[SESAME_DIR] in the rest of this document.

4. In case you are planning to use a database with Sesame, copy the
appropriate JDBC-driver file(s) to the directory [SESAME_DIR]/WEB-INF/lib/.

5. Copy

the

file

to
of
Sesame, if you are upgrading you will already have a config file, and
copying the example over it will destroy your existing configuration. The
example file contains some repository entries for different Sails and
databases, and one user account. The file may require some modifications
in order to work on your machine. Please check out Server administration if
you want to learn how to do this.
[SESAME_DIR]/WEB-INF/system.conf.example
[SESAME_DIR]/WEB-INF/system.conf. NOTE: only do this for a fresh install

6. (Re)start your Tomcat server and Sesame should now be up and running.
You
can
access
the
Sesame
web
interface
at
http://
[MACHINE_NAME]:8080/sesame.

2.2.3. Installation under Tomcat 3


Installation of Sesame under Tomcat 3 is almost identical to the procedure described above. It
requires one additional step:
1. Perform the steps described in Installation under Tomcat 4 or 5.
2. Copy the file [SESAME_DIR]/WEB-INF/lib/web.xml-2.2 over the existing
web.xml file and (re)start your Tomcat server.

2.2.4. Installation under Oracle Container for Java (OC4J)


Sesame has been tested with OC4J v9.0.3.0. The installed procedure differs from the standard
installation procedure.

Create a directory [OC4J_HOME]/j2ee/home/applications/sesame and


extract the sesame.war file there. We will refer to the directory where you
have installed Sesame as [SESAME_DIR] in the rest of this document.
Add the following line to [OC4J_HOME]/j2ee/home/config/application.xml:
<webmoduleid="sesame"path="../../home/applications/sesame"/>

Add

the

following

line

to

[OC4J_HOME]/j2ee/home/config/http-web-

site.xml:
<webappapplication="default"name="sesame"root="/sesame"/>

2.3. Testing Your Installation


If you have followed the installation instruction described in the previous section, the Sesame server
should now be up-and-running. Pointing a browser to the location where you have installed Sesame
(e.g. http://[MACHINE_NAME]:8080/sesame/ if you have installed Sesame under Tomcat as described
in this document) should now display the Sesame web interface.

You should also test whether the Sesame servlets are running correctly, and whether Sesame can
talk to the RDBMS (if applicable). Select one of the repositories that you have configured and press
'Go>>'. Click on the 'Add (www)' link in the toolbar at the top of the window, and try to upload the
test.rdf
file
from
Sesame's
admin
directory
(e.g.
http://
[MACHINE_NAME]:8080/sesame/admin/test.rdf). You can do this by typing this URL in the first text
field and by clicking on the 'Add data' button after that.

If the data-upload was successful, you should also be able to extract the uploaded data. Click on the
'Extract' link in the toolbar and press the 'Extract' button. This should yield an RDF document
describing all classes and properties in the repository.
Sesame has been successfully installed if all of this works. You can remove or reconfigure the test
user account and repository if you want. If you haven't done so already, you can take a look at the
next chapter for information on how to add and remove user accounts and repositories to/from
Sesame.

2.4. More on the RDBMS


Sesame has an RDBMS-Sail that uses an RDBMS for storing RDF data. Currently, this Sail supports
PostgreSQL, MySQL, Microsoft SQL Server and Oracle databases. The first two RDBMS's are open
source and are freely available on the Internet. Please check the documentation delivered with these
databases for any questions on how to get them installed.
Sesame's RDBMS Sail has been extensively tested in combination with MySQL and PostgreSQL.
The RDBMS Sail used to perform much better in combination with MySQL than with PostgreSQL, but
recent versions of PostgreSQL have shown major performance increases. These two RDBMS's now
have comparable performance, with PostgreSQL having an edge over MySQL where it concerns the
evaluation of complex queries. The SQL Server- and Oracle support are third-party contribution and
we have no comparitive data on their performance.

2.4.1. Notes on PostgreSQL

Recent versions of PostgreSQL are a lot faster than the 7.1 version that
Sesame was originally developed against. The most recents tests have
been done using version 8.1.4. If possibly, you should use the newest
possible (stable) version of PostgreSQL that is available.
JDBC-drivers for PostgreSQL can be found at http://jdbc.postgresql.org, but
these also come bundled with (some of) the PostgreSQL installation
packages.

Make sure that the PostgreSQL server is running with the TCP/IP
connections enabled. If TCP/IP is not enabled, the JDBC-driver will not be
able to talk to the server.

pgAdmin is an excellent tool to administer a PostgreSQL server (for those


who don't mind using GUIs).

The RDBMS Sail will need an (empty) database on the PostgreSQL server,
as well as a user account that has access to (or owns) that database. You
need to create these manually, for example by using the pgAdmin tool
mentioned above. In most cases, the encoding of the new database should
be set to 'UTF8'. The RDBMS Sail will take care of creating the required
tables and indexes when first run. We'll assume that the user account is
called 'sesame' in the rest of this document.

2.4.2. Notes on MySQL


Sesame tries to use the character set features that were introduced in
MySQL 4.1 to properly handle non-ASCII characters. Sesame will
automatically detect whether these features are available and will fall back
to using BLOBs when an older version of MySQL is used. In that case,
6

Sesame will not be able to properly handle non-ASCII characters in literals


and namespace names.
Sesame's RDBMS Sail makes extensive use of the TRUNCATE command.
Unfortunately, this command is mapped to the much slower DELETE
command for InnoDB tables in pre-MySQL 5.0.3 releases. To achieve
reasonable performance one should use MySQL 5.0.3 or newer, or
configure MySQL to use the older MyISAM tables instead of InnoDB tables.

Several people have reported problems with 4.x and early 5.0.x version of
MySQL, especially with versions that came pre-installed with Linux
distributions. So far, all these problems were resolved by installing the most
recent stable version of MySQL and its JDBC-driver. Please try this before
reporting problems when using unstable/beta releases.

MySQL Administrator is an great tool to administer a MySQL server (for


those who don't mind using GUIs).

The RDBMS Sail will need an (empty) database on the MySQL server, as
well as a user account that has access to that database. You need to create
these manually, for example by using the MySQL Administrator tool
mentioned above. In most cases, the encoding of the new database should
be set to 'UTF8'. The RDBMS Sail will take care of creating the required
tables and indexes when first run. We'll assume that the user account is
called 'sesame' in the rest of this document.

2.4.3. Notes on Oracle


Note: We do not have first-hand experience with using the RDBMS Sail on Oracle. The comments
below are based on feedback that we have received from users.

The RDBMS Sail has been tested with Oracle 9i and newer, Oracle 8i does
not work due to lack of support for left (outer) joins. Oracle 9.2.0.1.0 has a
bug affecting ANSI-style left (outer) joins which makes it incompatible with
Sesame. This bug has been fixed in version 9.2.0.4.0.
The
Oracle
JDBC
driver
can
be
found
at
[ORACLE_HOME]/jdbc/lib/classes12.jar or at http://otn.oracle.com/.

You will have to create a user with appropriate rights (resource + connect).

If ORA-0150 (maximum key length (...) exceeded) is raised during creation


of your DB-Schema the reason might be in your DB configuration. You have
got the following options:
o

Increase db_block_size in your init.ora and create a new database to


allow larger index columns (refer to Oracle Note:136158.1).

Edit Oracle.java in package org.openrdf.sesame.sailimpl.rdbms


and alter the size of the Datatype NAME and LABEL. The new size
can be calculated from the error message, e.g.: "ORA-01450
maximum key length (3166) exceeded at varchar(3157)" (length-9 for
block overhead).

Chapter 3. Server administration


6

Table of Contents

3.1. Changing the system configuration


3.2. Loading a system configuration
3.3. Storing a system configuration
3.4. Setting the admin password
3.5. Adding and removing user accounts
3.6. Configuring repositories
3.6.1. Editing an existing repository configuration
3.6.2. Adding new repositories
3.6.3. Removing repositories

3.1. Changing the system configuration


Sesame's configuration is specified in the file [SESAME_DIR]/WEB-INF/system.conf. You can edit this
configuration file locally on your Sesame server using the Configure Sesame! tool available in
[SESAME_DIR]/WEB-INF/bin/. You can start the tool with the command configSesame.bat (on
Windows) or configSesame.sh (on UNIX. Note that in UNIX you may have to give the file executable
permissions first). Alternatively, you can download Configure Sesame! as a standalone tool from the
Sesame project website, and install it on a remote client machine to configure your Sesame server
over HTTP.
It is possible to edit the system configuration manually with an XML or text editor, but we do not
recommend this.

3.2. Loading a system configuration


Figure 3.1. Configure Sesame!

When you have started Configure Sesame! (Figure 3.1, Configure Sesame!), load the file
system.conf. If you want to configure a running Sesame server, you can do this by loading the file
directly from the server (menu option [File]-->[Load from server...], see Figure 3.2, Loading the
configuration from a running server). If the server is not running, you can open the file from disk
(menu option [File]-->[Open file...]).

Figure 3.2. Loading the configuration from a running server

If this is a fresh installation of Sesame, the admin password is still the default password. In this case,
you will need to enter "admin" as the Current admin password to load the configuration. If this is not a
fresh installation of Sesame you will need to enter the admin password that you have specified
earlier.

3.3. Storing a system configuration


When you have modified the configuration, you can store it on disk (menu option [File]-->[Save file
as...]), or you can send it directly to a running Sesame server (menu option [File]-->[Send to
server...], see Figure 3.3, Send a configuration to a running server). Notice that if you use the "Send
to Server" option, the changes to the configuration will be applied to the running server immediately.
You do not need to restart or refresh the server separately.
Figure 3.3. Send a configuration to a running server

3.4. Setting the admin password


If you have not changed the admin password before, it's probably a good idea to set one right now.
To set the admin password, go to the server tab (Figure 3.4, The Server tab) and fill in an admin
password.

Figure 3.4. The Server tab

3.5. Adding and removing user accounts


To add a user account to Sesame, perform the following steps:
1. Open the Tab "Users" (Figure 3.5, The "Users" configuration tab). You see
an overview of currently configured users.
Figure 3.5. The "Users" configuration tab

2. Click the "Add user" icon on the bottom of the window. A new entry is added
to the overview.
3. Enter the credentials for the new user, hitting Enter to go to the next column.

To remove a user account, simply select the user you wish to remove and click the "Remove user"
button in the bottom right of the window.

3.6. Configuring repositories


You can configure existing repositories, add new ones and of course remove repository configuration
using Configure Sesame!.
In this section, we introduce the basic use of Configure Sesame! In Chapter 4, Advanced repository
configuration we go into the details of repository config parameters.

3.6.1. Editing an existing repository configuration


1. Open the "Repositories" tab (Figure 3.6, The "Repository" tab). Select the
repository you wish to configure and click the "Repository details" button on
the bottom left.
Figure 3.6. The "Repository" tab

2. In the Repository details window (Figure 3.7, The "Repository details"


window), you can edit several parameters of your repository. The top part of
the window shows the Sail stack, the bottom part shows the parameters of
the selected Sail in the stack. In most cases, you will only want to edit the
parameters of the bottom sail in the stack (for more information about the
Sail stack and configuration parameter see Chapter 4, Advanced repository
configuration).

Figure 3.7. The "Repository details" window

The Repository details window also allows you to change the access rights of users to a repository.
To change the access rights, click the "Access rights" tab, where you can edit the rights of existing
users or add new users (Figure 3.8, The "access rights" tab). The entry anonymous is a special
entry that represents users who do not log in. Giving this entry access rights means that anybody can
access the repository.
Figure 3.8. The "access rights" tab

3.6.2. Adding new repositories

The easiest way to add a new repository is to "clone" an existing repository. Use the "Clone" button
on the repository tab (Figure 3.6, The "Repository" tab) to do this. This creates a copy of the

currently selected repository configuration, which you can then edit. Take special care to change
details such as the jdbcUrl or file attributes of the Sail (see Chapter 4, Advanced repository
configuration).
Alternatively, you can add a new repository by using the "Add" button and filling in all the information
by yourself.

3.6.3. Removing repositories


To remove a repository, simply open the repository tab (Figure 3.6, The "Repository" tab), select a
repository and click the "Remove" button on the bottom right.

Chapter 4. Advanced repository configuration


Table of Contents
4.1. Basic setup
4.1.1. The repository id and title
4.1.2. The Sail stack
4.2. Native Sail Indexing
4.3. Custom inferencing
4.3.1. XML syntax
4.3.2. Example
4.3.3. Configuration
4.3.4. Notes and Hints
4.4. Change Tracking
When setting up a repository in Sesame, you can make a number of choices: should the repository
support versioning or security, or should it be as fast as possible? What database will it use, or will it
be in-memory?
In this chapter, we look at several of these configuration options in more detail.

4.1. Basic setup


The setup for each Sesame repository is configured using Configure Sesame!. As we have already
seen in Server administration, this configuration tool allows tweaking of numerous parameters, which
we will discuss in more detail here.

4.1.1. The repository id and title


In the repository tab (Figure 3.6, The "Repository" tab), the repository id and title are declared. The
id is how the repository will be known by Sesame: all client access will need to use this identifier.
The title is for human convenience and can be used to give a short description of the repository's
purpose. Clients such as the web interface use it to represent the repository to the end user.

4.1.2. The Sail stack

The most important part of the repository configuration is the sail stack, which can be found in the
"repository details" screen (Figure 3.7, The "Repository details" window). Here, you configure where
the actual repository storage resides, whether or not inferencing, security and versioning, etc. should
be used, and what additional options are needed.

The sail stack is represented top-to-bottom. In the example, we see two sail declarations:
org.openrdf.sesame.sailimpl.sync.SyncRdfSchemaRepository
and
org.openrdf.sesame.sailimpl.rdbms.RdfSchemaRepository. The first sail is stacked on top of the
second one (which means that it operates by calling methods on the Sail underneath it). The second
sail is the base sail: it is the lowest of the stack and does not operate on another sail, but directly on
the actual data source. In this example, the base sail is an RDF Schema-aware driver for a relational
database that supports (currently) MySQL (3.23.47 and higher), PostgreSQL (7.0.2 and higher) and
Oracle 9i.
The SyncRdfSchemaRepository is optional, but we strongly recommend using it. This Sail handles
concurrent access issues, without it Sesame would behave unpredictably when several users access
the repository simultaneously.
Other base sails to choose from include:

org.openrdf.sesame.sailimpl.rdbms.RdfRepository:

an non-inferencing

driver for relational database storage.

org.openrdf.sesame.sailimpl.omm.versioning.VersioningRdbmsSail:

an
inferencing driver for relational database storage that supports change
tracking.

org.openrdf.sesame.sailimpl.memory.RdfRepository:

non-inferencing

driver for storage in main memory.

org.openrdf.sesame.sailimpl.memory.RdfSchemaRepository:

an
inferencing driver for storage in main memory that support RDF and RDF
Schema entailment.

org.openrdf.sesame.sailimpl.nativerdf.NativeRdfRepository:

non-

inferencing driver for storage directly on disk.


All base sails that work on relational databases need a number of parameters to function:

identifies the JDBC (Java Data Base Connectivity) driver that is


to be used to access the database. In the example, com.mysql.jdbc.Driver,
the standard MySQL JDBC driver, is used.
jdbcUrl identifies the location of the database through a URL. The precise
syntax of this URL is DBMS-dependent. An example URl for a MySQL
database would be jdbc:mysql://localhost:3306/testdb. This specifies a
database names testdb on a MySQL server running on localhost, which
uses port 3306 for communication. The last part of the URL identifies the
name of the database (in this case testdb). Note that this is the name of the
database as it is known to the DBMS, and that it is not related to the
Sesame repository id (though it might be convenient to assign them
identical names).
jdbcDriver

identifies a username with which Sesame can access the database.


This must therefore be a user which is known to the DBMS, and which has
been granted access rights (see also Server administration).

user

password

identifies a password with which Sesame can access the


database. This must therefore be a password that matches the username
configured in the user parameter.
6

The RDBMS-based sails also take some optional parameters:

indicates whether the dependency-based truth


maintenance should be used (possible values are 'yes' and 'no', the default
is 'yes'). Dependency-based truth maintenance speeds up removal
operations, but performance of uploads is slowed down.
commitInterval indicates a number of triples to be added before the sail
does an in-between commit during upload of large datasets. The default is
'1000'. This figure can be tweaked to improve upload performance.
dependency-inferencing

The memory-based sails take four optional parameters:

specifies a file in which the in-memory repository stores its contents on


local disk. This file is automatically saved and reloaded on (re)start of the
server.
dataFormat specifies the format of the data in the file. Legal values are
'rdfxml' (the default), 'ntriples' and 'turtle'.
file

specifies whether the file used for storage should be


compressed with gzip.

compressFile

syncDelay

specifies the time (in milliseconds) to wait after a transaction was


commited before writing the changed data to file. Setting this variable to '0'
(the default value) will force a file sync immediately after each commit. A
negative value will deactivate file synchronization until the Sail is shut down.
A positive value will postpone the synchronization for at least that amount of
milliseconds. If in the meantime a new transaction is started, the file
synchronization will be rescheduled to wait for another syncDelay ms. This
way, bursts of transaction events can be combined in one file sync,
improving performance.

The native sail has one required parameter:

specifies the directory that can be used by the native sail to store its
files.
dir

The native sail also has an optional triple-indexes parameter, with which one can specify the
indexing strategy the native sail should take. We will explain this in more detail in the next section.

4.2. Native Sail Indexing


The native store uses B-Trees for indexing statements, where the index key consists of three fields:
subject (s), predicate (p) and object (o). The order in which each of these fields is used in the key
determines the usability of an index on a specify triple query pattern: searching triples with a specific
subject in an index that has the subject as the first field is signifantly faster than searching these
same triples in an index where the subject field is second or third. In the worst case, the 'wrong' triple
pattern will result in a sequential scan over the entire set of triples.
By default, the native store only uses a single index, with a subject-predicate-object key pattern.
However, it is possible to define different indexes for the native store, using the triple-indexes
parameter. This can be used to optimize performance for query patterns that occur frequently.

The subject-, predicate- and object fields are represented by the characters 's', 'p' and 'o',
respectively. Indexes can be specified by creating 3-letter words from these three characters. Multiple
indexes can be specified by separating these words with comma's, spaces and/or tabs. For example,

the string "spo, pos" specifies two indexes; a subject-predicate-object index and a predicate-objectsubject index.
Of course, creating multiple indexes speeds up querying, but there is a cost factor to take into
account as well: adding and removing data will become more expensive, because each index will
have to be updated. Also, each index takes up additional disk space.
The native store automatically creates/drops indexes upon (re)initialization, so the parameter can be
adjusted and upon the first refresh of the configuration the native store will change its indexing
strategy, without loss of data.

4.3. Custom inferencing


The basic set of RDFS inference rules (as defined in the RDF(S) MT semantics) sometimes can be
insufficient to build custom applications. For example, in some applications there is a need for
defining one's own transitive, symmetric or inverse properties. Providing an infrastructure to define
such custom inference rules helps developers to tune the Sesame inferencer so it can suit better in
the application.
Since

Sesame

release

0.95,

we

provide

an

alternative inferencer that works with


SAIL. This custom inferencer can be
initialized with a set of axiomatic triples and inference rules defined in an external file. The format of
these definitions is very simple and intuitive and it is explained in greater detail in the next section.
org.openrdf.sesame.sailimpl.rdbms.RdfSchemaRepository

Support for inter-rule dependency is also added to the customizable inferencer. Now we can state
explicitly which rules are triggered if a rule infers a new statement. This information is given within an
additional tag within the 'rule' one - 'triggers_rule'. It consists of several 'rule' tags with a name
attribute specifying the rules affected.

4.3.1. XML syntax


The definition file is in XML and should conform to the following DTD:
<!DOCTYPEInferenceRules[
<!ENTITYrdf'http://www.w3.org/1999/02/22rdfsyntaxns#'>
<!ENTITYrdfs'http://www.w3.org/2000/01/rdfschema#'>
<!ENTITYdaml'http://www.daml.org/2001/03/daml+oil#'>
<!ELEMENTInferenceRules(axiom|rule)*>
<!ELEMENTaxiom(subject,predicate,object)>
<!ELEMENTrule((premise+,consequent,triggers_rule?)|EMPTY)>
<!ATTLISTrule
nameCDATA#REQUIRED>
<!ELEMENTpremise(subject,predicate,object)>
<!ELEMENTconsequent(subject,predicate,object)>
<!ELEMENTtriggers_rule(rule)*>

<!ELEMENTsubjectEMPTY>
<!ATTLISTsubject
varCDATA#IMPLIED
uriCDATA#IMPLIED
patternCDATA#IMPLIED
escapeCDATA#IMPLIED
type(resource)#IMPLIED>

<!ELEMENTpredicateEMPTY>
<!ATTLISTpredicate
varCDATA#IMPLIED
uriCDATA#IMPLIED
patternCDATA#IMPLIED
escapeCDATA#IMPLIED
type(resource)#IMPLIED>
<!ELEMENTobjectEMPTY>
<!ATTLISTobject
varCDATA#IMPLIED
uriCDATA#IMPLIED
patternCDATA#IMPLIED
escapeCDATA#IMPLIED
type(resource)#IMPLIED>
]>

If a 'uri' attribute is present within the 'subject', 'predicate' or 'object' tags, its value is assumed to be a
name of a resource.
The value of the 'var' attribute of the above tags gives the name of that variable. This attribute cannot
be used within an 'axiom' tag.
For example, here are two of the axiomatic triples, as they are defined in the RDF(S) MT semantics.
They appear in the configuration file like this:
<axiom>
<subjecturi="&rdfs;subPropertyOf"/>
<predicateuri="&rdfs;domain"/>
<objecturi="&rdf;Property"/>
</axiom>
<axiom>
<subjecturi="&rdfs;subPropertyOf"/>
<predicateuri="&rdfs;range"/>
<objecturi="&rdf;Property"/>
</axiom>

An example of an inference rule (one stating that - if a resource is used as predicate then it is of 'type'
'Property') looks like:
<rulename="rdfs1">
<premise>
<subjectvar="xxx"/>
<predicatevar="aaa"/>
<objectvar="yyy"/>
</premise>
<consequent>
<subjectvar="aaa"/>
<predicateuri="&rdf;type"/>
<objecturi="&rdf;Property"/>
</consequent>

<triggers_rule>
<rulename="rdfs2"/>
<rulename="rdfs3"/>
<rulename="rdfs4a"/>
<rulename="rdfs5b"/>
<rulename="rdfs6"/>
<rulename="rdfs9"/>
</triggers_rule>
</rule>

In the above example 'xxx', 'aaa' and 'yyy' are variables and 'rdf:type' and 'rdf:Property' are exact
resource URIs.
A 'pattern' attribute with conjunction with an 'escape' attribute is used to define a pattern for matching
resource names. They both can appear only in a triple component denoting variables, e.g. with 'var'
attribute specified. Use '?' to denote any single character and '*' to match any character combination
with length greater than 0.
Use a character declared in 'escape' attribute to escape '?' or '*' characters within pattern. You need
to specify 'pattern' and 'escape' attributes for a given variable only once per rule (note that pattern
and escape are used only once for variable 'id'.
An example of rule using pattern matching:
<rulename="rdfsXI">
<premise>
<subjectvar="xxx"/>
<predicatevar="id"pattern="&rdf;_*"escape="\"/>
<objectvar="yyy"/>
</premise>
<consequent>
<subjectvar="id"/>
<predicateuri="&rdf;type"/>
<objecturi="&rdfs;ContainerMembershipProperty"/>
</consequent>
<triggers_rule>
<rulename="rdfs2"/>
<rulename="rdfs3"/>
<rulename="rdfs6"/>
<rulename="rdfs9"/>
<rulename="rdfs10"/>
</triggers_rule>
</rule>

Note that you can match these triple templates by the values to the variables used in them and the
specified resources used as subjects, predicates or objects of a triple.

4.3.2. Example
Consider the property URI is http://somewhere.org#partOf. In our example domain, we wish to
ensure that this resource is always inserted in the repository, so we add the axiomatic triple stating
that it is a property:
<axiom>
<subjecturi="http://somewhere.org#partOf"/>
<predicateuri="&rdf;type"/>
<objecturi="&rdf;Property"/>
</axiom>

<rulename="userPartOf">
<premise>
<subjectvar="xxx"/>
<predicateuri="http://somewhere.org#partOf"/>
<objectvar="yyy"/>
</premise>
<premise>

We also wish to define that the property is transitive. To this end, we add a single inference rule:

<subjectvar="yyy"/>
<predicateuri="http://somewhere.org#partOf"/>
<objectvar="zzz"/>
</premise>
<consequent>
<subjectvar="xxx"/>
<predicateuri="http://somewhere.org#partOf"/>
<objectvar="zzz"/>
</consequent>
<triggers_rule>
<rulename="rdfs2"/>
<rulename="rdfs3"/>
<rulename="rdfs6"/>
<rulename="userPartOf"/>
</triggers_rule>
</rule>

If the repository has these two triples: T1 - (finger.1, partOf, Hand.Left) and T2 - (Hand.Left, partOf,
Human.1) and if they match the condition (since the same 'yyy' variable is used in both 'premise'
tags) T1.object = T2.subject, a triple corresponding to the 'consequent' tag is added to the repository,
using the current variable bindings and will have the form TInfer = (T1.subject, partOf, T2.object) e.g.
Tinfer=(Finger.1, partOf, Human.1).

4.3.3. Configuration
The

inferencer

repository
based
on
org.openrdf.sesame.sailimpl.rdbms.RdfSchemaRepository sail is defined by a parameter passed to
it during the initialization. To start using the custom inferencer on a repository, add the following extra
parameter to the configuration of that repository:

used

by

specifies the full classname of the inferencer. To use the


inferencer,
use
the
value
org.openrdf.sesame.sailimpl.rdbms.CustomInferenceServices.
rule-file specifies the location of the XML file in which the inference rules
for the custom inferencer are specified. Make sure that you specify the full
path name.
use-inferencer

custom

4.3.4. Notes and Hints


An example rules file, containing the axioms and entailment rules as specified by the January 23
Working Draft of the RDF Model Theory, can be found in the Sesame source tree, specifically in
src/org/openrdf/sesame/sailimpl/rdbms/entailment-rdf-mt-20030123.xml. This file is used per
default by the custom inferencer if the rule-file parameter is not specified.
Changes to the rules file do not lead to automatic reapplication of the rules over the existing data in
the repository. So clean the repository first to avoid inconsistency problems.

The dependency information used by the TMS system is also affected by the rules. The default
inferencer uses dependency database table, that can handle cases where up to two triples leads to
the inference of a new one. Since there can exist inference rules involving arbitrary number of
'premise' tags in the configuration file - the structure of the default dependency table cannot handle
them. To avoid loss of data, the structure of that table is not altered and it is created only if it not exist.
This check is performed during repository initialization phase. So it is better to apply new/modified
inference rules on a completely clean datastorage (database).

4.4. Change Tracking


[This section not yet available. See the documentation at http://www.ontotext.com/omm/ for details.]

Chapter 5. The web interface


Table of Contents
5.1. Logging in
5.2. Adding data to a repository
Sesame comes with a Web interface to allow access to repositories through a normal Web browser.
In this chapter, we will briefly describe the user interface.

5.1. Logging in
If you installed Sesame according to the guidelines in Chapter 2, Installing Sesame, the Sesame
entry page is located at http://[MACHINE_NAME]:8080/sesame/. If you point your browser to this
address, it should display the Sesame entry page shown in Figure 5.1, The Sesame entry page.
Figure 5.1. The Sesame entry page

The screen provides you with a choice of repositories to work on. Since you are not yet logged in,
and no publicly accessible repositories are available, you get a notification that no repositories can be
accessed.

Figure 5.2. The Sesame login page

To log in to Sesame, click the "log in" link and provide user name and password (see Figure 5.2, The
Sesame login page).

After you have logged in, you are returned to the entry page, which now shows that you are logged in
and gives you a choice of repositories that you have access on.
Figure 5.3. The Sesame entry page when logged in

Figure 5.4. The repository function screen

After selecting a repository, you come to the actual Sesame function interface (see Figure 5.4, The
repository function screen).

The toolbar at the top of the screen shows user and repository information, and allows the selection
of different actions on the repository. The actions are divided in read actions (such as queries) and
write actions (adding and removing data).

5.2. Adding data to a repository


The web interface offers three options for adding data to a Sesame repository: Add file, Add (www)
and Add (copy-paste).
The Add file and Add (www) options are fairly straightforward. The first option allows you to select an
RDF document from your local disk to add to the Sesame repository. The second option allows you to
add RDF documents that are accessible through a URL to the repository.
Optionally, you can supply a base URL. The base URL is used by the RDF parser to disambiguate
any relative resource references in the RDF document. By default, Sesame uses foo:bar as a base
URL, but this may not always be desirable, for example when the file is being from a temporary
location, or when resources defined in the document are referenced by other RDF sources with
different URLs.
The Add (copy-paste) option allows you to upload data to Sesame by typing (or copying and pasting)
it in the text area. The pasted text should be valid RDF/XML document.

Chapter 6. The SeRQL query language (revision 1.2)


Table of Contents
6.1. Revisions
6.2. Introduction
6.3. URIs, literals and variables
6.3.1. Variables

6.1.1. revision 1.1


6.1.2. revision 1.2

6.3.2. URIs
6.3.3. Literals
6.3.4. Blank Nodes (R1.2)
6.4. Path expressions
6.4.1. Basic path expressions
6.4.2. Path expression short cuts
6.4.3. Optional path expressions
6.5. Select- and construct queries
6.6. Select queries
6.7. Construct queries
6.8. The WHERE clause
6.8.1. Boolean constants
6.8.2. Value (in)equality
6.8.3. Numerical comparisons
6.8.4. The LIKE operator (R1.2)
6.8.5. isResource() and isLiteral()
6.8.6. isURI() and isBNode() (R1.2)
6.8.7. AND, OR, NOT
6.8.8. Nested WHERE clauses (R1.2)
6.9. Other functions
6.9.1. label(), lang() and datatype()
6.9.2. namespace() and localName() (R1.2)
6.10. The LIMIT and OFFSET clauses
6.11. The USING NAMESPACE clause
6.12. Built-in predicates
6.13. Set combinatory operations
6.13.1. UNION (R1.2)
6.13.2. INTERSECT (R1.2)
6.13.3. MINUS (R1.2)
6.14. NULL values
6.15. Query Nesting
6.15.1. The IN operator (R1.2)
6.15.2. ANY and ALL (R1.2)
6.15.3. EXISTS (R1.2)
6.16. Example SeRQL queries
6.16.1. Query 1
6.16.2. Query 2
6.16.3. Query 3
6.17. Comments/feedback
6.18. References
6.19. SeRQL grammar

6.1. Revisions
6.1.1. revision 1.1
SeRQL revision 1.1 is a syntax revision (see issue tracker item SES-75). This document describes
the revised syntax. From Sesame release 1.2-RC1 onwards, the old syntax is no longer supported.

6.1.2. revision 1.2


SeRQL revision 1.2 covers a set of new functions and operators:
Specification of blank node identifiers (Section 6.3.4, Blank Nodes (R1.2)).

Case sensitive string matching (Section 6.8.4, The LIKE operator (R1.2)).

New functions isBNode(), isURI() (Section 6.8.6, isURI() and isBNode()


(R1.2)).

Nested WHERE clause for optional path expressions (Section 6.8.8,


Nested WHERE clauses (R1.2)).

New functions namespace(), localName() (Section 6.9.2, namespace() and


localName() (R1.2)).

OWL default namespace (Section 6.11, The USING NAMESPACE clause).

Set operations (Section 6.13, Set combinatory operations).

Nested queries (Section 6.15, Query Nesting).

Set membership operator (Section 6.15.1, The IN operator (R1.2)).

ANY and ALL keywords (Section 6.15.2, ANY and ALL (R1.2)).

Existential quantification (Section 6.15.3, EXISTS (R1.2)).

New operations have been marked with (R1.2) where appropriate in this document.

6.2. Introduction
SeRQL ("Sesame RDF Query Language", pronounced "circle") is a new RDF/RDFS query language
that is currently being developed by Aduna as part of Sesame. It combines the best features of other
(query) languages (RQL, RDQL, N-Triples, N3) and adds some of its own. This document briefly
shows all of these features. After reading through this document one should be able to write SeRQL
queries.
Some of SeRQL's most important features are:

Graph transformation.
RDF Schema support.

XML Schema datatype support.

Expressive path expression syntax.

Optional path matching.

6.3. URIs, literals and variables


URIs and literals are the basic building blocks of RDF. For a query language like SeRQL, variables
are added to this list. The following sections will show how to write these down in SeRQL.

6.3.1. Variables

Var1

Variables are identified by names. These names must start with a letter or an underscore ('_') and
can be followed by zero or more letters, numbers, underscores, dashes ('-') or dots ('.'). Examples
variable names are:

_var2

unwise.var-name_isnt-it

SeRQL keywords are not allowed to be used as variable names. Currently, the following keywords
are used or reserved for future use in SeRQL: select, construct, from, where, using, namespace, true,
false, not, and, or, like, label, lang, datatype, null, isresource, isliteral, sort, in, union, intersect, minus,
exists, forall, distinct, limit, offset.
Keywords in SeRQL are all case-insensitive, this in contrast to variable names; these are casesensitive.

6.3.2. URIs
There are two ways to write down URIs in SeRQL: either as full URIs or as abbreviated URIs. Full
URIs must be surrounded with "<" and ">". Examples of this are:

<http://www.openrdf.org/index.html>
<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>

<mailto:sesame@openrdf.org>

<file:///C:\rdffiles\test.rdf>

As URIs tend to be long strings with the first part being shared by several of them (i.e. the
namespace), SeRQL allows one to use abbreviated URIs (or QNames) by defining (short) names for
these namespaces which are called "prefixes". A QName always starts with one of the defined
prefixes and a colon (":"). After this colon, the part of the URI that is not part of the namespace
follows. The first part, consisting of the prefix and the colon, is replaced by the full namespace by the
query engine. Some example QNames are:

sesame:index.html
rdf:type

foaf:Person

6.3.3. Literals
RDF literals consist of three parts: a label, a language tag, and a datatype. The language tag and the
datatype are optional and at most one of these two can accompany a label (a literal can not have
both a language tag and a datatype). The notation of literals in SeRQL has been modelled after their
notation in N-Triples; literals start with the label, which is surrounded by double quotes, optionally
followed by a language tag with a "@" prefix or by a datatype URI with a "^^" prefix. Example literals
are:

"foo"
"foo"@en

"<foo/>"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral>

"<foo/>"^^rdf:XMLLiteral

The SeRQL notation for abbreviated URIs can also be used. When the prefix rdf is mapped to the
namespace http://www.w3.org/1999/02/22-rdf-syntax-ns#, the last example literal could also have
been written down like:

SeRQL has also adopted the character escapes from N-Triples; special characters can be escaped
by prefixing them with a backslash. One of the special characters is the double quote. Normally, a
double quote would signal the end of a literal's label. If the double quote is part of the label, it needs
to be escaped. For example, the sentence John said: "Hi!" can be encoded in a SeRQL literals as:
"John said: \"Hi!\"".
As the backslash is a special character itself, it also needs to be escaped. To encode a single
backslash in a literal's label, two backslashes need to be written in the label. For example, a Windows
directory would be encoded as: "C:\\Program Files\\Apache Tomcat\\".
SeRQL has functions for extracting each of the three parts of a literal. These functions are label, lang,
and datatype. label("foo"@en) extracts the label "foo", lang("foo"@en) extracts the language tag "en",
and datatype("foo"^^rdf:XMLLiteral) extracts the datatype rdf:XMLLiteral. The use of these functions
is explained later.

6.3.4. Blank Nodes (R1.2)


RDF has a notion of blank nodes. These are nodes in the RDF graph that are not labeled with a URI
or a literal. The interpretation of such blank nodes is as a form of existential quantification: it allows
one to assert that "there exists a node such that..." without specifying what that particular node is.
Blank nodes do in fact often have identifiers, but these identifiers are assigned internally by whatever
processor is processing the graph and they are only valid in the local context, not as global identifiers
(unlike URIs).
Strictly speaking blank nodes are only addressable indirectly, by querying for one or more properties
of the node. However, SeRQL, as a practical shortcut, allows blank node identifiers to be used in
queries. The syntax for blank nodes is adopted from N-Triples, using a QName-like syntax with "_" as
the namespace prefix, and the internal blank node identifier as the local name. For example:

_:bnode1

This identifies the blank node with internal identifier "bnode1". These blank node identifiers can be
used in the same way that normal URIs or QNames can be used.
Caution: It is important to realize that addressing blank nodes in this way makes SeRQL queries nonportable across repositories. There is no guarantee that in two repositories, even if they contain
identical datasets, the blank node identifiers will be identical. It may well be that "bnode1" in
repository A is a completely different blank node than "bnode1" in repository B. Even in the same
repository, it is not guaranteed that blank node identifiers are stable over updates: if certain
statements are added to or removed from a repository, it is not guaranteed "bnode1" still identifies the
same blank node that it did before the update operation.

6.4. Path expressions


One of the most prominent parts of SeRQL are path expressions. Path expressions are expressions
that match specific paths through an RDF graph. Most current RDF query languages allow you to
define path expressions of length 1, which can be used to find (combinations of) triples in an RDF
graph. SeRQL, like RQL, allows you to define path expressions of arbitrary length.

6.4.1. Basic path expressions

Imagine that we want to query an RDF graph for persons who work for companies that are IT
companies. Querying for this information comes down to finding the following pattern in the RDF
graph (gray nodes denote variables):
Figure 6.1. A basic path expression

The SeRQL notation for path expressions resembles the picture above; it is written down as:
{Person}ex:worksFor{Company}rdf:type{ex:ITCompany}

The parts surrounded by curly brackets represent the nodes in the RDF graph, the parts between
these nodes represent the edges in the graph. The direction of the arcs (properties) in SeRQL path
expressions is always from left to right.
In SeRQL queries, multiple path expressions can be specified by seperating them with commas. For
example, the path expression show before can also be written down as two smaller path expressions:
{Person}ex:worksFor{Company},
{Company}rdf:type{ex:ITCompany}

The nodes and edges in the path expressions can be variables, URIs and literals. Also, a node can
be left empty in case one is not interested in the value of that node. Here are some more example
path expressions to illustrate this:

{Person} ex:worksFor {} rdf:type {ex:ITCompany}


{Painting} ex:painted_by {} ex:name {"Picasso"}

{comic:RoadRunner} SomeRelation {foo:WillyECoyote}

6.4.2. Path expression short cuts


Each and every path can be constructed using a set of basic path expressions. Sometimes, however,
it is nicer to use one of the available short cuts. There are three types of short cuts, all of them are
explained below.
6.4.2.1. Multi-value nodes
In situations where one wants to query for two or more triples with identical subject and predicate, the
subject and predicate do not have to be repeated over and over again. Instead, a multi-value node
can be used:
{subj1}pred1{obj1,obj2,obj3}

A built-in constraint on this construction is that each value for the variables in the multi-value node is
unique (i.e. they are pairwise disjoint). Therefore, this path expression is equivalent to the following
combination of path expressions and boolean constraints:

FROM
{subj1}pred1{obj1},
{subj1}pred1{obj2},
{subj1}pred1{obj3}
WHEREobj1!=obj2ANDobj1!=obj3ANDobj2!=obj3

Or graphically:
Figure 6.2. Multi-value nodes

Multi-value nodes can also be used when statements share the predicate and object, e.g.:
{subj1,subj2,subj3}pred1{obj1}

When used in a longer path expression, multi-value nodes apply to both the part left of the node and
the part right of the node. The following path expression:
{first}pred1{middle1,middle2}pred2{last}

matches the following graph:


Figure 6.3. Multi-value nodes in a longer path expression

When using variables in multi-value nodes, a constraint on its values is implicitly added: the variable's
value is not allowed to be equal to any other value in the multi-value node. So, in the first example,
the variables obj1, obj2 and obj3 will not match identical values at the same time. This prevents the
path from matching a single triple three times.
6.4.2.2. Branches
One of the shorts cuts that is likely going to be used most, is the notation for branches in path
expressions. There are lots of situations where one wants to query multiple properties of a single
subject. Instead of repeating the subject over and over again, one can use a semi-colon to attach a
predicate-object combination to the subject of the last part of a path expression, e.g.:
{subj1}pred1{obj1};
pred2{obj2}

Which is equivalent to:


{subj1}pred1{obj1},
{subj1}pred2{obj2}

Or graphically:

Figure 6.4. Branches in a path expression

Or a slightly more complicated example:


{first}pred{}pred1{obj1};
pred2{obj2}pred3{obj3}

Which matches the following graph:


Figure 6.5. Branches in a longer path expression

Note that an anonymous variable is used in the middle of the path expressions.
6.4.2.3. Reified statements
The last short cut is a short cut for reified statements. A path expression representing a single
statement (i.e. {node} edge {node}) can be written between the curly brackets of a node, e.g.:
{{reifSubj}reifPred{reifObj}}pred{obj}

This would be equivalent to querying (using "rdf:" as a prefix for the RDF namespace, and
"_Statement" as a variable for storing the statement's URI):
{_Statement}rdf:type{rdf:Statement},
{_Statement}rdf:subject{reifSubj},
{_Statement}rdf:predicate{reifPred},
{_Statement}rdf:object{reifObj},
{_Statement}pred{obj}

Again, graphically:
Figure 6.6. A reification path expression

6.4.3. Optional path expressions

Optional path expressions differ from 'normal' path expressions in that they do not have to be
matched to find query results. The SeRQL query engine will try to find paths in the RDF graph

matching the path expression, but when it cannot find any paths it will skip the expression and leave
any variables in it uninstantiated (they will have the value null).
Consider an RDF graph that contains information about people that have names, ages, and
optionally e-mail addresses. This is a situation that is likely to be very common in RDF data. A logical
query on this data is a query that yields all names, ages and, when available, e-mail addresses of
people, e.g.:
{Person}ex:name{Name};
ex:age{Age};
ex:email{EmailAddress}

However, using normal path expressions like in the query above, people without e-mail address will
not be returned by the SeRQL query engine. With optional path expressions, one can indicate that a
specific (part of a) path expression is optional. This is done using square brackets, i.e.:
{Person}ex:name{Name};
ex:age{Age};
[ex:email{EmailAddress}]

Or alternatively:
{Person}ex:name{Name};
ex:age{Age},
[{Person}ex:email{EmailAddress}]

In contrast to the first path expressions, this expression will also match with people without an e-mail
address. For these people, the variable EmailAddress will not be assigned a value.
Optional path expressions can also be nested. This is useful in situations where the existence of a
specific path is dependent on the existence of another path. For example, the following path
expression queries for the titles of all known documents and, if the author of the document is known,
the name of the author (if it is known) and his e-mail address (if it is known):
{Document}ex:title{Title};
[ex:author{Author}[ex:name{Name}];
[ex:email{Email}]]

With this path expression, the SeRQL query engine will not try to find the name and e-mail address of
an author when it cannot even find the resource representing the author.

6.5. Select- and construct queries


The SeRQL query language supports two querying concepts. The first one can be characterized as
returning a table of values, or a set of variable-value bindings. The second one returns a true RDF
graph, which can be a subgraph of the graph being queried, or a graph containing information that is
derived from it. The first type of queries are called "select queries", the second type of queries are
called "construct queries".

A SeRQL query is typically built up from one to six clauses. For select queries these clauses are:
SELECT, FROM, WHERE, LIMIT, OFFSET and USING NAMESPACE. One might recognize the first
five clauses from SQL, but their usage is slightly different. For construct queries the clauses are the
same with the exception of the first; construct queries start with a CONSTRUCT clause instead of a
SELECT clause.

The first clause (i.e. SELECT or CONSTRUCT) determines what is done with the results that are
found. In a SELECT clause, one can specify which variable values should be returned and in what
order. In a CONSTRUCT clause, one can specify which triples should be returned.
The FROM clause is optional and always contains path expressions, which were explained in the
previous section. It defines the paths in an RDF graph that are relevant to the query. Note that when
the FROM clause is not specified, the query will simply return the constants specified in the SELECT
or CONSTRUCT clause.
The WHERE clause is optional and can contain additional (Boolean) constraints on the values in the
path expressions. These are constraints on the nodes and edges of the paths, which cannot be
expressed in the path expressions themselves.
The LIMIT and OFFSET clauses are also optional. These clauses can be used separately or
combined in order to get a subset of all query answers. Their usage is very similar to the LIMIT and
OFFSET clauses in SQL queries. The LIMIT clause determines the (maximum) amount of query
answers that will be returned. The OFFSET clause determines which query answer will be returned
as the first result, skipping as many query results as specified in this clause.
Finally, the USING NAMESPACE clause is also optional and it can contain namespace declarations;
these are the mappings from prefixes to namespaces that were referred to in one of previous
sections about (abbreviated) URIs.
The WHERE, LIMIT, OFFSET and USING NAMESPACE clauses will be explained in one of the next
sections. The following section will explain the SELECT and FROM clause.

6.6. Select queries


As said before, select queries return tables of values, or sets of variable-value bindings. Which
values are returned can be specified in the select clause. One can specify variables and/or values in
the select clause, seperated by commas. The following example query returns all URIs of classes:
SELECTC
FROM{C}rdf:type{rdfs:Class}

It is also possible to use a '*' in the SELECT clause. In that case, all variable values will be returned
in the order in which they appear in the query, e.g.:
SELECT*
FROM{S}rdfs:label{O}

This query will return the values of the variables S and O, in that order. If a different order is
preferred, one needs to specify the variables in the select clause, e.g.:
SELECTO,S
FROM{S}rdfs:label{O}

SELECTDISTINCT*
FROM{Country1}ex:borders{}ex:borders{Country2}

By default, the results of a select query are not filtered for duplicate rows. Because of the nature of
the above queries, these queries will never return duplicates. However, more complex queries might
result in duplicate result rows. These duplicates can be filtered out by the SeRQL query engine. To
enable this functionality, one needs to specify the DISTINCT keyword after the select keyword. For
example:

USINGNAMESPACE
ex=<http://example.org/things#>

6.7. Construct queries


Construct queries return RDF graphs as set of triples. The triples that a query should return can be
specified in the construct clause using the previously explained path expressions. The following is an
example construct query:
CONSTRUCT{Parent}ex:hasChild{Child}
FROM{Child}ex:hasParent{Parent}
USINGNAMESPACE
ex=<http://example.org/things#>

This query defines the inverse of the property foo:hasParent to be foo:hasChild. This is just one
example of a query that produces information that is derived from the original information. Here is
one more example:
CONSTRUCT
{Artist}rdf:type{ex:Painter};
ex:hasPainted{Painting}
FROM
{Artist}rdf:type{ex:Artist};
ex:hasCreated{Painting}rdf:type{ex:Painting}
USINGNAMESPACE
ex=<http://example.org/things#>

This query derives that an artist who has created a painting, is a painter. The relation between the
painter and the painting is modelled to be art:hasPainted.
Instead of specifying a path expression in the CONSTRUCT clause, one can also use a '*'. In that
case, the CONSTRUCT clause is identical to the FROM clause. This allows one to extract a
subgraph from a larger graph, e.g.:
CONSTRUCT*
FROM{SUB}rdfs:subClassOf{SUPER}

This query extracts all rdfs:subClassOf relations from an RDF graph.


Just like with select queries, the results of a construct query are not filtered for duplicate triples by
default. Again, these duplicates are filtered out by the SeRQL query engine if the DISTINCT keyword
is specified after the construct keyword, for example:
CONSTRUCTDISTINCT
{Artist}rdf:type{ex:Painter}
FROM
{Artist}rdf:type{ex:Artist};
ex:hasCreated{}rdf:type{ex:Painting}
USINGNAMESPACE
ex=<http://example.org/things#>

6.8. The WHERE clause

The third clause in a query is the WHERE clause. This is an optional clause in which one can specify
Boolean constraints on variables.

The following sections will explain the available Boolean expressions for use in the WHERE clause.
Section 6.8.8, Nested WHERE clauses (R1.2) will explain how WHERE clauses can be nested
inside optional path expressions.

6.8.1. Boolean constants


There are two Boolean constants, TRUE and FALSE. The first one is simply always true, the last one
is always false. The following query will never produce any results because the constraint in the
where clause will never evaluate to true:
SELECT*
FROM{X}Y{Z}
WHEREFALSE

6.8.2. Value (in)equality


The most common boolean constraint is equality or inequality of values. Values can be compared
using the operators "=" (equality) and "!=" (inequality). The expression
Var=<foo:bar>

is true if the variable Var contains the URI <foo:bar>, and the expression
Var1!=Var2

checks whether two variables are not equal.

6.8.3. Numerical comparisons


Numbers can be compared to each other using the operators "<" (lower than), "<=" (lower than or
equal to), ">" (greater than) and ">=" (greater than or equal to). SeRQL uses a literal's datatype to
determine whether its value is numerical. All XML Schema built-in numerical datatypes are supported,
i.e.: xsd:float, xsd:double, xsd:decimal and all subtypes of xsd:decimal (xsd:long,
xsd:nonPositiveInteger, xsd:byte, etc.), where the prefix xsd is used to reference the XML Schema
namespace.
In the following query, a comparison between values of type xsd:positiveInteger is used to retrieve all
countries that have a population of less than 1 million:
SELECTCountry
FROM{Country}ex:population{Population}
WHEREPopulation<"1000000"^^xsd:positiveInteger
USINGNAMESPACE
ex=<http://example.org/things#>

SeRQL is currently restricted to numerical comparisons between values with identical datatypes. This
means that e.g. xsd:int values cannot (yet) be compared to xsd:byte values.
If only one of the parameters of a comparison has a datatype, SeRQL will try to assign the other
parameter the same datatype. This means that the above query can still be used when the population
literals don't have any datatype. SeRQL will try to interpret the literal as a positive integer and
compare it to the one million constant.

6.8.4. The LIKE operator (R1.2)

The LIKE operator can check whether a value matches a specified pattern of characters. '*'
characters can be used as wildcards, matching with zero or more characters. The rest of the
characters are compared lexically. The pattern is surrounded with double quotes, just like a literal's
label.
SELECTCountry
FROM{Country}ex:name{Name}
WHERENameLIKE"Belgium"
USINGNAMESPACE
ex=<http://example.org/things#>

By default, the LIKE operator does a case-sensitive comparison: in the above query, the operator
fails is the variable Name is bound to the value "belgium" instead of "Belgium". Optionally, one can
specify that the operator should perform a case-insensitive comparison:
SELECTCountry
FROM{Country}ex:name{Name}
WHERENameLIKE"belgium"IGNORECASE
USINGNAMESPACE
ex=<http://example.org/things#>

In this query, the operator will succeed for "Belgium", "belgium", "BELGIUM", etc.
The '*' character can be used as a wildcard to indicate substring matches, for example:
SELECTCountry
FROM{Country}ex:name{Name}
WHERENameLIKE"*Netherlands"
USINGNAMESPACE
ex=<http://example.org/things#>

This query will match any country names that end with the string "Netherlands", for example "The
Netherlands".

6.8.5. isResource() and isLiteral()


The isResource() and isLiteral() boolean functions check whether a variable contains a resource or a
literal, respectively. For example:
SELECT*
FROM{R}rdfs:label{L}
WHEREisLiteral(L)

6.8.6. isURI() and isBNode() (R1.2)


The isURI() and isBNode() boolean functions are more specific versions of isResource(). They check
whether a variable is bound to a URI value or a BNode value, respectively. For example, the following
query returns only URIs (and filters out all bNodes and literals):
SELECTV
FROM{R}prop{V}
WHEREisURI(V)

6.8.7. AND, OR, NOT

Boolean constraints and functions can be combined using the AND and OR operators, and negated
using the NOT operator. The NOT operator has the highest presedence, then the AND operator, and

finally the OR operator. Parentheses can be used to override the default presedence of these
operators. The following query is a (kind of artifical) example of this:
SELECT*
FROM{X}Prop{Y}rdfs:label{L}
WHERENOTLLIKE"*FooBar*"AND
(Y=<foo:bar>ORY=<bar:foo>)AND
isLiteral(L)

6.8.8. Nested WHERE clauses (R1.2)


In order to be able to express boolean constraints on variables in optional path expressions, it is
possible to use a nested WHERE clause. The constraints in such a nested WHERE clause restrict
the potential matches of the optional path expressions, without causing the entire query to fail if the
boolean constraint fails.
To illustrate the difference between a nested WHERE clause and a 'normal' WHERE clause, consider
the following two queries on the same data:
Data (using Turtle format):
@prefixfoaf:<http://xmlns.com/foaf/0.1/>.
@prefixex:<http://example.org/>.
_:afoaf:name"Michael".
_:bfoaf:name"Rubens".
_:bex:email"rubinho@example.work".
_:bfoaf:name"Giancarlo".
_:bex:email"giancarlo@example.work".

Query 1 (normal WHERE-clause):


SELECT
Name,EmailAddress
FROM
{Person}foaf:name{Name};
[ex:email{EmailAddress}]
WHEREEmailAddressLIKE"g*"

Query 2 (nested WHERE-clause):


SELECT
Name,EmailAddress
FROM
{Person}foaf:name{Name};
[ex:email{EmailAddress}WHEREEmailAddressLIKE"g*"]

In query 1, a normal WHERE clause specifies that the EmailAddress found by the optional
expression must begin with the letter "g". The result of this query will be:
Name

EmailAddress

Giancarlo "giancarlo@example.work"

Despite the fact that the match on EmailAddress is defined as optional, the persons named "Michael"
and "Rubens" are not returned. The reason is that the WHERE clause explicitly says that the value
bound to the optional variable must start with the letter "g". For Michael, no value is found, hence the
variable is equal to NULL, and the comparison operator fails on this. For Rubens, a value is found,
but it does not start with the letter "g".
In query 2, however, a nested WHERE-clause is used. This specifies that any binding the optional
expression does must begin with the letter "g", otherwise NULL is returned. The result of this query is:
Name

EmailAddress

Michael
Rubens
Giancarlo "giancarlo@example.work"
The person "Michael" is returned without a result for his email address because there is no email
address known for him at all. The person "Rubens" is returned without a result for his email address
because, although he does have an email address, it does not start with the letter "g".
A query can contain at most one nested WHERE-clause per optional path expression, and at most
one 'normal' WHERE-clause.

6.9. Other functions


Apart from the boolean functions and operators introduced in the previous section, SeRQL supports
several other functions that return RDF terms rather than non-boolean values. These functions can
be used in both the SELECT and the WHERE clause.

6.9.1. label(), lang() and datatype()


The three functions label(), lang() and datatype() all operate on literals. The result of the label()
function is the lexical form of the supplied literal. The lang() function returns the language attribute.
Both functions return their result as an untyped literal, which can again be compared with other
literals using (in)equality-, comparison-, and like operators. The result of the datatype() function is a
URI, which can be compared to other URIs. These functions can also be used in SELECT clauses,
but not in path expressions.
An example query:
SELECTlabel(L)
FROM{R}rdfs:label{L}
WHEREisLiteral(L)ANDlang(L)LIKE"en*"

6.9.2. namespace() and localName() (R1.2)


The functions namespace() and localName() operate on URIs. The namespace() function returns the
namespace of the supplied URI, as a URI object. The localName() function returns the local name
part of the supplied URI, as a literal. These functions can also be used in SELECT clauses, but not in
path expressions.

The following query retrieves all properties of foaf:Person instances that are in the FOAF namespace.
Notice that as a shorthand for the full URI, we can use a namespace prefix (followed by a colon) as
an argument.

Data:
@prefixfoaf:<http://xmlns.com/foaf/0.1/>.
@prefixex:<http://example.org/>.
_:ardf:typefoaf:Person.
_:amy:nick"Schumi".
_:afoaf:firstName"Michael".
_:afoaf:knows_:b.
_:brdf:typefoaf:Person.
_:bfoaf:firstName"Rubens".
_:bfoaf:nick"Rubinho".

Query:
SELECTfoafProp,Value
FROM{}foafProp{Value}
WHEREnamespace(foafProp)=foaf:
USINGNAMESPACE
foaf=<http://xmlns.com/foaf/0.1/>

Result:
foafProp

Value

<http://xmlns.com/foaf/0.1/firstName "Michael"
<http://xmlns.com/foaf/0.1/knows

_:b

<http://xmlns.com/foaf/0.1/firstName "Rubens"
<http://xmlns.com/foaf/0.1/nick

"Rubinho"

In the following example, the localName() function is used to match two equivalent properties from
different namespaces (using the above data).
Query:
SELECTnick
FROM{}rdf:type{foaf:Person};
nickProp{nick}
WHERElocalName(nickProp)LIKE"nick"
USINGNAMESPACE
foaf=<http://xmlns.com/foaf/0.1/>

Result:
nick
"Schumi"
"Rubinho"

6.10. The LIMIT and OFFSET clauses

LIMIT and OFFSET allow you to retrieve just a portion of the results that are generated by the query.
If a limit count is given, no more than that many results will be returned (but possibly less, if the query
itself yields less results).

OFFSET says to skip that many results before beginning to return results. OFFSET 0 is the same as
omitting the OFFSET clause. If both OFFSET and LIMIT appear, then OFFSET rows are skipped
before starting to count the LIMIT results that are returned.

6.11. The USING NAMESPACE clause


The USING NAMESPACE clause can be used to define short prefixes for namespaces, which can
then be used in abbreviated URIs. Multiple prefixes can be defined, but each declaration must have a
unique prefix. The following query shows the use of namespace prefixes:
CONSTRUCT
{Artist}rdf:type{art:Painter};
art:hasPainted{Painting}
FROM
{Artist}rdf:type{art:Artist};
art:hasCreated{Painting}rdf:type{art:Painting}
USINGNAMESPACE
rdf=<http://www.w3.org/1999/02/22rdfsyntaxns#>,
art=<http://example.org/arts/>

The query engine will replace every occurence of rdf: in an abbreviated URI with
http://www.w3.org/1999/02/22-rdf-syntax-ns#, and art: with http://example.org/arts/. So art:hasPainted
will be resolved to the URI http://example.org/arts/hasPainted.
Four namespaces that are used very frequently have been assigned prefixes by default:
Table 6.1. Default namespaces
Prefix Namespace
rdf

http://www.w3.org/1999/02/22-rdf-syntax-ns#

rdfs

http://www.w3.org/2000/01/rdf-schema#

xsd

http://www.w3.org/2001/XMLSchema#

owl

http://www.w3.org/2002/07/owl#

serql

http://www.openrdf.org/schema/serql#

These prefixes can be used without declaring them. If either of these prefixes is declared explicitly in
a query, this declaration will override the default mapping.

6.12. Built-in predicates


SeRQL contains a number of built-in predicates. These built-ins can be used like any other predicate,
as part of a path expression. The difference with normal predicates is that the built-ins act as
operators on the underlying rdf graph: they can be used to query for relations between RDF
resources that are not explicitly modeled, nor immediately apparant from the RDF Semantics, but
which are nevertheless very useful.
Currently, the following built-in predicates are supported:
{X}serql:directSubClassOf{Y}

This relation holds for every X and Y where:


1. X rdfs:subClassOf Y.

2. X != Y.
3. There is no class Z (Z != Y and Z != X) such that X rdfs:subClassOf Z
and Z rdfs:subClassOf Y.

{X}serql:directSubPropertyOf{Y}

This relation holds for every X and Y where:


1. X rdfs:subPropertyOf Y.
2. X != Y.
3. There is no property Z (Z != X and Z != Y) such that X
rdfs:subPropertyOf Z and Z rdfs:subPropertyOf Y.

{X}serql:directType{Y}

This relation holds for every X and Y where:


1. X rdf:type Y.
2. There is no class Z (Z != Y) such that X rdf:type Z and Z
rdfs:subClassOf Y.
Note: the above definition takes class/property equivalence through cyclic subClassOf/subPropertyOf
relations into account. This means that if A rdfs:subClassOf B, and B rdfs:subClassOf A, it holds that
A = B.
The namespace prefix 'serql' is built-in and does not have to be defined in the query.

6.13. Set combinatory operations


SeRQL offers three combinatory operations that can be used to combine sets of query results.

6.13.1. UNION (R1.2)


UNION is a combinatory operation the result of which is the set of query answers of both its
operands. This allows one to specify alternatives in a query solution.
By default, UNION filters out duplicate answers from its operands. Specifying the ALL keyword
("UNION ALL") disables this filter.
The following example query retrieves the titles of books in the data, where the property used to
describe the title can be either from the DC 1.0 or DC 1.1 specification.
Data:
@prefixdc10:<http://purl.org/dc/elements/1.0/>.
@prefixdc11:<http://purl.org/dc/elements/1.1/>.
_:adc10:title"TheSeRQLQueryLanguage".
_:bdc11:title"TheSeRQLQueryLanguage(revision1.2)".
_:cdc10:title"SeRQL".
_:cdc11:title"SeRQL(updated)".

Query:

SELECTtitle
FROM{book}dc10:title{title}
UNION
SELECTtitle
FROM{book}dc11:title{title}
USINGNAMESPACE
dc10=<http://purl.org/dc/elements/1.0/>,
dc11=<http://purl.org/dc/elements/1.1/>

Result:
title
"The SeRQL Query Language"
"The SeRQL Query Language (revision 1.2)"
"SeRQL"
"SeRQL (updated)"
The union operator matches the projection items in order without taking the name of the projection
item into account:
SELECTtitle,"1.0"AS"version"
FROM{book}dc10:title{title}
UNION
SELECTy,NULL
FROM{x}dc11:title{y}
USINGNAMESPACE
dc10=<http://purl.org/dc/elements/1.0/>,
dc11=<http://purl.org/dc/elements/1.1/>

Result:
title
"The SeRQL Query Language"

version
"1.0"

"The SeRQL Query Language (revision 1.2)"


"SeRQL"

"1.0"

"SeRQL (updated)"
SeRQL will use the names of the variables in the first operand of the union in the query result.

6.13.2. INTERSECT (R1.2)


The INTERSECT operation retrieves query results that occur in both its operands.
The following query only retrieves those album creators for which the name is specified identically in
both DC 1.0 and DC 1.1.

Data:

@prefixdc10:<http://purl.org/dc/elements/1.0/>.
@prefixdc11:<http://purl.org/dc/elements/1.1/>.
_:adc10:creator"George".
_:adc10:creator"Ringo".
_:bdc11:creator"George".
_:bdc11:creator"Ringo".
_:cdc10:creator"Paul".
_:cdc11:creator"PaulC.".

Query:
SELECTcreator
FROM{album}dc10:creator{creator}
INTERSECT
SELECTcreator
FROM{album}dc11:creator{creator}
USINGNAMESPACE
dc10=<http://purl.org/dc/elements/1.0/>,
dc11=<http://purl.org/dc/elements/1.1/>

Result:
creator
"George"
"Ringo"

6.13.3. MINUS (R1.2)


The Minus operation returns query results from its first operand which do not occur in the results from
its second operand.
The following query returns the titles of all albums of which "Paul" is not a creator.
Data:
@prefixdc10:<http://purl.org/dc/elements/1.0/>.
_:adc10:creator"George".
_:adc10:title"SergeantPepper".
_:bdc10:creator"Paul".
_:bdc10:title"YellowSubmarine".
_:cdc10:creator"Paul".
_:cdc10:creator"Ringo".
_:cdc10:title"LetitBe".

Query:
SELECTtitle
FROM{album}dc10:title{title}

MINUS

SELECTtitle
FROM{album}dc10:title{title};
dc10:creator{creator}
WHEREcreatorlike"Paul"
USINGNAMESPACE
dc10=<http://purl.org/dc/elements/1.0/>,
dc11=<http://purl.org/dc/elements/1.1/>

Result:
title
"Sergeant Pepper"

6.14. NULL values


Just like SQL and most programming languages, SeRQL also has a NULL value. This value can be
used just like any other value in SeRQL. For example, it can be used in the where clause to check
that a literal doesn't have a datatype:
SELECT*
FROM{X}Y{Z}
WHEREisLiteral(Z)ANDdatatype(L)=NULL

6.15. Query Nesting


SeRQL has several constructs for nested queries. Nested queries can occur as operands for several
boolean operators, which are explained in more detail in the following sections.
SeRQL applies variable scoping for nested queries. This means that when a variable is assigned in
the outer query, its value will be carried over to the inner query when that variable is reused there.

6.15.1. The IN operator (R1.2)


The IN operator allows set membership checking where the set is defined by a nested SELECTquery.
The following example query uses the IN operator to retrieve all names of Persons, but only those
names that also appear as names of Authors.
@prefixex:<http://example.org/things#>.
_:ardf:typeex:Person.
_:aex:name"John".
_:brdf:typeex:Person.
_:bex:name"Ringo".
_:crdf:typeex:Author.
_:cex:name"John".
_:drdf:typeex:Author.
_:dex:name"George".

SELECTname

Query:

FROM{}rdf:type{ex:Person};
ex:name{name}
WHEREnameIN(SELECTn
FROM{}rdf:type{ex:Author};
ex:name{n}
)
USINGNAMESPACE
ex=<http://example.org/things#>

Result:
name
"John"

6.15.2. ANY and ALL (R1.2)


The ANY and ALL keywords can be used for existential and universal quantification on the right
operand of a boolean operator, if this operand is a set, defined by a nested query. The ALL keyword
indicates that for every value of the nested query the boolean condition must hold. The ANY keyword
indicates that the boolean condition must hold for at least one value of the nested query.
The following query selects the highest value from a set of values using the ALL keyword and a
nested query.
Data:
@prefixex:<http://example.org/things#>.
_:aex:value"10"^^xsd:int.
_:bex:value"11"^^xsd:int.
_:cex:value"12"^^xsd:int.
_:dex:value"13"^^xsd:int.
_:eex:value"14"^^xsd:int.

Query:
SELECThighestValue
FROM{node}ex:value{highestValue}
WHEREhighestValue>=ALL(SELECTvalue
FROM{}ex:value{value}
)
USINGNAMESPACE
ex=<http://example.org/things#>

Result:
highestValue
"14"^^xsd:int

6.15.3. EXISTS (R1.2)


EXISTS is a unary operator that has a nested SELECT-query as its operand. The operator is an
existential quantifier that succeeds when the nested query has at least one result.

In the following example, we use EXIST to determine whether any authors are known that share a
name with a person, and if so, to retrieve that person's names and hobbies.

Data:
@prefixex:<http://example.org/things#>.
_:ardf:typeex:Person.
_:aex:name"John".
_:aex:hobby"Stampcollecting".
_:brdf:typeex:Person.
_:bex:name"Ringo".
_:bex:hobby"Crosswordpuzzles".
_:crdf:typeex:Author.
_:cex:name"John".
_:cex:authorOf"Letitbe".

Query:
SELECTname,hobby
FROM{}rdf:type{ex:Person};
ex:name{name};
ex:hobby{hobby}
WHEREEXISTS(SELECTn
FROM{}rdf:type{ex:Author};
ex:name{n};
ex:authorOf{}
WHEREn=name
)
USINGNAMESPACE
ex=<http://example.org/things#>

Result:
name

hobby

"John" "Stamp collecting"

6.16. Example SeRQL queries


6.16.1. Query 1
Description: Find all papers that are about "RDF" and about "Querying", and their authors.
SELECT
Author,Paper
FROM
{Paper}rdf:type{foo:Paper};
ex:keyword{"RDF","Querying"};
dc:author{Author}
USINGNAMESPACE
dc=<http://purl.org/dc/elements/1.0/>,
ex=<http://example.org/things#>

Depicted as a graph, this query searches through the RDF graph for all subgraphs matching the
following template:

Figure 6.7. Path expression for query 1

6.16.2. Query 2
Description: Find all artefacts whose English title contains the string "night" and the museum where
they are exhibited. The artefact must have been created by someone with first name "Rembrandt".
The artefact and museum should both be represented by their titles.
SELECTDISTINCT
label(ArtefactTitle),MuseumName
FROM
{Artefact}arts:created_by{}arts:first_name{"Rembrandt"},
{Artefact}arts:exhibited{}dc:title{MuseumName},
{Artefact}dc:title{ArtefactTitle}
WHERE
isLiteral(ArtefactTitle)AND
lang(ArtefactTitle)="en"AND
label(ArtefactTitle)LIKE"*night*"
USINGNAMESPACE
dc=<http://purl.org/dc/elements/1.0/>,
arts=<http://example.org/arts/>

Again, depicted as a subgraph template:


Figure 6.8. Path expression for query 2

Note that this figure only shows the path expressions from the from clause. The where clause poses
additional constraints on the values of the variables which can't be as easily depicted graphically.

6.16.3. Query 3
Description: Find all siblings of class foo:bar.
SELECTDISTINCT
Sibling
FROM
{Sibling,<foo:bar>}rdfs:subClassOf{ParentClass}

Or graphically:

Figure 6.9. Path expression for query 3

Note that the URI foo:bar is not returned as a result (there is an implicit constraint that doesn't allow
Sibling to be equal to values that occur in the same multi-value node).

6.17. Comments/feedback
Feedback on this document and/or the SeRQL language is highly appreciated and can be posted on
the forum at www.openrdf.org.

6.18. References

RQL
RQL tutorial

RDQL

RDF/XML syntax (W3C Recommandation)

Revised RDF/XML syntax (W3C Technical Report)

RDF Semantics (W3C Recommandation)

N-Triples

Turtle

N3

URI (RFC 2396)

Namespace in XML (W3C Recommandation)

6.19. SeRQL grammar


The following is the BNF grammar of SeRQL, revision 1.2:
Query::=Table_query_set(Namespace_list)?
|Graph_query_set(Namespace_list)?
Namespace_list::="using""namespace"Namespace(","Namespace)*
Namespace::=<PREFIX_NAME>"="<FULL_URI>
Table_query_set::=Table_query(Set_operatorTable_query_set)?
Table_query::="("Table_query_set")"
|Select_query
Graph_query_set::=Graph_query(Set_operatorGraph_query_set)?
Graph_query::="("Graph_query_set")"
|Construct_query

Set_operator::="union"|"minus"|"intersect"

Select_query::="select"("distinct")?Projection
("from"Graph_pattern)?
("limit"<POS_INTEGER>)?
("offset"<POS_INTEGER>)?
Projection::="*"
|Projection_elem(","Projection_elem)*
Projection_elem::=Var_or_value("as"<STRING>)?
Construct_query::="construct"("distinct")?Construct_clause
("from"Graph_pattern)?
("limit"<POS_INTEGER>)?
("offset"<POS_INTEGER>)?
Construct_clause::="*"
|Path_expr_list
Graph_pattern::=Path_expr_list("where"Boolean_expr)?
Path_expr_list::=Path_expr(","Path_expr)*
Path_expr::=Path_expr_head((";")?Path_expr_tail)?
|"["Graph_pattern"]"
Path_expr_head::=NodeEdgeNode
Path_expr_tail::=EdgeNode((";")?Path_expr_tail)?
|"["EdgeNode((";")?Path_expr_tail)?("where"Boolean_expr)?"]"
(";"Path_expr_tail)?
Edge::=Var
|Uri
Node::="{"(Node_elem_list)?"}"
Node_elem_list::=Node_elem(","Node_elem)*
Node_elem::=Var
|Uri
|BNode
|Literal
|Reified_stat
Reified_stat::=NodeEdgeNode
Boolean_expr::=And_expr("or"Boolean_expr)?
And_expr::=Boolean_elem("and"And_expr)?
Boolean_elem::="("Boolean_expr")"
|"true"
|"false"
|"not"Boolean_elem
|Var_or_valueComp_opVar_or_value
|Var_or_valueComp_op("any"|"all")"("Table_query_set")"
|Var_or_value"like"<STRING>
|Var_or_value"in""("Table_query_set")"
|"exists""("Table_query_set")"
|"isResource""("Var")"
|"isURI""("Var")"
|"isBNode""("Var")"
|"isLiteral""("Var")"
Comp_op::="="|"!="|"<"|"<="|">"|">="

Var::=<NC_NAME>
Value::=Uri
|BNode
|Literal
|"null"
|"datatype""("Var")"

Var_or_value::=Var|Value

|"lang""("Var")"
|"label""("Var")"
|"namespace""("Var")"
|"localname""("Var")"
Uri::=<FULL_URI>
|<QNAME>
BNode::=<BNODE>
Literal::=(*ASeRQLliteral,seesectiononliterals*)
|<POS_INTEGER>
|<NEG_INTEGER>
|<DECIMAL>
<FULL_URI>::="<"(*alegalURI,seehttp://www.ietf.org/rfc/rfc2396.txt*)">"
<QNAME>::=<PREFIX_NAME>":"<NC_NAME_CHAR>*
<BNODE>::="_:"<NC_NAME>
<POS_INTEGER>::="+"?[09]+
<NEG_INTEGER>::=""[09]+
<DECIMAL>::=("+"|"")?[09]*"."[09]+
<STRING>::='"'(*zeroormore(encoded)characters*)'"'
<PREFIX_NAME>::=<LETTER><NC_NAME_CHAR>*
|"_"<NC_NAME_CHAR>+
<NC_NAME>::=(<LETTER>|"_")<NC_NAME_CHAR>*
<NC_NAME_CHAR>::=(*seehttp://www.w3.org/TR/RECxmlnames/#NTNCNameChar*)
<LETTER>::=(*seehttp://www.w3.org/TR/RECxml/#NTLetter*)

Note: all keywords are assumed to be case-insensitive. Whitespace characters between tokens are
not significant other than for separating the tokens. Production rules with a head that is surrounded
by angular brackets define tokens (aka "terminals").

Chapter 7. The Sesame API


Table of Contents
7.1. An Overview of the Sesame Architecture
7.2. The Repository API
7.2.1. Accessing a repository
7.2.2. Querying a repository
7.2.3. Adding RDF data to a repository
7.3. The Graph API
7.3.1. Creating an empty Graph and adding statements to it
7.3.2. Adding/removing a Graph to/from a repository
7.3.3. Creating a Graph for an existing repository
7.3.4. Creating a graph using graph queries
7.3.5. Using graphs and graph queries for updates
In this chapter, we introduce the Sesame API, and give some brief code examples to show how this
API can be used to communicate with Sesame from another program, either remote, or locally, and
how it can be used as a library instead of as a server.

The Javadoc reference for the Sesame API is available online.

7.1. An Overview of the Sesame Architecture


In Figure 7.1, The Sesame architecture an overview of Sesame's overall architecture is given.
Figure 7.1. The Sesame architecture

Starting at the bottom, the Storage And Inference Layer, or SAIL API, is an internal Sesame API that
abstracts from the storage format used (i.e. whether the data is stored in an RDBMS, in memory, or
in files, for example), and provides reasoning support. SAIL implementations can also be stacked on
top of each other, to provide functionality such as caching or concurrent access handling.
On top of the SAIL, we find Sesame's functional modules, such as the SeRQL, RQL and RDQL query
engines, the admin module, and RDF export. Access to these functional modules is available through
Sesame's Access APIs, consisting of two seperate parts: the Repository API and the Graph API. The
Repository API provides high-level access to Sesame repositories, such as querying, storing of rdf
files, extracting RDF, etc. The Graph API provides more fine-grained support for RDF manipulation,
such as adding and removing individual statements, and creation of small RDF models directly from
code. The two APIs complement each other in functionality, and are in practice often used together.
The Access APIs provide direct access to Sesame's functional modules, either to a client program
(for example, a desktop application that uses Sesame as a library), or to the next component of
Sesame's architecture, the Sesame server. This is a component that provides HTTP- and RMI-based
access to Sesame's APIs. Then, on the remote HTTP/RMI client side, we again find the access APIs,
which can again be used for communicating with Sesame, this time not as a library, but as a server
running on a remote location.
While each part of the Sesame code is publicly available and extensible, most developers will be
primarily interested in the Access APIs, for communicating with a Sesame RDF model or a Sesame
repository from their application. In the next sections, these APIs are described in more detail,
through several code examples.

7.2. The Repository API

The Repository API is the central access point for Sesame repositories. It can be used to query and
update the contents of both local and remote repositories. The Repository API handles all the details
of client-server communication, allowing you to handle remote repositories as easily as local ones.

The main interfaces for the repository API can be found in package org.openrdf.sesame.repository.
The implementations of these interface for local and remote repositories can be found in
subpackages of this package.
In the following sections, the repository API is explained in more detail. We will show how one
connects to an existing repository, how to configure a new (local or remote) Sesame repository, and
how to perform queries or other actions.

7.2.1. Accessing a repository


The first step in any action that involves Sesame repositories is to get hold of a SesameRepository
object representing it. The following sections explain how to do this for a local repository, a remote
repository and a server repository.
7.2.1.1. Local repositories
Local repositories are very useful when you have to deal with some RDF in your own application. You
can quickly create a local repository directly from your own program (without the use of any
configuration files or databases), and store RDF in it, query this RDF and change it if necessary.
To quickly create a non-inferencing main-memory repository, one can use the following code:
LocalServiceservice=Sesame.getService();
booleaninferencing=true;
LocalRepositorymyRepository=service.createRepository("myRep",inferencing);

This creates a local repository that uses main memory for storing its data. The boolean parameter
inferencing indicates whether the repository should do RDF Schema inferencing. Note that the
created repository is volatile: its contents are lost when the object is garbage collected or when the
program is shut down.
For many purposes, the above way of creating a repository is convenient and sufficient. Sometimes,
however, you may want to have a little more control over the exact configuration of a repository. For
example, you may want to have a repository that dumps its contents to file. In such cases, you can
create a RepositoryConfig object, configure it to your liking and pass that object to the
createRepository() method of class LocalRepository.
In the following example, we again create a local repository, but this time we specify that it should use
a file for persistence. First, we need to create a RepositoryConfig object that specifies the
configuration of our required repository. In this example, we create a specification for a repository
with ID "myCustomRep" that uses a stack of two Sails -- a main-memory Sail with schema support,
and a synchronization Sail on top -- and which uses the file C:\TEMP\myCustomRep.rdf as a dump file
for persistent storage.
RepositoryConfigrepConfig=newRepositoryConfig("myCustomRep");
SailConfigsyncSail=new
SailConfig("org.openrdf.sesame.sailimpl.sync.SyncRdfSchemaRepository");
SailConfigmemSail=neworg.openrdf.sesame.sailimpl.memory.RdfSchemaRepositoryConfig(
"C:\\tmp\\myCustomRep.rdf",
RDFFormat.RDFXML);

repConfig.addSail(syncSail);
repConfig.addSail(memSail);
repConfig.setWorldReadable(true);
repConfig.setWorldWriteable(true);

As you can see, by using the SailConfig and RepositoryConfig classes, we can fine-tune the
configuration of our repository. We specify the types of Sails that are to be used, any paramaters for
those Sails (these are the same parameters as described in Chapter 4, Advanced repository
configuration), and read and write permissions. Note that we use the utility class
RdfSchemaRepositoryConfig from package org.openrdf.sesame.sailimpl.memory in this example.
This class is a subclass of SailConfig with main-memory specific methods for easy configuration.
Utility classes like these are available for most Sail implementations.
Now that we have created the repository specification, creating a repository object for it is a snap:
LocalRepositorymyCustomRepository=service.createRepository(repConfig);

The resulting LocalRepository object can then be used to add RDF data, to query the added data,
etc. We will briefly illustrate this in one of the following sections.
7.2.1.2. Remote repositories
When we are using a remote Sesame server, we need to set up a connection with the remote server
and identify the repository that we want to use. The code example below sets up a remote connection
to
a
Sesame
server
over
HTTP. The
server
is
running
at
the
location
http://HOSTNAME/SESAME_DIR/ and we are authenticating ourselves using the username
USERNAME and the password PASSWORD.
java.net.URLsesameServerURL=newjava.net.URL("http://HOSTNAME/SESAME_DIR/");
SesameServiceservice=Sesame.getService(sesameServerURL);
service.login("USERNAME","PASSWORD");

The example for RMI-based communication is nearly identical:


java.net.URIsesameServerURI=newjava.net.URI("rmi://HOSTNAME:PORT/");
SesameServiceservice=Sesame.getService(sesameServerURI);
service.login("USERNAME","PASSWORD");

Please note that we are using a URL object in the HTTP example and a URI object in the RMI
example.
The next step is to connect to a specific repository on this server. Assuming that we want to connect
to the repository that is identified by the string remoteRepositoryID:
SesameRepositorymyRepository=service.getRepository("remoteRepositoryID");

Of course, all of the above may not succeed for a number of reasons, such as the user not being
known, having passed an erroneous password, or perhaps the server is not available. You will need
to handle the exceptions thrown for all these cases. These exceptions are all documented in the
Javadoc documentation. For the sake of keeping the examples simple, we will ignore these
exceptions here.
7.2.1.3. Local manipulation of server repositories

In the previous examples, we have seen how to quickly create a local repository on the spot, or how
to connect through a remote communication protocol (like HTTP or RMI) to a running Sesame server.
In this section, we describe a special use case of the repository API, namely one where we want to
extend the functionality of a Sesame server. An example of this is the creation of a new JSP page for
the server. Of course, one can communicate with the local server through the remote access method
shown earlier, but Sesame also allows us to use the local access method on a running server, which
is much more efficient because the data does not need to beserialized and deserialized.

The Sesame server is represented by the class org.openrdf.sesame.server.SesameServer. Among


other things, this class allows us to retrieve the LocalService that is used by the server by calling the
getLocalService() method:
LocalServiceservice=SesameServer.getLocalService();

Using this object we can get to the available repositories in an identical fashion as in the local
repository scenario.
Note: this method of accessing the server locally only works if the code that executes the
getLocalService() method is executed within the same Java Virtual Machine as the one on which
the server itself runs. For example, this can be used if you wish to add JSP pages to your website,
and these JSP pages are hosted on the same server as the Sesame server. It will not work, however,
if you are programming a standalone program that happens to be executed on the same machine as
the Sesame server.

7.2.2. Querying a repository


Now that we have a connection to a repository (either remote or local), we want to do something with
it. As you can see in the Javadoc documentation, there are a number of methods available for
SesameRepository objects. We will show an example that performs a SeRQL query on a
SesameRepository object called myRepository, retrieve the result as a table, and dumps its values to
standard output:
Stringquery="SELECT*FROM{x}p{y}";
QueryResultsTableresultsTable=myRepository.performTableQuery(QueryLanguage.SERQL,query);
introwCount=resultsTable.getRowCount();
intcolumnCount=resultsTable.getColumnCount();
for(introw=0;row<rowCount;row++){
for(intcolumn=0;column<columnCount;column++){
Valuevalue=resultsTable.getValue(row,column);
if(value!=null){
System.out.print(value.toString());
}
else{
System.out.print("null");
}
System.out.print("\t");
}
System.out.println();
}

A large variety of operations can be performed on repositories in a similar way as the above example.
Of course, all such operations are only allowed if you have sufficient prilileges to perform the
operation. This may require you to log in to the SesameService prior to obtaining the repository object.
For example, if you do not have read acccess on myRepository, the above example will throw an
AccessDeniedException.

7.2.3. Adding RDF data to a repository

Adding RDF to a repository can be done in several ways: the RDF can be in the form of a local file, a
location on the Web, or a java String object. Individual RDF statements can not be added through the
repository API. For that purpose, use the Graph API (see the next section).

The method in the Repository API for adding data is named addData() and it takes several
parameters. The first parameter is the data source. This can be either a java String that contains the
actual RDF, a java.net.URL that specifies the location of an RDF file on the Web, a java.io.File, or
an java.io.InputStream. We will use a URL in the next example.
The addData() method takes several other parameters. The parameter baseURI specifies the base
URI that any relative URIs in the data should be resolved against. format specifies the format of the
data (RDF/XML, N-Triples or Turtle). verifyData is a boolean flag that specifies whether the data
should be checked for syntactic correctness before attempting upload. Finally, listener specifies an
AdminListener object to which status updates during upload, and possible errors and warnings, are
reported.
There are several types of AdminListener available. The AdminMsgCollector collects all messages
and offers convenience methods for checking e.g. whether any errors were reported.
StdOutAdminListener simply prints all messages to StdOut. For other purposes, it can be useful or
necessary to implement your own AdminListener. We will use the StdOutAdminListener in the
following example.
java.net.URLmyRDFData=newjava.net.URL("http://www.foo.com/bar/myRdfFile.rdf");
StringbaseURI="http://my.base.uri#";
booleanverifyData=true;
AdminListenermyListener=newStdOutAdminListener();
myRepository.addData(myRDFData,baseURI,RDFFormat.RDFXML,verifyData,myListener);

7.3. The Graph API


The Graph API provides a representaton of an RDF graph in the form of a Java object. The main
interface for the Graph API is org.openrdf.model.Graph. The purpose of this class is to offer a
convenient way for handling RDF graphs from code. Graphs can be built by programmaticaly adding
statements to it, or they can be created by evaluating a SeRQL-construct query on a Sesame
repository.
In the next sections we will show how to use the Graph API in your own program.

7.3.1. Creating an empty Graph and adding statements to it


An empty graph can be acquired by simply creating a GraphImpl object:
GraphmyGraph=neworg.openrdf.model.impl.GraphImpl();

To add new statements to this graph, we have to create the building blocks of these statements (the
subject, predicate, and object) first. This can be done using a ValueFactory object, which can be
obtained from the graph, as is shown in the following example:
ValueFactorymyFactory=myGraph.getValueFactory();
Stringnamespace="http://www.foo.com/bar#";
URImySubject=myFactory.createURI(namespace,"actor1");
URImyPredicate=myFactory.createURI(namespace,"hasName");
LiteralmyObject=myFactory.createLiteral("TomHanks");
myGraph.add(mySubject,myPredicate,myObject);

We have now added a single statement to the graph, namely that actor1 has a property hasName
with the value "Tom Hanks".

More statements can be added in the same manner, but sometimes it is more convenient to use the
URIs directly to add properties to it:
URIactorClass=myFactory.createURI(namespace,"Actor");
URIrdfType=myFactory.createURI(org.openrdf.vocabulary.RDF.TYPE);
mySubject.addProperty(rdfType,actorClass);

The above code adds a new statement to the graph that produced the ValueFactory that was used to
create mySubject. This code is equivalent to the following:
URIactorClass=myFactory.createURI(namespace,"Actor");
URIrdfType=myFactory.createURI(org.openrdf.vocabulary.RDF.TYPE);
myGraph.add(mySubject,rdfType,actorClass);

7.3.2. Adding/removing a Graph to/from a repository


Now that we have created a graph, we can use it to add all of its statements to our repository:
myRepository.addGraph(myGraph);

We can remove the graph from the repository in the same way:
myRepository.removeGraph(myGraph);

7.3.3. Creating a Graph for an existing repository


Often, you will not want to create a new graph from scratch, but rather create a graph that contains
statements that are in a (local) Sesame repository. The Repository API allows you to do just this: it
can produce a Graph object that wraps a local repository:
GraphmyGraph=myLocalRepository.getGraph();

The produced Graph object allows you to use all of its convenience methods for manipulating the
RDF graph. All changes that are made on the Graph object are directly passed on to the underlying
repository.

7.3.4. Creating a graph using graph queries


In the previous section we have seen how to create a graph view for a local repository. This is easy,
but it might not always be what you want: it doesn't work for remote repositories and it always gives
you a "live" view of the complete contents of the repository. Sometimes you may want to create a
local copy of (a subset of) the RDF graph. Graph queries can be used to accomplish this.
The Repository API offers two methods for evaluating graph queries, of which one returns a Graph
object for the statements produced by the query. This method can be used to extract (a subset of) the
statements from a repository into a local copy.
The following code fragment uses a SeRQL-construct query to create a Graph object containing all
rdfs:subClassOf statements:
Stringquery="CONSTRUCT*FROM{SubClass}rdfs:subClassOf{SuperClass}";
GraphclassHierarchy=myRepository.performGraphQuery(QueryLanguage.SERQL,query);

A graph created in this fashion will be independent from the repository it was extracted from: changes
to the graph will not be passed on to the repository.

7.3.5. Using graphs and graph queries for updates


The Graph API, in combination with graph queries, can be very useful when you wish to update (e.g.
change the value of) a large number of statements in your repository.
For example, suppose we have a repository that contains a large number of statements with a
property NumberOfWheels, and we wish to change the property value from "3" to "4" for each
statement. To achieve this, we can do the following:
myRepository.addGraph(QueryLanguage.SERQL,
"CONSTRUCT{X}<http://www.foo.com/bar#NumberOfWheels>{\"4\"}"+
"FROM{X}<http://www.foo.com/bar#NumberOfWheels>{\"3\"}");
myRepository.removeGraph(QueryLanguage.SERQL,
"CONSTRUCT*"+
"FROM{X}<http://www.foo.com/bar#NumberOfWheels>{\"3\"}";

What happens here is the following: the first query derives new statements from the existing
NumberOfWheels statements, changing the object of these statements from "3" to "4". These new
statements are then added to the repository.
The second query selects all NumberOfWheels statements with the object "3" and removes them
from the repository.
Note that in this particular example the order in which the add and remove operation are executed is
important: the add operation uses a query that selects all resource that have a property
NumberOfWheels with value "3". If we had removed all of the matching statements first, the add
operation would not have had any effect.
Ideally, one would have the posibility to use SQL-like INSERT and REPLACE queries to perform this
kind of operations. Extending SeRQL with these types of queries is on the TODO list.

Chapter 8. Communication protocols


Table of Contents
8.1. Communicating over HTTP
8.1.1. Logging in
8.1.2. Logging out
8.1.3. Requesting a list of available repositories
8.1.4. Evaluating a SeRQL-select, RQL or RDQL query
8.1.5. Evaluating a SeRQL-construct query
8.1.6. Extracting RDF from a repository
8.1.7. Uploading data to a repository
8.1.8. Adding data from the web to a repository
8.1.9. Clearing a repository
8.1.10. Removing statements

In the previous chapter, we have seen how a Java application can communicate remotely with
Sesame through the API. It is also possible to bypass this API (for example, when the client
application is not a Java app) and communicate with a remote Sesame server directly through the
HTTP protocol. In the first section of this chapter, the available actions and parameters for HTTP
communication are explained.

8.1. Communicating over HTTP


In this section, the URL http://HOSTNAME/SESAME_DIR/ is used quite often. This URL is meant to
indicate the location where Sesame is installed. HOSTNAME should be replaced by the name of the
machine that is running Sesame. SESAME_DIR should be replaced by the directory where Sesame
is installed (an empty string if Sesame is installed at the server's root directory).
To communicate with our public demo server, HOSTNAME should be replaced by www.openrdf.org
and SESAME_DIR should be replaced by sesame. This yields http://www.openrdf.org/sesame/ as
the location for the public demo server.
Sesame makes extensive use of multipart/form-data encoded HTTP-POST requests. The reason
for this is that both HTTP-GET and x-www-form-url-encoded HTTP-POST requests can not properly
handle non-ASCII characters. The %xx escape sequences used by this encoding is not able to
represent byte values larger than 255.
All requests described below use multipart/form-data encoded HTTP-POST requests, unless
specified otherwise. All string values are assumed to be encoded in UTF-8. Sesame switched to
using this communication style in version 1.1-RC2. For now, the server will also be able to handle the
previously used x-www-form-url-encoded requests to facilitate the transition of all third-party tools.

8.1.1. Logging in
8.1.1.1. Request
In order to get access to non-public repositories on a Sesame server, one needs to log in to it. To do
this, a request should be sent to http://HOSTNAME/SESAME_DIR/servlets/login, supplying the
following parameters:
Table 8.1. Parameters for login
Parameter Required? Description
user

yes

The user's login name.

password

no

The user's password. The password is only required in case the concerning
user has a non-empty password.

8.1.1.2. Response
If the log in attempt succeeded, Sesame will respond with HTTP-code 200 ("OK") and will supply a
cookie with a session ID that should be supplied for authentication in subsequent requests. The
name of this cookie is sesame_sid.
8.1.1.3. Errors
If an invalid request is sent (e.g. the username is missing or the password was incorrect) Sesame will
respond with an HTTP error code and a free format error message.

8.1.2. Logging out

8.1.2.1. Request

To

log

out

from

Sesame

server, one
needs
to
send
a
request
to
http://HOSTNAME/SESAME_DIR/servlets/logout, supplying a session ID cookie that has been
received earlier while logging in. Duplicate log out requests or log out requests for non-existing
sessions are silently ignored.
8.1.2.2. Response
Sesame will respond with HTTP-code 200 ("OK") and a free format text telling you that you have
been logged out.

8.1.3. Requesting a list of available repositories


8.1.3.1. Request
Information on available repositories can be acquired from Sesame by sending an HTTP-GET
request to http://HOSTNAME/SESAME_DIR/servlets/listRepositories. This request requires no
parameters, other than the optional session cookie.
8.1.3.2. Response
Sesame will respond with HTTP-code 200 ("OK"). The body of the response contains an XMLdocument describing the repositories available to the user that is currently logged in (if any). This
XML-document will adhere to the following DTD:
<!ELEMENTrepositorylist(repository)*>
<!ELEMENTrepository(title)>
<!ELEMENTtitle(#PCDATA)>
<!ATTLISTrepository
idID#REQUIRED
readable(true|false)#REQUIRED
writeable(true|false)#REQUIRED>

The following is an example output with two repositories, one read-write and one read-only.
<?xmlversion="1.0"encoding="UTF8"?>
<repositorylist>
<repositoryid="repository1"readable="true"writeable="true">
<title>Publicrepository</title>
</repository>
<repositoryid="repository2"readable="true"writeable="false">
<title>Repository2</title>
</repository>
</repositorylist>

The value of the id attribute is the identifier of the repository. This identifier can be used in
consecutive requests to Sesame to specify which repository that request is about.

8.1.4. Evaluating a SeRQL-select, RQL or RDQL query


8.1.4.1. Request

SeRQL-select, RQL and RDQL queries are all queries that return, in some way or another, sets of
variable bindings or table-like results. SeRQL-construct queries are a different type of queries that
return free-form RDF documents. Details about SeRQL-construct queries can be found in Evaluating
a SeRQL-construct query.

SeRQL-select,

RQL

and

RDQL

queries
can
be
sent
to
http://HOSTNAME/SESAME_DIR/servlets/evaluateTableQuery. The multipart/form-data encoded
HTTP-POST method is the preferred method. HTTP-GET is also supported but can only be used if all
parameter values consists of ASCII characters only. All requests can or must include the following
parameters:
Table 8.2. Parameters for evaluateTableQuery
Parameter

Required? Description

repository

yes

The id of the repository to evaluate the query on.

query

yes

The query to evaluate.

queryLanguage

yes

The query's language. Legal values are SeRQL, RQL and RDQL.

resultFormat

no

Determines the format of the result. Legal values are xml (the default
value) for an XML-representation of the query result, html for a humanreadable HTML-table presentation and rdf for an RDF-representation of
the variable bindings.

serialization

no

The serialization to use when rdf is choosen as the resultFormat. Legal


values are rdfxml (the default value), ntriples and turtle.

8.1.4.2. Response
If all went well, Sesame responds with HTTP-code 200 ("OK") and the results of the query evaluation.
The resultFormat and serialization parameters determine the format of the results and the
Content-Type header of the response:
Table 8.3. Response formats for SeRQL-select, RQL and RDQL queries

xml

html

rdf

rdfxml

text/xml

text/html

Result

An XML
representatio This is the default format and is the best
n of the
format for processing by other applications.
results table.
An HTML
document

An XMLapplication/rdf+x encoded
ml
RDF
document

rdf

ntriples

text/plain

rdf

turtle

application/xturtle

Comments

The results are formatted in a humanreadable (when displayed in a browser)


HTML-table. This format should only be
used by the Sesame web interface.
The result is an RDF document containing
sets of variable bindings. This is an
experimental format from Andy Seaborne
and may be modified in the future. See
http://www.w3.org/2003/03/rdfqrtests/recording-query-results.html for details.

An N-Triples- The result is identical to the previous one,


encoded
but uses another encoding: N-Triples. See
RDF
http://www.w3.org/TR/rdf-testcases/#ntriples
document
for more information about N-Triples.
A Turtleencoded
RDF

The result is identical to the previous two,


but uses yet another encoding: Turtle (Terse
RDF Triple Language). See

resultForma serializatio
Content-type
t
n

resultForma serializatio
Content-type
t
n

Result

Comments

document

http://www.ilrt.bris.ac.uk/discovery/2004/01/t
urtle/ for more information about Turtle.

If the selected result format is xml, the output will look something like this:
<?xmlversion="1.0"encoding="UTF8"?>
<tableQueryResult>
<header>
<columnName>X</columnName>
<columnName>Y</columnName>
</header>
<tuple>
<uri>http://www.foo.com/schema.rdf#change</uri>
<literal>Change</literal>
</tuple>
<tuple>
<bNode>node001</bNode>
<literaldatatype="http://www.w3.org/2001/XMLSchema#int">256</literal>
</tuple>
</tableQueryResult>

The document starts with a header listing the names of all result columns. The names of these
columns often represent variable names, but this is not guaranteed. Some query languages also
allow you to use constants or functions in a query's projection. In that case, the name of the column
will be the constant and the function, respectively.
Following the header, zero or more tuple-elements will follow, one for each query result (or row in the
table). Each result consists of a sequence of URIs, bNodes (blank nodes, also know as anonymous
nodes), and/or literals. The values appear in the order in which they were specified in the query,
which is the same as the order in the header.
The example output above shows how URIs, bNodes and literals (with their optional language
encoding or datatype) are exported. Next to these three, there is a fourth type of value that is only
exported by the RQL engine: intersections of classes. If a query asks for a domain or range of a
property, then this domain or range can consist of the intersection of zero or more classes. These
intersections are exported in intersection elements containing zero or more URIs and bNodes:
<?xmlversion="1.0"encoding="UTF8"?>
<tableQueryResult>
<tuple>
<uri>http://www.icom.com/schema1.rdf#creates</uri>
<intersection>
<uri>http://www.icom.com/schema1.rdf#Artifact</uri>
<uri>http://www.schemas.org/general#Stuff</uri>
</intersection>
</tuple>
</tableQueryResult>

When a property doesn't have any range restrictions, its range will be an empty intersection element.
Domains or ranges that consist of exactly one class are exported as normal resources (see first
example), and not as intersections.
8.1.4.3. Errors

If an error occurred while the request was being processed, Sesame will send back an HTTP error
code (i.e. not 200) and a free format error message.

8.1.5. Evaluating a SeRQL-construct query


8.1.5.1. Request
SeRQL-construct

queries

can

be
sent
to
The multipart/form-data encoded
HTTP-POST method is the preferred method. HTTP-GET is also supported but can only be used if all
parameter values consists of ASCII characters only. All requests can or must include the following
parameters:
http://HOSTNAME/SESAME_DIR/servlets/evaluateGraphQuery.

Table 8.4. Parameters for evaluateGraphQuery


Parameter

Required? Description

repository

yes

The id of the repository to evaluate the query on.

query

yes

The query to evaluate.

queryLanguage

yes

The query's language. Currently, the only legal value is SeRQL.

serialization

no

Determines the serialization format of the returned RDF document. Legal


values are rdfxml (the default value), ntriples and turtle.

8.1.5.2. Response
If all went well, Sesame responds with HTTP-code 200 (i.e. "OK") and the results of the query
evaluation. The serialization parameter determines the encoding of the returned RDF document
and the Content-Type header of the response:
Table 8.5. RDF encodings for SeRQL-construct queries
Serialization Content-type

RDF
Comments
encoding

rdfxml

XMLapplication/rdf+xml encoded
RDF.

ntriples

text/plain

turtle

This is the official standard format for exchanging RDF


documents. See http://www.w3.org/RDF/ for more info.

This is a quite verbose, line-based encoding that is the


N-Triples easiest one to parse. See http://www.w3.org/TR/rdftestcases/#ntriples for more info.

application/x-turtle Turtle

Turtle stands for Terse RDF Triple Language and is


developed by Dave Beckett to combine useful features
of N3 and N-Triples into an easy-to-read-and-parse
serialization format. See
http://www.ilrt.bris.ac.uk/discovery/2004/01/turtle/ for
more info.

What follows are three examples of one and the same RDF document (a possible query result) in
different encodings.
XML-encoded RDF:

<?xmlversion="1.0"encoding="UTF8"?>
<rdf:RDFxml:lang="en"
xmlns:rdf="http://www.w3.org/1999/02/22rdfsyntaxns#"
xmlns:cult="http://www.icom.com/schema.rdf#">

<cult:Cubistrdf:about="http://www.europeanhistory.com/picasso.html">
<cult:paints>
<cult:Paintingrdf:about="http://www.europeanhistory.com/jpg/guernica03.jpg">
<cult:technique>oiloncanvas</cult:technique>
</cult:Painting>
</cult:paints>
<cult:first_name>Pablo</cult:first_name>
<cult:last_name>Picasso</cult:last_name>
</cult:Cubist>
</rdf:RDF>

N-Triples:
<http://www.europeanhistory.com/picasso.html><http://www.w3.org/1999/02/22rdfsyntax
ns#type><http://www.icom.com/schema.rdf#Cubist>.
<http://www.europeanhistory.com/picasso.html><http://www.icom.com/schema.rdf#paints>
<http://www.europeanhistory.com/jpg/guernica03.jpg>.
<http://www.europeanhistory.com/jpg/guernica03.jpg><http://www.w3.org/1999/02/22rdf
syntax#type><http://www.icom.com/schema.rdf#Painting>.
<http://www.europeanhistory.com/jpg/guernica03.jpg>
<http://www.icom.com/schema.rdf#technique>"oiloncanvas"@en.
<http://www.europeanhistory.com/picasso.html><http://www.icom.com/schema.rdf#first_name>
"Pablo"@en.
<http://www.europeanhistory.com/picasso.html><http://www.icom.com/schema.rdf#last_name>
"Picasso"@en.

Turtle:
@prefixcult:<http://www.icom.com/schema.rdf#>.
@prefixrdf:<http://www.w3.org/1999/02/22rdfsyntaxns#>.
<http://www.europeanhistory.com/jpg/guernica03.jpg>acult:Painting;
cult:technique"oiloncanvas"@en.
<http://www.europeanhistory.com/picasso.html>acult:Cubist;
cult:paints<http://www.europeanhistory.com/jpg/guernica03.jpg>;
cult:first_name"Pablo"@en;
cult:last_name"Picasso"@en.

8.1.5.3. Errors
If an error occurred while the request was being processed, Sesame will send back an HTTP error
code (i.e. not 200) and a free format error message.

8.1.6. Extracting RDF from a repository


8.1.6.1. Request
Ontologies

and

data

can

be

extracted

from

Sesame

by

sending

request

to

http://HOSTNAME/SESAME_DIR/servlets/extractRDF. This operation supports both multipart/formdata encoded HTTP-POST requests as well as HTTP-GET requests. Note that the latter can not be

used when one of the parameter values contains non-ASCII characters.


The request must or can have the following parameters:

Parameter

Required? Description

repository

yes

The id of the repository to extract the data from.

Table 8.6. Parameters for extractRDF

Parameter

Required? Description

schema

no

RdfExport will export the schematical data if the value of this parameter is
on. The schematical data will not be exported if this parameter is missing
or if it has any other value.

no

RdfExport will export the non-ontological data if the value of this parameter
is on. This data will not be exported if this parameter is missing or if it has
any other value.

no

RdfExport will only export the explicitly added statements if the value of
this parameter is on. If this parameter is missing or if it has any other
value, all relevant statements (both explicit and inferred) will be exported.

niceOutput

no

RdfExport will invest extra effort into making the exported data more
readable to humans (e.g. by sorting statements by their subject) if the
value of this parameter is on. If this parameter is missing or if it has any
other value, no such effort is made, allowing RdfExport to export the data
as efficiently as possible.

serialization

no

Determines the serialization of the resulting RDF document. Legal values


are rdfxml (the default value), ntriples and turtle.

data

explicitOnly

So, to extract the ontological data only (both explicit and inferred) from a repository test-db on host
www.openrdf.org
you
can
send
an
HTTP-GET
request
to
the
url
http://www.openrdf.org/sesame/servlets/extractRDF?repository=testdb&serialization=rdfxml&onto=on.

8.1.6.2. Response
If all went well, Sesame responds with HTTP-code 200 ("OK"). The body of the response contains the
requested data. The serialization parameter determines the encoding and the Content-Type
header of the response identically to what is described in Table 8.5, RDF encodings for SeRQLconstruct queries.
8.1.6.3. Errors
If an invalid request is sent (e.g. the repository does not exist) Sesame will respond with an HTTP
error code and a free format error message.

8.1.7. Uploading data to a repository


8.1.7.1. Request
Data

can

be

uploaded

to

http://HOSTNAME/SESAME_DIR/servlets/uploadData,

Sesame
by
sending
supplying the following parameters:

it

to

Table 8.7. Parameters for uploadData


Required? Description

repository

yes

The id of the repository to which to add the data.

data

yes

The RDF data that should be added to the repository. The format of the
data should match the value of the dataFormat parameter.

dataFormat

no

The format of the data that is uploaded to Sesame. Legal values are rdfxml
(the default value), ntriples and turtle.
6

Parameter

Parameter

Required? Description

baseURI

no

Specifies the base URI of the data for resolving any relative URIs. This
parameter defaults to foo:bar, which is fine if the uploaded data does not
contain any relative URIs.

verifyData

no

The uploaded data will be verified before it is actually added to a repository


if the value of this parameter is on. If this parameter is missing or if it has
any other value, the data will be added directly to the repository. Verification
of the data should only be disabled if the data to upload is guaranteed to be
correct.

resultFormat

no

Determines the response format. Legal values are xml (the default value)
and html.

8.1.7.2. Response
The response is always an HTTP-code 200 ("OK"). Streaming feedback is given on the progress, and
warnings and errors are given if the data contains errors. If the selected format was html, then this
feedback will be formatted in human-readable HTML (when displayed in a browser). If the selected
format was xml, then the feedback will adhere to the following DTD:
<!ELEMENTtransaction(status|notification|warning|error)*>
<!ELEMENTstatus(msg,line?,column?)>
<!ELEMENTnotification(msg,line?,column?,statement?)>
<!ELEMENTwarning(msg,line?,column?,statement?)>
<!ELEMENTerror(msg,line?,column?,statement?)>
<!ELEMENTmsg(#PCDATA)>
<!ELEMENTline(#PCDATA)>
<!ELEMENTcolumn(#PCDATA)>
<!ELEMENTstatement((uri|bNode),uri,(uri|bNode|literal))>
<!ELEMENTuri(#PCDATA)>
<!ELEMENTbNode(#PCDATA)>
<!ELEMENTliteral(#PCDATA)>
<!ATTLISTliteral
xml:langCDATA#IMPLIED
datatypeCDATA#IMPLIED>

<?xmlversion="1.0"encoding="UTF8"?>
<transaction>
<status>
<msg>Loadingdata</msg>
</status>
<status>
<msg>Dataloaded(756bytes)</msg>
</status>
<status>
<msg>Checkingdataforerrors</msg>
</status>
<error>
<msg>Notalegalinteger:HelloWorld!</msg>
<line>483</line>
<column>42</column>
<statement>
<bNode>node1234</bNode>
<uri>http://example.org/schema.rdf#age</uri>
<literaldatatype="http://www.w3.org/2001/XMLSchema#int">HelloWorld!</literal>

The following is a simple example of what the feedback might look like when incorrect data is
uploaded to Sesame:

</statement>
</error>
</transaction>

8.1.7.3. Errors
Errors in the requests are signaled using HTTP error codes. Errors in the data are expressed in the
streaming feedback.

8.1.8. Adding data from the web to a repository


8.1.8.1. Request
Data can also be added to a repository by specifying a URL that points to the RDF data that should
be
added.
To
do
this,
send
an
HTTP-POST
request
to
http://HOSTNAME/SESAME_DIR/servlets/uploadURL, supplying the following parameters:
Table 8.8. Parameters for uploadData
Parameter

Required? Description

repository

yes

The id of the repository to which to add the data.

url

yes

A URL pointing at the RDF data that should be added to the repository. The
format of the data at the specified location should match the value of the
dataFormat parameter.

dataFormat

no

The format of the data that is at the specified URL. Legal values are rdfxml
(the default value), ntriples and turtle.

baseURI

no

Specifies the base URI of the data for resolving any relative URIs. This
parameter defaults to the value of url.

verifyData

no

The data at the specified URL will be verified before it is actually added to a
repository if the value of this parameter is on. If this parameter is missing or
if it has any other value, the data will be added directly to the repository.
Verification of the data should only be disabled if the data to upload is
guaranteed to be correct.

resultFormat

no

Determines the response format. Legal values are xml (the default value)
and html.

8.1.8.2. Response
The response format is identical to what is described in Data upload response format.
8.1.8.3. Errors
Errors in the requests are signaled using HTTP error codes. Errors in the data are expressed in the
streaming feedback.

8.1.9. Clearing a repository


8.1.9.1. Request
can

be

removed

from

Sesame

http://HOSTNAME/SESAME_DIR/servlets/clearRepository.

clearing a repository:

by
sending
a
request
to
The following parameters are relevant to
6

Data

Table 8.9. Parameters for clearRepository


Parameter

Required? Description

repository

yes

The id of the repository that should be cleared.

resultFormat

no

Determines the response format. Legal values are xml (the default value)
and html.

8.1.9.2. Response
Identical to the reponse when adding data to a repository. See See Data upload response format. for
more information.
8.1.9.3. Errors
Errors in the requests are signaled using HTTP error codes. Errors that occured while clearing the
repository are expressed in the streaming feedback.

8.1.10. Removing statements


8.1.10.1. Request
Data

can

be

removed

from

Sesame

by
sending
a
requests
to
Currently, Sesame only support removing
of statements using statement patterns: one can specify a subject, predicate and/or object and all
statements that match that pattern will be removed. The following parameters are relevant to the
removal of statements:
http://HOSTNAME/SESAME_DIR/servlets/removeStatements.

Table 8.10. Parameters for removeStatements


Parameter

Required? Description

repository

yes

The id of the repository from which the statements should be removed.

subject

no

An N-Triples encoded URI or bNode specifying the subject of the


statements that should be removed. If not specified, statements with any
subject will be removed.

predicate

no

An N-Triples encoded URI specifying the predicate of the statements that


should be removed. If not specified, statements with any predicate will be
removed.

object

no

An N-Triples encoded URI, bNode or literal specifying the object of the


statements that should be removed. If not specified, statements with any
object will be removed.

resultFormat

no

Determines the result format. Legal values are xml (the default value) and
html.

8.1.10.2. Response
Identical to the reponse when adding data to a repository. See Data upload response format for more
information.

8.1.10.3. Errors

Errors in the requests are signaled using HTTP error codes. Errors that occured while removing
statements from the repository are expressed in the streaming feedback.

Chapter 9. Frequently Asked Questions


Table of Contents
9.1. General Questions
9.1.1. I've got a Sesame-related question, where can I get an answer?
9.1.2. Something goes wrong when I use Sesame, what do I do?
9.1.3. How do I report a bug?
9.1.4. Why doesn't Sesame support $FEATURE?
9.1.5. I need $FEATURE right now!
9.1.6. Can you keep me informed of any Sesame-related news?
9.1.7. Is this user guide the only documentation for Sesame?
9.2. Troubleshooting
9.2.1. I get a "HTTP error 500" message in the toolbar frame
9.2.2. I get a "HTTP error 500" message in the main frame
9.2.3. I get "error while adding new triples: Invalid byte 2 of 3-byte UTF-8
sequence"
9.2.4. I get a warning: "Unable to set namespace prefix 'foo' for
namespace ..."
9.2.5. My in-memory repository is very slow and/or runs out of memory
9.2.6. On upload I get an error "java.lang.IllegalStateException: Post too
large"
9.2.7. Can not evaluate directSubClassOf on a non-inferencing repository

9.1. General Questions


9.1.1. I've got a Sesame-related question, where can I get an answer?
First of all, please make sure that your question is not already answered in this user guide. If it isn't,
then feel free to post your question on the openRDF.org forum. To avoid off-topic discussions (a.k.a.
"spam"), you'll have to register yourself before you can post to the forum. Also, we don't like to talk to
"anonymous" all the time.
Please don't send any questions to the developers directly, unless the question is related to the public
server or is somewhat confidential.

9.1.2. Something goes wrong when I use Sesame, what do I do?


In general, when something does not work as expected in Sesame, or you get an error, try and find
the cause of the error before reporting it to us. See if the error message tells you anything. Check the
Sesame log files in [SESAME_DIR]/WEB-INF/logs for any clues about what went wrong.
Also, check the documentation and forum to see if your problem is described there somewhere. In
Section 9.2, Troubleshooting we provide a number of possible causes and solutions to regularlyoccurring problems. On the forum, we answer user problems, your problem might have come up
before, and our answer to that other person might be useful for you as well.

If you can't find any relevant information for your problem anywhere, feel free to report a bug or post
a comment on the forum.

9.1.3. How do I report a bug?


If you have found a bug in Sesame then you can log it directly in the issue tracker. Please make sure
that the bug is not a duplicate of an already logged issue. If you are not sure that your problem is
caused by a bug in Sesame then feel free to post a description of your problem on the forum.
When posting a bug report to either issue tracker or forum, always make sure to include detailed
information: in what circumstances does the bug occur, what version of Sesame are you using, what
type of repository (RDBMS, in-memory, inferencing, etc.) are you using, and if available provide an
exception stacktrace.

9.1.4. Why doesn't Sesame support $FEATURE?


Sesame is used by a diverse group of people for very different purposes, who all demand different
features to be implemented in Sesame. Since there are only 24 hours in a day, we can not please
everybody all the time. Instead, we try to assess as best we can which features are most important
for the largest part of Sesame's user base. Also, we give priority to features that we need for our own
work with Sesame.
So, if Sesame doesn't support a particular feature, but this feature 'should be in any self-respecting
RDF framework', chances are that we simply haven't had time for it yet. Try and see if the feature has
come up on Sesame's issue tracker or web forum. If it hasn't, don't be shy to raise the issue. If you've
come up with something you'd really like to see included in Sesame, we'd like to know about it.

9.1.5. I need $FEATURE right now!


There is a number of ways you can make sure a particular feature is added to Sesame:

You can let us know of your need, explaining why it is crucial, through the
web forum or issue tracker (by adding a new item or by voting for an
existing issue). Of course, there is no guarantee that we will immediately
move it to the top of our ToDo pile.
You can implement it yourself. Yes, that's right: Sesame is open source, and
we thrive on community feedback, not just in the form of comments and bug
reports, but also of code contributions. If you need some feature or
improvement real bad, consider implementing it yourself and sharing the
result with the rest of the Sesame community. We'd be overjoyed to receive
your contribution and include it in Sesame.
You can pay Aduna to implement it for you. Aduna offers commercial
support contracts for Sesame, and if special features are something you
need, we can provide that as part of such support. Contact info@adunasoftware.com for detailed information.

9.1.6. Can you keep me informed of any Sesame-related news?


Sesame-related news items, such as release announcements, are sent to the sesame-interest
mailing list, which is hosted by SourceForge. Please subscribe yourself to the mailing list if you want
to be kept informed. Please note that this is a restricted mailing list: it can not be used for discussing
Sesame-related issues.

If you want to keep up-to-date on Sesame developments in more detail, consider joining the web
forum. The forum also provides an RSS feed that will provide you with the most recent topics of
discussion. Ideal for staying in touch with the community!

9.1.7. Is this user guide the only documentation for Sesame?


No, it isn't. The project's website contains a number of references to research papers and Sesamerelated projects.

9.2. Troubleshooting
In this section, we identify some commonly encountered problems with the installation, configuration
and use of Sesame, and possible solutions.
Of course, not all possible problems can be found here. If you have a problem that is not described
here, you can get feedback on how to deal with it by posting a message to the openRDF.org forum.
Include as many relevant details as possible, for example, which version of Sesame you are using,
possible java exceptions, log error messages, and so forth.

9.2.1. I get a "HTTP error 500" message in the toolbar frame


There are several possible reasons for this error. HTTP error 500 is a generic code that means
'Internal server error'. It often helps to try and scroll down in the toolbar frame (by selecting the text
with the mouse), there will be more detailed error report further down.
There are several possible problems:

The JDBC driver can not be found


This means that you have tried to access an RDBMS-based repository for
which no JDBC driver is installed. Make sure that you have the correct
JDBC driver, and have it installed in [SESAME_DIR]/WEB-INF/lib.

The database does not exist


This means that you have tried to access a repository for which no database
was created. Verify in your repository configuration that the parameter
jdbcUrl is set correctly, and verify that the database is created and
accessible for Sesame (for details on how to do this, we refer you to the
documentation of your RDBMS).
Access denied for user 'sesame'@'localhost'
This means that the the supplied MySQL user ('sesame') does not have
sufficient access rights.
Sesame will need a user account on the MySQL server. You can create a
new user account in MySQL by connecting to the mysql database mysql -u
root -p mysql, and by granting the user all privileges on the concerning
database(s), e.g.:
GRANTALLON<DATABASE>.*TO<USER>@localhost;

See http://www.mysql.com/doc/G/R/GRANT.html for MySQL's syntax of


GRANT.

Other less common problems may also cause this error. In general, take a good look at the detailed
error message or the repository log file (in [SESAME_DIR]/WEB-INF/logs/repositories/) to find out
the cause of the problem.

9.2.2. I get a "HTTP error 500" message in the main frame


After upgrading a Sesame server to a new version of Sesame, it may occur that the web interface
fails with a HTTP error 500 and an error report similar to the following:
javax.servlet.ServletException:org.openrdf.sesame.server.SesameServer.getLocalService()
Lorg/openrdf/sesame/local/LocalService;
(....)
rootcause
java.lang.NoSuchMethodError:org.openrdf.sesame.server.SesameServer.getLocalService()
Lorg/openrdf/sesame/local/LocalService;
org.apache.jsp.index_jsp._jspService(index_jsp.java:77)
(....)

The root cause here indicates that the JSP page is not correctly compiled: it can not find a particular
Java method.
The cause is that Apache Tomcat sometimes fails to recompile JSP pages after they have been
updated. The compiled JSP pages still refer to methods in the old version of Sesame, which may not
be present anymore in your new version (this is most likely to occur when upgrading to 1.0 from an
earlier release, since a lot of API changes were made for that version).
The solution is to empty Tomcat's JSP compile cache. For Tomcat 4 this cache can be found in
[TOMCAT_DIR]\work\Standalone\localhost\sesame,
for
Tomcat
5
in
[TOMCAT_DIR]\work\Catalina\localhost\sesame. Simply delete all files and folders contained in this
directory and re-load the web interface.

9.2.3. I get "error while adding new triples: Invalid byte 2 of 3-byte UTF-8 sequence"
This is a parser error that can occur during upload of RDF/XML documents to Sesame. The most
likely cause is that the document you are uploading specifies that it is in UTF-8 encoding, but that it
contains non-UTF-8 characters. As UTF-8 is the default character set for XML, it might also be the
case that the document does not specify a character set at all.
The solution is to change the encoding specification of the XML file to the appropriate type. For
example, if the used character set is ISO-8859-1 (this is one of the most common character sets for
"Western" documents), the header of the XML file should be changed to:
<?xmlversion="1.0"encoding="iso88591"?>

More information about character encodings can be found here.

9.2.4. I get a warning: "Unable to set namespace prefix 'foo' for namespace ..."

This happens when you try to upload data to a repository which already contains a namespace
declaration with the prefix 'foo', but which maps it to a different namespace URL. In such cases, a
conflict occurs. Sesame handles these cases by assigning a non-conflicting namespace prefix to the
namespace in the new document (for example, 'ns1').

Most of the time, you can safely ignore this warning. Sometimes it indicates a problem with your RDF
document: it may have a mistake in its namespace declarations. In such cases, examine the
namespace declarations in your RDF document and fix any errors before attempting another upload.

9.2.5. My in-memory repository is very slow and/or runs out of memory


By default, Tomcat only uses a 64MB heap size for the Java process. When you are using a large inmemory repository, this can be too small: the process becomes slow because the garbage collector
is invoked more often, and it can even run out of memory.
The solution is to configure Tomcat to use a larger heap size. This can be done by editing
[TOMCAT_DIR]/bin/catalina.bat (MS Windows) or catalina.sh (Unix systems). You can increase
the heap size by adding a parameter to the environment variable JAVA_OPTS. The parameter to be
added is '-Xmx128M' (where the number 128 indicates that 128 Megabytes should be used. Increase
as required). For catalina.bat there now should be a line in your file that looks like this:
setJAVA_OPTS=Xmx128M

For catalina.sh the line should look like this:


JAVA_OPTS='Xmx128M'

For more information on Tomcat memory reservation, see the Tomcat FAQ.

9.2.6. On upload I get an error "java.lang.IllegalStateException: Post too large"


Apache Tomcat by default sets a limit on the maximum size of HTTP POST requests it accepts. In
Tomcat 5, this limit is set to 2 MB. When you try to upload RDF files larger than 2 MB to Sesame, this
error can occur.
The solution is to reconfigure Tomcat to accept larger POST requests, either by increasing the limit,
or by disabling it. This can be done by editing [TOMCAT_DIR]/conf/server.xml. Set the Tomcat
configuration parameter maxPostSize for the HTTPConnector to a larger value (in bytes) to increase
the limit. Setting it to 0 in will disable the size check. See the Tomcat Configuration Reference for
more information.

9.2.7. Can not evaluate directSubClassOf on a non-inferencing repository


When executing queries that use a SeRQL built-in operator, such as directSubClassOf (see
Chapter 6, The SeRQL query language (revision 1.2)), this error may occur:
org.openrdf.sesame.query.QueryEvaluationException:
CannotevaluatedirectSubClassOfonanoninferencingrepository

This indicates that the repository you are trying to evaluate this query on is an RDF repository, not an
RDF Schema repository. The former does not have inferencing capabilities.
SeRQL needs an inferencing repository for evaluating queries with built-in operators, because these
operators work on the class hierarchy. Without inferencing support, the results of these operators
would become random and unpredictable.

The solution is to either reformulate your query, removing all use of SeRQL built-in operators, or
create a new repository that does have inferencing capabilities (an RdfSchemaRepository), transfer
your RDF data to it, and use this new repository for your queries.

Appendix A. GNU Free Documentation License


Table of Contents
A.1. PREAMBLE
A.2. APPLICABILITY AND DEFINITIONS
A.3. VERBATIM COPYING
A.4. COPYING IN QUANTITY
A.5. MODIFICATIONS
A.6. COMBINING DOCUMENTS
A.7. COLLECTIONS OF DOCUMENTS
A.8. AGGREGATION WITH INDEPENDENT WORKS
A.9. TRANSLATION
A.10. TERMINATION
A.11. FUTURE REVISIONS OF THIS LICENSE
A.12. How to use this License for your documents
Version 1.1, March 2000
Copyright (C) 2000 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 021111307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but
changing it is not allowed.

A.1. PREAMBLE
The purpose of this License is to make a manual, textbook, or other written document "free" in the
sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without
modifying it, either commercially or noncommercially. Secondarily, this License preserves for the
author and publisher a way to get credit for their work, while not being considered responsible for
modifications made by others.
This License is a kind of "copyleft", which means that derivative works of the document must
themselves be free in the same sense. It complements the GNU General Public License, which is a
copyleft license designed for free software.
We have designed this License in order to use it for manuals for free software, because free software
needs free documentation: a free program should come with manuals providing the same freedoms
that the software does. But this License is not limited to software manuals; it can be used for any
textual work, regardless of subject matter or whether it is published as a printed book. We
recommend this License principally for works whose purpose is instruction or reference.

A.2. APPLICABILITY AND DEFINITIONS


This License applies to any manual or other work that contains a notice placed by the copyright
holder saying it can be distributed under the terms of this License. The "Document", below, refers to
any such manual or work. Any member of the public is a licensee, and is addressed as "you".
A "Modified Version" of the Document means any work containing the Document or a portion of it,
either copied verbatim, or with modifications and/or translated into another language.

A "Secondary Section" is a named appendix or a front-matter section of the Document that deals
exclusively with the relationship of the publishers or authors of the Document to the Document's
overall subject (or to related matters) and contains nothing that could fall directly within that overall

subject. (For example, if the Document is in part a textbook of mathematics, a Secondary Section
may not explain any mathematics.) The relationship could be a matter of historical connection with
the subject or with related matters, or of legal, commercial, philosophical, ethical or political position
regarding them.
The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those
of Invariant Sections, in the notice that says that the Document is released under this License.
The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or BackCover Texts, in the notice that says that the Document is released under this License.
A "Transparent" copy of the Document means a machine-readable copy, represented in a format
whose specification is available to the general public, whose contents can be viewed and edited
directly and straightforwardly with generic text editors or (for images composed of pixels) generic
paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to
text formatters or for automatic translation to a variety of formats suitable for input to text formatters.
A copy made in an otherwise Transparent file format whose markup has been designed to thwart or
discourage subsequent modification by readers is not Transparent. A copy that is not "Transparent" is
called "Opaque".
Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo
input format, LaTeX input format, SGML or XML using a publicly available DTD, and standardconforming simple HTML designed for human modification. Opaque formats include PostScript, PDF,
proprietary formats that can be read and edited only by proprietary word processors, SGML or XML
for which the DTD and/or processing tools are not generally available, and the machine-generated
HTML produced by some word processors for output purposes only.
The "Title Page" means, for a printed book, the title page itself, plus such following pages as are
needed to hold, legibly, the material this License requires to appear in the title page. For works in
formats which do not have any title page as such, "Title Page" means the text near the most
prominent appearance of the work's title, preceding the beginning of the body of the text.

A.3. VERBATIM COPYING


You may copy and distribute the Document in any medium, either commercially or noncommercially,
provided that this License, the copyright notices, and the license notice saying this License applies to
the Document are reproduced in all copies, and that you add no other conditions whatsoever to those
of this License. You may not use technical measures to obstruct or control the reading or further
copying of the copies you make or distribute. However, you may accept compensation in exchange
for copies. If you distribute a large enough number of copies you must also follow the conditions in
section 3.
You may also lend copies, under the same conditions stated above, and you may publicly display
copies.

A.4. COPYING IN QUANTITY

If you publish printed copies of the Document numbering more than 100, and the Document's license
notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all
these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover.
Both covers must also clearly and legibly identify you as the publisher of these copies. The front
cover must present the full title with all words of the title equally prominent and visible. You may add
other material on the covers in addition. Copying with changes limited to the covers, as long as they

preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in
other respects.
If the required texts for either cover are too voluminous to fit legibly, you should put the first ones
listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.
If you publish or distribute Opaque copies of the Document numbering more than 100, you must
either include a machine-readable Transparent copy along with each Opaque copy, or state in or with
each Opaque copy a publicly-accessible computer-network location containing a complete
Transparent copy of the Document, free of added material, which the general network-using public
has access to download anonymously at no charge using public-standard network protocols. If you
use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque
copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated
location until at least one year after the last time you distribute an Opaque copy (directly or through
your agents or retailers) of that edition to the public.
It is requested, but not required, that you contact the authors of the Document well before
redistributing any large number of copies, to give them a chance to provide you with an updated
version of the Document.

A.5. MODIFICATIONS
You may copy and distribute a Modified Version of the Document under the conditions of sections 2
and 3 above, provided that you release the Modified Version under precisely this License, with the
Modified Version filling the role of the Document, thus licensing distribution and modification of the
Modified Version to whoever possesses a copy of it. In addition, you must do these things in the
Modified Version:
A. Use in the Title Page (and on the covers, if any) a title distinct from that of
the Document, and from those of previous versions (which should, if there
were any, be listed in the History section of the Document). You may use the
same title as a previous version if the original publisher of that version gives
permission.
B. List on the Title Page, as authors, one or more persons or entities
responsible for authorship of the modifications in the Modified Version,
together with at least five of the principal authors of the Document (all of its
principal authors, if it has less than five).
C. State on the Title page the name of the publisher of the Modified Version, as
the publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modifications adjacent to the
other copyright notices.
F. Include, immediately after the copyright notices, a license notice giving the
public permission to use the Modified Version under the terms of this
License, in the form shown in the Addendum below.
G. Preserve in that license notice the full lists of Invariant Sections and
required Cover Texts given in the Document's license notice.

H. Include an unaltered copy of this License.

I. Preserve the section entitled "History", and its title, and add to it an item
stating at least the title, year, new authors, and publisher of the Modified
Version as given on the Title Page. If there is no section entitled "History" in
the Document, create one stating the title, year, authors, and publisher of
the Document as given on its Title Page, then add an item describing the
Modified Version as stated in the previous sentence.
J. Preserve the network location, if any, given in the Document for public
access to a Transparent copy of the Document, and likewise the network
locations given in the Document for previous versions it was based on.
These may be placed in the "History" section. You may omit a network
location for a work that was published at least four years before the
Document itself, or if the original publisher of the version it refers to gives
permission.
K. In any section entitled "Acknowledgements" or "Dedications", preserve the
section's title, and preserve in the section all the substance and tone of
each of the contributor acknowledgements and/or dedications given therein.
L. Preserve all the Invariant Sections of the Document, unaltered in their text
and in their titles. Section numbers or the equivalent are not considered part
of the section titles.
M. Delete any section entitled "Endorsements". Such a section may not be
included in the Modified Version.
N. Do not retitle any existing section as "Endorsements" or to conflict in title
with any Invariant Section.
If the Modified Version includes new front-matter sections or appendices that qualify as Secondary
Sections and contain no material copied from the Document, you may at your option designate some
or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the
Modified Version's license notice. These titles must be distinct from any other section titles.
You may add a section entitled "Endorsements", provided it contains nothing but endorsements of
your Modified Version by various parties--for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a standard.
You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words
as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage
of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made
by) any one entity. If the Document already includes a cover text for the same cover, previously
added by you or by arrangement made by the same entity you are acting on behalf of, you may not
add another; but you may replace the old one, on explicit permission from the previous publisher that
added the old one.
The author(s) and publisher(s) of the Document do not by this License give permission to use their
names for publicity for or to assert or imply endorsement of any Modified Version.

A.6. COMBINING DOCUMENTS

You may combine the Document with other documents released under this License, under the terms
defined in section 4 above for modified versions, provided that you include in the combination all of
the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant
Sections of your combined work in its license notice.

The combined work need only contain one copy of this License, and multiple identical Invariant
Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same
name but different contents, make the title of each such section unique by adding at the end of it, in
parentheses, the name of the original author or publisher of that section if known, or else a unique
number. Make the same adjustment to the section titles in the list of Invariant Sections in the license
notice of the combined work.
In the combination, you must combine any sections entitled "History" in the various original
documents, forming one section entitled "History"; likewise combine any sections entitled
"Acknowledgements", and any sections entitled "Dedications". You must delete all sections entitled
"Endorsements."

A.7. COLLECTIONS OF DOCUMENTS


You may make a collection consisting of the Document and other documents released under this
License, and replace the individual copies of this License in the various documents with a single copy
that is included in the collection, provided that you follow the rules of this License for verbatim
copying of each of the documents in all other respects.
You may extract a single document from such a collection, and distribute it individually under this
License, provided you insert a copy of this License into the extracted document, and follow this
License in all other respects regarding verbatim copying of that document.

A.8. AGGREGATION WITH INDEPENDENT WORKS


A compilation of the Document or its derivatives with other separate and independent documents or
works, in or on a volume of a storage or distribution medium, does not as a whole count as a
Modified Version of the Document, provided no compilation copyright is claimed for the compilation.
Such a compilation is called an "aggregate", and this License does not apply to the other selfcontained works thus compiled with the Document, on account of their being thus compiled, if they
are not themselves derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the
Document is less than one quarter of the entire aggregate, the Document's Cover Texts may be
placed on covers that surround only the Document within the aggregate. Otherwise they must appear
on covers around the whole aggregate.

A.9. TRANSLATION
Translation is considered a kind of modification, so you may distribute translations of the Document
under the terms of section 4. Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include translations of some or all Invariant
Sections in addition to the original versions of these Invariant Sections. You may include a translation
of this License provided that you also include the original English version of this License. In case of a
disagreement between the translation and the original English version of this License, the original
English version will prevail.

A.10. TERMINATION

You may not copy, modify, sublicense, or distribute the Document except as expressly provided for
under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void,
and will automatically terminate your rights under this License. However, parties who have received

copies, or rights, from you under this License will not have their licenses terminated so long as such
parties remain in full compliance.

A.11. FUTURE REVISIONS OF THIS LICENSE


The Free Software Foundation may publish new, revised versions of the GNU Free Documentation
License from time to time. Such new versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number. If the Document specifies that a
particular numbered version of this License "or any later version" applies to it, you have the option of
following the terms and conditions either of that specified version or of any later version that has been
published (not as a draft) by the Free Software Foundation. If the Document does not specify a
version number of this License, you may choose any version ever published (not as a draft) by the
Free Software Foundation.

A.12. How to use this License for your documents


To use this License in a document you have written, include a copy of the License in the document
and put the following copyright and license notices just after the title page:
Copyright (c) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License, Version 1.1 or any later version
published by the Free Software Foundation; with the Invariant Sections being LIST THEIR TITLES,
with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. A copy of the
license is included in the section entitled "GNU Free Documentation License".
If you have no Invariant Sections, write "with no Invariant Sections" instead of saying which ones are
invariant. If you have no Front-Cover Texts, write "no Front-Cover Texts" instead of "Front-Cover
Texts being LIST"; likewise for Back-Cover Texts.
If your document contains nontrivial examples of program code, we recommend releasing these
examples in parallel under your choice of free software license, such as the GNU General Public
License, to permit their use in free software.

_______________________________________________

You might also like