[rdfweb-dev] Subject: Schema-Aware FOAF Editor

Sean B. Palmer sean at mysterylights.com
Wed Oct 15 15:34:34 UTC 2003

[Recommendations on augmenting the FOAF 0.1 schema below.]

Further to Danny's little-RDF-serialization email [1], I worked on a
few ideas to see what the easiest way of entering RDF data on the
command line is. It occured to me that since schemata can provide
domain and range constraints, we might as well use them in an editor.

When combined with path searching for classes and properties à la
$PATH and $CDPATH in bash, qnames, and some other features described
below, it makes for a very intuitive data-input environment.

Straight off, here's an example:

$ python rdfe.py
RES> Person
foaf:Person PROP> name
_ foaf:name LIT> Sean B. Palmer
_ PROP> knows
_ foaf:knows RES> Person
   _ PROP> name
   _ foaf:name LIT> Libby Miller
   _ PROP>
_ PROP> homepage
_ foaf:homepage RES> http://purl.org/net/sbp/

There's quite a lot going on in this short example. The only things
that I entered come after the first "...>" prompt in each line--all
the rest is context data given out by the program.

First of all, what you can't see in the example above is that before
you can use the editor, it asks you for some schemata to use. I fed it
the RDF, RDFS, OWL, FOAF, and DC schemata, merged them, and then
applied the rdfs-closure rules. There were 1044 statements before
applying the rules, and 2096 after. It then saves the results locally
to a file so that it doesn't have to download from the Web and do the
reasoning again every time it loads (it takes a while!).

When initialized with the schema already loaded, as in the example
above, it'll prompt for a particular type of data to be entered: RES>
for a resource, LIT> for a literal, or PROP> for an rdf:Property
instance. It prompts me for a subject with the type of RES first of
all, so I give it "Person".

   RES> Person

It looks through its path, which at the moment is set to
"rdf:rdfs:owl:foaf:dc". The problem with searching through paths is
that if, for example, RDF suddenly sprouted an rdf:name property, I'd

be flummoxed when entering "name" in and getting it to path-search. @@
It should therefore be possible to change the current subject or
predicate in the editor.

So the subject is initially set to foaf:Person. Now it shows what the
current subject is in the prompt, and asks me for a PROP to apply. I
give it "name", which it resolves to foaf:name.

   foaf:Person PROP> name

Now for the first clever bit. It looks at the schemata, and sees that
I declared a couple of things in my local editorial schema: "foaf:name
rdfe:domain foaf:Person . foaf:Person rdfe:disjointWith rdfs:Class ."
Note that I've used rdfe: instead of rdfs: and owl:, since these
constraints aren't actually in the FOAF schema. What I'm saying is
that locally, for this editor, I will only ever use foaf:name on
foaf:Person instances, and that foaf:Person is disjoint with

Upon seeing this information, the editor decides that "foaf:Person
foaf:name" is not a valid start to a triple, and so it decides that
what I really meant is "_:person rdf:type foaf:Person . _:person
foaf:name" and accordingly makes the typed statement and resets the
subject to be a bNode. It represents bNodes using the "_"
(underscore), as shown in the next prompt:

   _ foaf:name LIT> Sean B. Palmer

Note here that it also automatically knows that the object of
foaf:name is an rdfs:Literal, and so it prompts for LIT> instead of
RES>. This means that I don't have to use <> for URIs and "" for
Literals, since it should automatically decide.

Aside: note that rdfs:Literal is a subClassOf rdfs:Resource... so
there's a minor problem there, though I'm resolving that at the moment
by saying that if there's only rdfs:Literal in the range of the
property, prompt for LIT>, if there's both, I could probably guess
what's meant by using some heuristic (e.g. if the entered object
contains a space, then it's a literal), and if there's no rdfs:Literal
in the property ranges, prompt for RES>.

Now it asks for another property, and I give it knows. I then say that
I know a person.

   _ PROP> knows
   _ foaf:knows RES> Person
      _ PROP> name

Again, more reasoning: the range of foaf:knows is foaf:Person, so it
creates a new subject and types it as being a Person instead of using
Person itself as the object. It then says that I know this new
subject. To show that we've moved into the graph a bit further, as it
were, it indents. So I'm now entering properties for the Person that I
foaf:know. I add a name arc.

      _ foaf:name LIT> Libby Miller
      _ PROP>
   _ PROP> homepage

