This documentation describes version 0.85 of SemWeb.
To get started, you should use the pre-compiled binaries provided in the download package. These are located in the bin directory. You will need to reference SemWeb.dll in all of the examples.
The documentation is split into several pages:
In the previous tutorial you saw the Select method of StatementSources, which streams all of the statements into a sink. The name "Select" was derived from SQL syntax, where it's used to retrieve rows that match a criteria. In SemWeb, Select is used to retreive statements matching a filter. (And as with SQL, when no criteria is given all statements are retrieved.)
A template is a Statement but with subject, predicate, and object possibly null. nulls are wildcards. So here are a few examples:
store.Select(sink); // selects all statements, streaming them into sink store.Select(new Statement(null, null, null), sink); // the same store.Select(Statement.All, sink); // the same, but shorthand store.Select(new Statement(subj, null, null), sink); // any statement with that particular subject entity store.Select(new Statement(subj, pred, null), sink); // any statement with that particular subject and predicate store.Select(new Statement(subj, pred, obj), sink); // just that statement, if it exists in the store
The sink can be any StatementSink. This includes RdfWriters, which would let you write out just a part of a store to a file, and Stores like the MemoryStore so that you can move statements between data sources.
Stores provide a few convenience methods. Two methods are provided for getting all of the subjects found with a given predicate and object, and similarly all objects found with a given subject and predicate. This can be used to move around in a graph:
foreach (Resource r in store.SelectObjects(person, foafname))
Console.WriteLine("His name is: " + r);
Other convenience methods are overrides of Select that rather than sending the results to a sink, load them into memory so that you may for-each over them:
foreach (Statement statement in store.Select(new Statement(null, rdftype, foafPerson))) {
...
}
You obviously shouldn't use these on data sources of unbounded size as you wouldn't necessarily want to load the results all into memory.
These convenience methods are only provided in the Store class and its subclasses. If you want to use them on data from a file or other data source that doesn't extend Store, load the data into a MemoryStore:
Store store = new MemoryStore();
store.Import(RdfReader.LoadFromUri(new Uri("http://dannyayers.com/misc/foaf/foaf.rdf")));
Here's an example program that loads a FOAF document and extracts some information using Select:
using System;
using SemWeb;
public class Select {
const string RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
const string FOAF = "http://xmlns.com/foaf/0.1/";
static readonly Entity rdftype = RDF+"type";
static readonly Entity foafPerson = FOAF+"Person";
static readonly Entity foafknows = FOAF+"knows";
static readonly Entity foafname = FOAF+"name";
public static void Main() {
Store store = new MemoryStore();
store.Import(RdfReader.LoadFromUri(new Uri("http://dannyayers.com/misc/foaf/foaf.rdf")));
Console.WriteLine("These are the people in the file:");
foreach (Statement s in store.Select(new Statement(null, rdftype, foafPerson))) {
foreach (Resource r in store.SelectObjects(s.Subject, foafname))
Console.WriteLine(r);
}
Console.WriteLine();
Console.WriteLine("And here's RDF/XML just for some of the file:");
using (RdfWriter w = new RdfXmlWriter(Console.Out)) {
store.Select(new Statement(null, foafname, null), w);
store.Select(new Statement(null, foafknows, null), w);
}
Console.WriteLine();
}
}
RDF collections, like Bag, Alt, and Seq, in RDF/XML use a strange rdf:li pseudo-property. rdf:li isn't actually a property. It is an abbreviation for rdf:_1, rdf:_2, etc. in that order. Thus when you select for members of a collection, you can't use rdf:li. However, RDFS defines the property rdfs:member which rdf:_## properties are all subproperties of. The SemWeb stores all recognize the rdfs:member predicate and will match it to any of the rdf:_## predicates.
In addition, the SelectObjects method of the Store class will automatically sort the objects by their collection order, where possible, when you call the method with the rdfs:member predicate.
Here's an example of that:
// This example deals with RDF containers. You can use the rdfs:member
// property to match any rdf:_### (i.e. rdf:li) property. Or,
// use SelectObjects on the Store, which will return the items
// in sorted order.
using System;
using SemWeb;
public class Containers {
const string RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
const string RDFS = "http://www.w3.org/2000/01/rdf-schema#";
public static void Main() {
MemoryStore store = new MemoryStore();
Entity container = new Entity("http://www.example.org/#container");
store.Add(new Statement(container, RDF+"type", (Entity)(RDF+"Bag")));
store.Add(new Statement(container, RDF+"_3", (Literal)"Three"));
store.Add(new Statement(container, RDF+"_2", (Literal)"Two"));
store.Add(new Statement(container, RDF+"_1", (Literal)"One"));
// use the rdfs:member property to match for any rdf:_### predicates.
Entity rdfs_member = (Entity)(RDFS+"member");
using (RdfWriter writer = new N3Writer(Console.Out)) {
writer.Namespaces.AddNamespace(RDF, "rdf");
store.Select(new Statement(container, rdfs_member, null), writer);
}
foreach (Resource r in store.SelectObjects(container, rdfs_member))
Console.WriteLine(r);
}
}
semweb-1.05+dfsg/doc/readingrdf.html 0000644 0001750 0001750 00000007423 10774502134 016707 0 ustar meebey meebey
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.
semweb-1.05+dfsg/doc/selectfilter.html 0000644 0001750 0001750 00000004604 10774502134 017265 0 ustar meebey meebeyFor anything but the MemoryStore, there is considerable overhead in each request for information from an underlying database. With the MySQL store, for instance, a call to Select makes a SQL SELECT query on the database. There is overhead in constructing, transmitting across processes, and parsing the query, and then the response. This makes repeated calls to Select (the method) much slower than they should be if they could be combined into a single SQL SELECT.
SemWeb has an advanced API call, an overload of Select, taking a SelectFilter argument, which allows the caller to query for statements matching a more complex filter than the simple form of Select. In the simple form, the subject, predicate, object, and meta can be either 1) specified or 2) a wildcard. In the more complex API, there is a third option, which is specifying a range of possible values. Schematically, these three calls to select:
Select(X, null, null) Select(Y, null, null) Select(Z, null, null)
can be replaced with a single call like this:
Select( { X, Y, Z}, null, null);
Further, these permutations can be condensed into a single call:
Select(X, A, null)
Select(Y, A, null)
Select(Z, A, null)
Select(X, B, null)
Select(Y, B, null)
Select(Z, B, null)
Select(X, C, null)
Select(Y, C, null)
Select(Z, C, null)
Select( { X, Y, Z}, { A, B, C}, null);
The statements returned from the complex Select are those that match any of the provided resources.
The actual syntax uses arrays of entities or, for objects, resources. As an example, one use case of this is to fetch the foaf:name of many entities in one call.
SelectFilter filter = new SelectFilter(); // for now all wildcards
filter.Subjects = new Entity[] { X, Y, Z };
filter.Predicates = new Entity[] { foaf_name };
// filter.Objects, filter.Metas are left as wildcards
store.Select(filter, sink);
The sink receives all statements whose subject is X, Y, or Z, and whose predicate is foaf_name.