All() does not return literal objects, but it does return predicates. Technically, the underlying RDF implementation determines what is considered to be a resource for Versa purposes, but any compliant. RDF processor would return the above as all the known resources specified in wordnet.rdf, according to standard RDF 1.0 rules. The support and presence of RDF schemata, could, of course, change what objects are considered resources and literals based on applicable declarations.

Lesson 1.2

Let us get the label of all resources that have one. We'll do this using a traversal expression,

all()-rdfs:label->*

rdfs:label is a resource. Versa allows you to express resources in an abbreviated form that should be familiar to RDF users: the URI of the resource is broken into two parts, and the first part is mapped to a namespace prefix, in this case "rdfs". The abbreviation form consists of the namespace prefix and the latter part of the URI joined by a colon. This is similar to a "QName" from XML.

Traversal expressions are a core feature of Versa. They allow you to match patterns in the model, by analogy to their structure as directed graphs. The above traversal expression is a forward traversal expession, with an expression that yields a set of subjects, one that yields a set of predicates. A set of statements is gathered: all statements whose subject is in the subject set and whose predicate is in the predicate set. The last expression acts as a filter, taking the object from each statement set, and using it as the context for evaluation. If the result of this evaluation is boolean true (after any necessary conversions), the object is added to the result set.

To reiterate: this means that the result set comes from the *objects* of statements matching the traversal expression.

I only specify a single resource for the predicate (rdfs:label), but this is OK, as it is converted to a Set of length 1 automatically by Versa.

From now on we'll display the results without reference to the 4versa command line. You should expect the same structure of results from any Versa engine, although they may not be presented in the same XML form as 4versa uses, or they may not be in XML at all.

Lesson 1.3

I can make my criteria more sophisticated. For instance, to get only values whose label is "Web [ 1 ]", I can replace the catch-all "*" with an equality check:

Of course, in such cases, what I usually want are the resource that are subjects of matching statements rather than the objects. See lesson 9 for how to retrieve the subjects instead.

Lesson 1.4

But actually, the above will get the label of all all resources in the model that have one. If I want to restrict it to resource of type rdfs:Class that have labels, I could write

(rdfs:Class <- rdf:type - *) - rdfs:label -> *

This uses a chained traversal expression, one backward, and one forward. Let's take a quick look at the backward traversal:

rdfs:Class <- rdf:type - *

This is similar to the forward traversal, but it starts with a set of objects. The second expression is a set of predicates, and the third is still a filtering expression that is evaluated on all the partial results of statements matching the subject and predicate set. The filter is applied with each subject as context, and if true, the subject is added to the result set.

So if you can think of the forward traversal as moving along the specified arcs from subjects to objects, and then filtering the result, think of a backward traversal as moving *against* the specified predicates from objects to subjects, and then filtering the subjects.

The result of the first traversal becomes the subject set of the second one.

It will help to make this process clear if you follow this movement on the graph of my sample model.

Lesson 1.6

But what if I want to do the same thing, but I want the label *and* the description? I can retrieve the list of resources of interest, and then use the distribute function to compute subexpressions over each:

The distribute function takes 2 or more aruments. The result of the first argument is converted to a list (the source list). Each item in the list is take in turn, and treated as context. The second and following arguments are each converted to a string, which is parsed as a Versa sub-query (a dynamic expression) and evaluated with this context. The result of the distribute function is a list of lists. The outer list is as long as the list given by the first argument. Each inner list contains the results of evaluating each item in the initial list against the dynamic expressions.

The filter function takes 2 or more arguments. The first one is converted to a list (the source list). Each item in this list is used as the context in evaluating the dynamic expressions given by the second and subsequent arguments. The result of each dynamic expression is converted to boolean and the result is a list of each item from the source list that produces a true result when applied against all the dynamic expression.

Lesson 1.8

I can easily look up a particular resource, using a traversal expression. Let us get the description of one of the resources:

<http://xmlns.com/wordnet/1.6/Object> - rdfs:description -> *

One can't always use an abbreviated resource literal. Versa allows you to spell out the entire URL of the resource: @"http://xmlns.com/wordnet/1.6/Object". The part between the quotes must be a valid URI, and the literal represents the resource with that URI. In this case, I could also have used an abbreviated form, such as wn:Object.

Result:

#!EXPECTED
<List>
<String>a physical (tangible and visible) entity; "it was full of rackets, balls and other objects"</String>
</List>

Lesson 1.9

So far I have obtained the objects of statements in traversal expressions, but often what I want are the subjects of matching statements. Versa provides filter expressions, which are similar to traversal expressions, but which return subjects rather than objects.

For example, to get all resources with a label of "Web [ 1 ]", I can use the following:

Lesson 2.4

I can also traverse properties transitively. In for instance, if I wanted to get all ancestors of Uche Ogbuji, I need to transitively traverse father and mother relationships. I can do so using a special long-hand form of the traversal expression: the traverse function. Notably, this function also allows us to specify arguments, including the transitivity of the traversals:

traverse(<#uogbuji>, set(o:mother, o:father))

returns a similar result to that of:

<#uogbuji> - set(o:mother, o:father) -> *

The traverse function takes a set of subjects and predicates to be matched in the model. The objects of all statements matching one of the given subjects and predicates are returned.

Hmm. Perhaps this is not quite what I want. I get one copy of each resource for each of its properties. One way to fix this is to convert the resulting list to a set, which will eliminate the duplicates (and destroy any ordering).