1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
<html>
<head>
<title>SemWeb: Docs: Selecting Statements</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css"/>
</head>
<body>
<p><a href="index.html">SemWeb Documentation</a></p>
<h1>Selecting Statements</h1>
<h2>Using statement templates</h2>
<p>In the previous tutorial you saw the <tt>Select</tt> method of <tt>StatementSource</tt>s, 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.)</p>
<p>A template is a <tt>Statement</tt> but with subject, predicate, and object possibly <tt>null</tt>. <tt>null</tt>s are wildcards. So here are a few examples:</p>
<pre class="code">
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
</pre>
<p>The sink can be any <tt>StatementSink</tt>. This includes <tt>RdfWriters</tt>, which would let
you write out just a part of a store to a file, and <tt>Stores</tt> like the <tt>MemoryStore</tt>
so that you can move statements between data sources.</p>
<p>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:</p>
<pre class="code">
foreach (Resource r in store.SelectObjects(person, foafname))
Console.WriteLine("His name is: " + r);
</pre>
<p>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:</p>
<pre class="code">
foreach (Statement statement in store.Select(new Statement(null, rdftype, foafPerson))) {
...
}
</pre>
<p>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.</p>
<p>These convenience methods are only provided in the <tt>Store</tt> class and its subclasses.
If you want to use them on data from a file or other data source that doesn't extend <tt>Store</tt>,
load the data into a <tt>MemoryStore</tt>:</p>
<pre class="code">
Store store = new MemoryStore();
store.Import(RdfReader.LoadFromUri(new Uri("http://dannyayers.com/misc/foaf/foaf.rdf")));
</pre>
<p>Here's an example program that loads a FOAF document and extracts some information using Select:</p>
<pre class="code" file="../examples/select.cs">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();
}
}
</pre>
<h2>Other notes</h2>
<p>RDF collections, like Bag, Alt, and Seq, in RDF/XML use a strange
<tt>rdf:li</tt> pseudo-property. <tt>rdf:li</tt> isn't actually a
property. It is an abbreviation for <tt>rdf:_1</tt>, <tt>rdf:_2</tt>,
etc. in that order. Thus when you select for members of a collection,
you can't use <tt>rdf:li</tt>. However, RDFS defines the property
<tt>rdfs:member</tt> which <tt>rdf:_##</tt> properties are all
subproperties of. The SemWeb stores all recognize the <tt>rdfs:member</tt>
predicate and will match it to any of the <tt>rdf:_##</tt> predicates.<p>
<p>In addition, the <tt>SelectObjects</tt> method of the <tt>Store</tt>
class will automatically sort the objects by their collection order,
where possible, when you call the method with the <tt>rdfs:member</tt> predicate.</p>
<p>Here's an example of that:</p>
<pre class="code" file="../examples/containers.cs">// 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);
}
}
</pre>
</body>
</html>
|