SemWeb Documentation

Reading RDF

Reading RDF files is pretty easy so here are a few examples.

This loads an RDF/XML file into a MemoryStore:

MemoryStore store = new MemoryStore();
store.Import(new RdfXmlReader("data.rdf"));

This loads a N-Triples, Turtle, or Notation 3 file into a store:

store.Import(new N3Reader("data.n3"));

This loads a RDF file from the web:

store.Import(RdfReader.LoadFromUri(new Uri("http://www.mozilla.org/news.rdf")));

LoadFromUri will determine the format of the file (XML or N3) based on the MIME type sent back from the server, or if that fails, the file extension.

You don't have to put the contents of a file into memory. All of the RdfReaders are "streaming", which means it doesn't need to load the entire file before getting statements out of it. The reader can stream statements to a "sink" as soon as each is read.

In fact, readers are one type of StatementSource. StatementSources provide a Select method which streams statements to a StatementSink, providing a corresponding Add method.

Stores are one type of sink. You saw the MemoryStore's Add method in the last tutorial.

The following is pretty much equivalent to the code above:

RdfReader webrdf = RdfReader.LoadFromUri(new Uri("http://www.mozilla.org/news.rdf"));
webrdf.Select(store);

For a MemoryStore, there is no difference. Other stores may override Import with transaction or locking mechanics to speed up the process of loading a large data file.

By creating your own sink, you can process statements in a streaming way:

class StatementPrinter : StatementSink {
    public bool Add(Statement assertion) {
        Console.WriteLine(assertion.ToString());
        return true;
    }
}

This class implements a sink that simply prints out each statement to the console as each statement is received. It returns true to indicate to the source to continue. Returning false would end the streaming.

The Statement type is a struct that contains three fields: Subject, Predicate, and Object (actually it contains a Meta field too). Since RDF statements only have entities as subjects and predicates, the first two fields are typed as Entity, while the last field is typed as Resource. If you want to access the URIs and literal values within the statement, you might write something like this:

Console.WriteLine("Subject: " + assertion.Subject.Uri);
Console.WriteLine("Predicate: " + assertion.Predicate.Uri);
if (assertion.Object is Entity)
    Console.WriteLine("Object: " + ((Entity)assertion.Object).Uri + " (it's an entity)");
else
    Console.WriteLine("Object: " + ((Literal)assertion.Object).Value + " (it's a literal)");

Of course, beware that BNodes are entities without URIs, and the Uri property will return null in that case.

To stream the statements from the web directly to the custom sink, use:

webrdf.Select(new StatementPrinter());

There's one final twist. Stores, as I mentioned, are a type of sink, letting you stream statements into them. They are simultaneously a type of source! This lets you stream statements out of them too, just as you stream statements out of the RdfXmlReader and into your own class.