I give it libby's name, and then enter nothing as a property. Entering
nothing as a property makes it go up to the previous level. So now I'm
back to entering in properties about myself. I bung in homepage, and
it correctly guesses foaf:homepage and prompts for a resource.

   _ PROP> homepage
   _ foaf:homepage RES> http://purl.org/net/sbp/
   _ PROP>

I gave it a blank property and blank subject resource to exit the
program. I've also been experimenting with commands, which start with
"@" (an at-sign), so I could enter @quit to quit, @subj to view the
current subject in full, and so on.

Just before the program quits, it pipes out the N-Triples of the
result to STDOUT. All of the prompts are on STDIN. Here's what I got
for the example above, using QNames to make it readable:

_:NRKRkBbM rdf:type foaf:Person .
_:NRKRkBbM foaf:name "Sean B. Palmer" .
_:NRKRkBbM foaf:knows _:LDzZyLRa .
_:LDzZyLRa rdf:type foaf:Person .
_:LDzZyLRa foaf:name "Libby Miller" .
_:NRKRkBbM foaf:homepage <http://purl.org/net/sbp/> .

Here's another example:

$ python rdfe.py
RES> Person
foaf:Person PROP> name
_ foaf:name LIT> Sean B. Palmer
_ PROP> mbxo
Not found: mbxo
_ PROP> mbox
_ foaf:mbox RES> mailto:sean at mysterylights.com
_ PROP> weblog
_ foaf:weblog RES> http://miscoranda.com/
RES> http://miscoranda.com/
+ PROP> label
+ rdfs:label LIT> miscoranda

The new features of note here are a) if it can't find a property in
the current schemata, it says so, and b) "+" (plus-sign) is used to
denote a URI as a subject. I'm glad it guessed that rdfs:label was a
literal straight off, since it meant I didn't have to add it to my
local.nt schema and rebuild the whole lot.

In making the editor, I came across a number of issues, many with FOAF
since that's what I've been using to test it generally (and what I
think it'll be most useful for--it's what Danny's original example was

The first issue is that auto-discovery of the FOAF schema is hard,
because it's embedded in the HTML. I had to write something to extract
the rdf:RDF from there, and it's all regexp based, of course. Plus, if
you want the charset of the embedded RDF, you have to parse it out of
the HTML MIME type header, or from http-equiv, which is really horky.
I could've sent accept: application/rdf+xml, but the rdf:RDF in the
HTML specification is more up-to-date.

So I don't believe that embedding the schema in the HTML is a good
idea. If it were <link>'d, as recommended, it would have solved the
regexp problem (what happens if there's "</rdf:RDF>" in a literal?),
and the charset problem. I suggest that the specification be changed
to use that method.

   <link rel="meta"
         href="index.rdf" />

Secondly, there are some things missing from the schema. I already
pinged danbri on #foaf about adding rdfs:Resource as a domain for
foaf:name (actually, I was wanting foaf:Agent or foaf:Person, but oh
well--I just added it to my local schema), but foaf:nick is also
missing rdfs:Literal as a range.

The source for rdfe.py isn't available online yet since it uses my
as-yet-unreleased RDF API. If you want to play around with it, email
me and I'll send it over. You'll need Python 2.3 installed, and a lot
of determination...

Perhaps if there are enough requests, I'll release the API :-)

I'm sure that the editor could have many more features, and that it's
actually not all that useful, and there are probably GUI schema-aware
RDF editors already that are much better, so I'd be interested to hear
about any parallel research or feature requests.

As my colophon, I'd like to note that I've been doing this
schema-aware via RDFS-Closure sort of stuff for a couple of years now,
and that for me it's quite a pointer to how RDF can actually be
useful. My previous experiments were in validating RDF, which I found
useful in debugging the EARL schema.

Oh, and I really like the definition of foaf:Agent in the
specification: "things that do stuff" :-)


[1] http://rdfweb.org/pipermail/rdfweb-dev/2003-October/012056.html

Sean B. Palmer, <http://purl.org/net/sbp/>
"phenomicity by the bucketful" - http://miscoranda.com/

More information about the foaf-dev mailing list