Hi Ben,
I've written and re-written the following post umpteen times, over
the last month or so. :) Finally, I've decided that the best way to
break this down is to explain why I disagree with your approach, and
then separately to spell out the extra couple of rules we need to
make your use-cases work. All attempts I've made to mix the two have
been even longer than this email...and as you can see below, this
shortened version is still pretty long!
So, here goes...
You wrote:
Manu wanted me to express my proposed @instanceof rules in a way
similar
to what he recently posted [1], so that we could compare.
The main driver for my rules is to make it easy for @instanceof to be
used on chaining nodes, so that one can say "I know a person named
'Ralph'", or even the more complicated "I know a person who knows a
person who knows a person named 'Bill'".
The statements:
I know a person named 'Ralph'
and:
I know a person who knows a person who knows a person named 'Bill'
were both always possible in earlier versions of RDFa, and in my
view, in a way that is simpler than in your proposal. So before I go
into that, some context.
CONTEXT
What I believe has happened is this; chaining was removed from RDFa
in the first draft that was produced within the taskforce, because
it was deemed too complicated. After a while--and probably many use-
cases :) --you proposed the idea that @href, @src, etc., should set
the subject of contained statements, which was both an insightful
idea, and effectively a 'reintroduction' of chaining. :)
However, there are a number of other aspects to chaining that need
to be 'reintroduced' if we are to make it completely consistent, and
I think it is the lack of these that makes your proposal not quite
hang together (in my view). I don't think I can explain them all in
this posting, but what I do think is important to do first--which I
will do here--is to explore the problems with your 'rules', and to
look at why I think they create unnecessary inconsistencies with
attribute behaviour, without any gain.
(Sorry to put it so bluntly!)
CONSISTENCY
I'll begin with your first statement, that:
I know a person called Ralph
To indicate this, if we had all of the 'old' chaining rules in RDFa,
then *any* of the following constructs could be used:
========
<div about="#me">
<div rel="foaf:knows">
<div instanceof="foaf:Person">
<span property="foaf:name">Ralph</span>
</div>
</div>
</div>
========
========
<div about="#me">
<div rel="foaf:knows">
<span property="foaf:name" instanceof="foaf:Person">Ralph</span>
</div>
</div>
========
========
<div about="#me" rel="foaf:knows">
<div instanceof="foaf:Person">
<span property="foaf:name">Ralph</span>
</div>
</div>
========
========
<div about="#me" rel="foaf:knows">
<span property="foaf:name" instanceof="foaf:Person">Ralph</span>
</div>
========
Note the consistency as the mark-up is expanded and contracted--by
which I mean that elements are added and removed--the rules always
stay the same, regardless of the presence of other attributes. In
fact, if you removed the _elements_ and left behind only the
attributes, every single one of these constructs results in the same
structure:
about="#me"
rel="foaf:knows"
{bnode}
instanceof="foaf:Person"
property="foaf:name"
content="Ralph"
This is obviously desirable, and is no accident.
Before I look at your rules in more depth, Ben, I'd like to continue
to demonstrate the consistency of the 'complete' set of chaining
rules that we used to have (which as I said, I'll go into in another
thread). We'll take as our starting-point the last piece of mark-up,
i.e., this one:
========
<div about="#me" rel="foaf:knows">
<span property="foaf:name" instanceof="foaf:Person">Ralph</span>
</div>
========
and use it as a base from which to build up to your more complicated
scenario:
I know a person who knows a person who knows a person named 'Bill'
However, let's make the example slightly more realistic, by adding
more information--we'll give each of the people down the chain a
name, as follows:
I know a person named 'Ralph', who knows a person named 'Ivan', who
knows a
person named 'Bill'
Having established where we're heading, we need to do one last minor
piece of preparation, and that is to slightly reorganise the mark-up
so that we use @content instead of an inline literal; this makes the
examples easier to read as they get more complex, and of course, it
makes it easier to 'nest' elements, one inside the other.
So, our first statement, from which we will build up, now looks like
this:
========
<div about="#me" rel="foaf:knows">
<span
instanceof="foaf:Person"
property="foaf:name" content="Ralph"
>
</span>
</div>
========
The next step is to simply cut-and-paste Ralph (painless, I hope),
in order to create a third person that looks exactly like the second
one, but with the name value set to 'Ivan':
========
<div about="#me" rel="foaf:knows">
<span
instanceof="foaf:Person"
property="foaf:name" content="Ralph"
>
<span
instanceof="foaf:Person"
property="foaf:name" content="Ivan"
>
</span>
</span>
</div>
========
Note that the only difference between this 'person' and the one we
already had was that @content is set to 'Ivan' instead of 'Ralph',
but the structure is exactly the same.
Once we've added this extra 'person' item, all we should have to do
is to add an additional predicate to the second item (i.e., Ralph),
to indicate the relationship between the two people:
========
<div about="#me" rel="foaf:knows">
<span
instanceof="foaf:Person"
property="foaf:name" content="Ralph"
rel="foaf:knows"
>
<span
instanceof="foaf:Person"
property="foaf:name" content="Ivan"
>
</span>
</span>
</div>
========
As you can see, the only difference between the mark-up that
expressed two _unconnected_ people (i.e., the previous step), and
the mark-up that has two _connected_ people, is at line 5; it is
there that we have added the extra predicate to the second item
(Ralph) that indicates a relationship with the third item (Ivan).
The first thing that is important here--although the significance is
probably quite obvious--is the way that I created the 'inner' item
by cutting-and-pasting an item from elsewhere; the consistency of
the language means that you can just 'drop' items from different
places into position. In addition, we can keep adding child
elements, getting deeper and deeper, as much as we like.
The second thing that is worth noting is that adding the @rel to
establish the relationship between the two items is nothing more
than adding a predicate to an item, and so does not change that item
in any way. I'll say more on this below, but at this point the key
thing to note is that adding and removing the @rel only changes the
relationship between the items, and changes nothing about the item
itself.
Anyway, let's continue, and finish your more complex scenario; we
need to add:
Ivan knows a person called 'Bill'
As before, first we add a self-contained 'person' item:
========
<div about="#me" rel="foaf:knows">
<span
instanceof="foaf:Person"
property="foaf:name" content="Ralph"
rel="foaf:knows"
>
<span
instanceof="foaf:Person"
property="foaf:name" content="Ivan"
>
<span
instanceof="foaf:Person"
property="foaf:name" content="Bill"
>
</span>
</span>
</span>
</div>
========
and then, as before, we add the relationship between Ivan and Bill:
========
<div about="#me" rel="foaf:knows">
<span
instanceof="foaf:Person"
property="foaf:name" content="Ralph"
rel="foaf:knows"
>
<span
instanceof="foaf:Person"
property="foaf:name" content="Ivan"
rel="foaf:knows"
>
<span
instanceof="foaf:Person"
property="foaf:name" content="Ben"
>
</span>
</span>
</span>
</div>
========
SUMMARY OF POSITION
Now, hopefully what's obvious after having carried out the same
process twice is that:
* the attributes behave consistently;
* @instanceof always applies to the subject on an element (possibly
a bnode), and not the object.
In this, therefore, it does not differ from the setting of any
other predicate;
* items can be easily cut from one document and dropped into
another, as self-contained
building-blocks that stand in relation to other items;
* adding a relationship between one item and another does not change
anything about the items.
I think all of these are important arguments, and each of them
presents a strong case against making @instanceof behave in the way
that you want, Ben. But I think the most significant is the last,
which I mentioned earlier, and said I'd return to.
ESTABLISHING A RELATIONSHIP SHOULDN'T
CHANGE AN ITEM'S MEANING
So, to illustrate what I mean by saying that 'adding a relationship
changes the meaning of the items', let's rewind to the beginning of
my steps, and this time we'll use your rules instead of my 'old'
RDFa rules. Also, since I'm not 100% certain that we agree on the
meaning of the mark-up I've used as my starting-point, I've scoured
all the discussions for a piece of mark-up that both sets of rules
agree on, and found this (the initial comment is yours, just to put
the mark-up into context):
"And if you wanted to declare #me a foaf:Person, you would write it
with two elements:
<div about="#me" instanceof="foaf:Person">
<div rel="foaf:knows">
<span property="foaf:name">Ralph</span>
</div>
</div>"
I think we agree that in both sets of rules this snippet means:
I am a person who knows something named 'Ralph'
As before I'll use @content to make things easier to read, giving us
this:
========
<div about="#me" instanceof="foaf:Person">
<div rel="foaf:knows">
<span property="foaf:name" content="Ralph">
</span>
</div>
</div>
========
Now, we're ready to proceed pretty much as before.
Let's say that Ralph knows Ivan; we know that Ivan can be identified
by "http://www.w3.org/People/Ivan/#me", so it should be pretty
straightforward to add @rel="foaf:knows", as follows:
========
<div about="#me" instanceof="foaf:Person">
<div rel="foaf:knows">
<span
property="foaf:name" content="Ralph"
rel="foaf:knows" href="http://www.w3.org/People/Ivan/#me"
>
</span>
</div>
</div>
========
This inner element is quite a nice, self-contained block. At the
moment it could be passed around from one document to another in its
self-contained form:
========
<span
property="foaf:name" content="Ralph"
rel="foaf:knows" href="http://www.w3.org/People/Ivan/#me"
>
</span>
========
No matter where it appears it should mean the same thing--this is
the 'cut-and-paste' point I made earlier.
But what if we want this self-contained block to also indicate that
Ralph is a person? In earlier versions of RDFa we could have added a
child <link>, as follows:
========
<span
property="foaf:name" content="Ralph"
rel="foaf:knows" href="http://www.w3.org/People/Ivan/#me"
>
<link rel="rdf:type" resource="[foaf:Person]" />
</span>
========
However, as we know, due to browser limitations we've had to remove
this feature--the rule that allows '<link> and <meta> everywhere--
from the current version of RDFa , although it is still present in
XHTML 2's use of RDFa.
There was an additional design principle, though, that <link> as a
child element was actually a longhand version of adding an attribute
to the element, so the previous mark-up *should be* the same as this:
========
<span
property="foaf:name" content="Ralph"
rel="foaf:knows" href="http://www.w3.org/People/Ivan/#me"
instanceof="foaf:Person"
>
</span>
========
That's a slight diversion, but essentially my point is that since
@instanceof is the renamed @class, and @class was always understood
to be a shorthand for a child <link> element, then it is easy to see
why the type and all predicates should be applied to the same
subject. (And conversely, it is a very big leap to suggest that
instead we should apply @instanceof to the _object_ rather than the
_subject_, since there is nothing in the general architecture of
RDFa that gives a precedent for that.)
So, your rules effectively suggest that @instanceof no longer
applies to the subject of the element as it used to, but is now
applied to the 'thing' being referred to, in this case Ivan. So if
we wanted to indicate that 'the thing named Ralph' is a person, we
would have to wrap the mark-up in another element, and put the type
onto that element. In other words, we would have to go from this:
========
<span
property="foaf:name" content="Ralph"
rel="foaf:knows" href="http://www.w3.org/People/Ivan/#me"
>
</span>
========
to this:
========
<span instanceof="foaf:Person">
<span
property="foaf:name" content="Ralph"
rel="foaf:knows" href="http://www.w3.org/People/Ivan/#me"
>
</span>
</span>
========
You could say that this is not onerous, but it's not the extra mark-
up that is the problem, it's the justification; we're asking authors
to create an extra containing element, only because there is a
resource predicate sitting on the element that represents the item
that we want to set the type of. If the element didn't have a
resource predicate:
========
<span
property="foaf:name" content="Ralph"
>
</span>
========
then we'd be allowed to add the type information to the same element
as the one containing the literal:
========
<span
instanceof="foaf:Person"
property="foaf:name" content="Ralph"
>
</span>
========
In other words, there would be no need for the containing element.
In my mind this kind of restriction is a world away from the rules I
showed at the beginning where all sorts of different pieces of mark-
up represented exactly the same set of triples.
MORE COMPLEX
Anyway, let's continue with this item--a self-contained item which
is now 'a person named Ralph'. Given such an item, we'd expect to be
able to put this anywhere we like, without any unexpected side-
effects. So to continue our example, let's drop it into the the mark-
up we were looking at earlier:
========
<div about="#me" instanceof="foaf:Person">
<div rel="foaf:knows">
<span
instanceof="foaf:Person"
property="foaf:name" content="Ralph"
>
</span>
</div>
</div>
========
We now have:
I am a person who knows a person named 'Ralph'.
Let's duplicate Ralph, change the name to Ivan, and paste this into
the empty <span> element that represents Ralph:
========
<div about="#me" instanceof="foaf:Person">
<div rel="foaf:knows">
<span
instanceof="foaf:Person"
property="foaf:name" content="Ralph"
>
<span
instanceof="foaf:Person"
property="foaf:name" content="Ivan"
>
</span>
</span>
</div>
</div>
========
At the moment there is no relationship between the two items, and
all we have is this:
I am a person who knows a person named 'Ralph'
There is a person named 'Ivan'
This is pretty much the same as we had when building this up using
my rules, and as before, we want to now continue on, heading for the
same complex statement about Ralph, Ivan and Bill that we had above.
So now we need to say that not only do 'I know Ralph', but also that
'Ralph knows Ivan'. We know that to express this relationship we
need to use @rel="foaf:knows", so the question is quite simply,
where should we put this attribute?
Since the predicate we are expressing ('foaf:knows') is a property
of Ralph, then it would seem to make sense to add the attribute to
Ralph's <span>:
========
<div about="#me" instanceof="foaf:Person">
<div rel="foaf:knows">
<span
instanceof="foaf:Person"
property="foaf:name" content="Ralph"
rel="foaf:knows"
>
<span
instanceof="foaf:Person"
property="foaf:name" content="Ivan"
>
</span>
</span>
</div>
</div>
========
In the rules as they used to be, and as I showed above, this gives
the desired result, with no side-effects. But with the rules you are
proposing, Ben, although adding the @rel at this position creates
the desired _relationship_ between the two items, it causes a number
of very awkward things to happen.
SIDE-EFFECTS
First, Ralph's @instanceof suddenly 'moves' from applying to him, to
now applying to the bnode that the @rel creates. In other words, one
moment Ralph is a person, the next he isn't, and all the author did
was to try to place the item representing Ralph into a relationship
with some other item.
Secondly, in your rules we are saying that 'Ivan is a person', twice.
Now you could argue that in order to create the explicit
relationship that we want, we have to mark things up differently to
this, according to your rules; after all, the fact that your rules
don't give the same results as mine is the whole point of the
discussion. :) So once again, to make things work we have to
introduce an extra mediating element:
========
<div about="#me" instanceof="foaf:Person">
<div rel="foaf:knows">
<span
instanceof="foaf:Person"
property="foaf:name" content="Ralph"
>
<span rel="foaf:knows">
<span
instanceof="foaf:Person"
property="foaf:name" content="Ivan"
>
</span>
</span>
</span>
</div>
</div>
========
Essentially we've had to add the extra element in between the two
items, with @rel on it. Admittedly, as I said before, that's not an
enormous amount of extra mark-up, but the real problem I have with
this is that it is something that an author *must* do; it's not just
a coding convention, or something that makes things a little easier
to read, but is actually something that if the author _didn't_ do
it, then their mark-up would mean something completely different to
what they wanted it to mean.
SIMPLE PATTERNS
But the worse thing about this is that it breaks the simple pattern
that we have in RDFa, and it raises the question, why is @rel
allowed to accompany its subject on statements like "I know a person
named 'Ralph'":
========
<div about="#me" rel="foaf:knows">
<span
instanceof="foaf:Person"
property="foaf:name" content="Ralph"
>
</span>
</div>
========
but it is not allowed to accompany its subject on the next
statement, "Ralph knows a person named 'Ivan'"? The mark-up for that
looks like this:
========
<div about="#me" rel="foaf:knows">
<span
instanceof="foaf:Person"
property="foaf:name" content="Ralph"
rel="foaf:knows" href="http://www.w3.org/People/Ivan/#me"
>
<span
instanceof="foaf:Person"
property="foaf:name" content="Ivan"
>
</span>
</span>
</div>
========
and although it works fine with my rules (we get "I know a person
named 'Ralph' who knows a person named 'Ivan'"), when using your
rules it is not intuitive at all why the @instanceof on the 'Ralph
item' should suddenly 'jump' to begin applying to Ivan.
PREDICATE PERMUTATIONS
To put this in a different way again, it's worth looking at what is
the limit of what an element can express, as follows. Under normal
circumstances, an element can obviously have a subject, but then on
top of that, an element could have a maximum of three predicates,
i.e., a literal, a resource, and an rdf:type. However, with your
rules we have to effectively say that not all permutations are
possible, and instead say that an element can only have a maximum of
two predicates to accompany the subject. The permutations are as
follows:
* a literal on its own;
* a resource on its own;
* a type on its own;
* a literal and a resource;
* a literal and a type.
After that, when using your rules the remaining two permutations are
unavailable:
* a resource and a type;
* a literal, a resource and a type.
This is because the moment you add a predicate that takes a
resource--as we did here by saying that Ralph knows Ivan--the type
value no longer applies to the subject.
What I've tried to show in the way that the examples have gradually
built up, adding a small piece of mark-up at a time, is that this
restriction is unfair to authors; why should taking a self-contained
item and adding a predicate to it change the meaning of that item?
BUCKAROO
This 'flip/flop' behaviour reminds me of the children's game
Buckaroo, where adding just one more item to the donkey's saddle can
make it suddenly kick its hind legs in the air, throwing everything
off its back that the players have added. :) In the case of your
rules, adding @rel when @instanceof is already present, causes
everything to be thrown into the air.
You might argue that I'm putting this a little strongly, and that
it's not just _any_ relationship between two items that causes a
problem, but rather it's the specific 'hierarchical' relationship
that we've been using so far (i.e., where one <span> is inside
another). But I'm afraid that's not the case, and even if we remove
this hierarchy, the problem remains.
Let's rewrite the items for Ralph and Ivan so that they appear side-
by-side, and let's also give Ivan the identifier that he uses:
========
<span
instanceof="foaf:Person"
property="foaf:name" content="Ralph"
>
</span>
<span
about="http://www.w3.org/People/Ivan/#me"
instanceof="foaf:Person"
property="foaf:name" content="Ivan"
>
</span>
========
Combining both pieces of mark-up, both your rules and mine would
agree with the following interpretation:
There is a person named 'Ralph'
There is a person named 'Ivan', identified by the resource <http://www.w3.org/People/Ivan/#me
>
Now, if we wanted to add the fact that Ralph knows Ivan, once again
it would seem obvious to put the relationship information directly
onto Ralph's <span>, as follows:
========
<span
instanceof="foaf:Person"
property="foaf:name" content="Ralph"
rel="foaf:knows" resource="http://www.w3.org/People/Ivan/#me"
>
</span>
========
But now, once again, simply by expressing a relationship between two
items, the rules you are proposing cause a change in the actual
*meaning* of one of those items; in this case, Ralph is no longer a
'person', because the moment that you added the @rel/@resource
combination, the @instanceof attribute 'flips' to applying to Ivan.
And note also that the Buckaroo doesn't just happen with the use of
@rel and @instanceof. Let's return to the mark-up describing Ivan:
========
<span
about="http://www.w3.org/People/Ivan/#me"
instanceof="foaf:Person"
property="foaf:name" content="Ivan"
>
</span>
========
We agree that this means:
There is a person named 'Ivan', identified by the resource <http://www.w3.org/People/Ivan/#me
>
Let's add that Ivan knows Ralph:
========
<span
about="http://www.w3.org/People/Ivan/#me"
instanceof="foaf:Person"
property="foaf:name" content="Ivan"
rel="foaf:knows" resource="http://www.w3.org/People/Ralph/#me"
>
</span>
========
Again, we should agree that this means:
There is a person named 'Ivan', identified by the resource <http://www.w3.org/People/Ivan/#me
>
who knows something identified by the resource <http://www.w3.org/People/Ralph/#me
>
Everything looks fine, so far...now try removing the @about value,
perhaps to include this block somewhere else. Unfortunately, we once
again get a flip/flop of meaning--a Buckaroo--since the mark-up
without @about means something completely different:
========
<span
instanceof="foaf:Person"
property="foaf:name" content="Ivan"
rel="foaf:knows" resource="http://www.w3.org/People/Ralph/#me"
>
</span>
========
In your rules Ben, this means:
Something with a name of 'Ivan' knows a person identified by the
resource <http://www.w3.org/People/Ralph/#me>
With my rules, removing @about has no effect on the general meaning,
which seems to me reliable and predictable--all removing the
identifier does to our item is to remove the identifier. :) In other
words, from this:
There is a person named 'Ivan', identified by the resource <http://www.w3.org/People/Ivan/#me
>
who knows something identified by the resource <http://www.w3.org/People/Ralph/#me
>
we simply get this:
There is a person named 'Ivan' who knows something identified by the
resource <http://www.w3.org/People/Ralph/#me>
AVOIDING THE US OF ALL ATTRIBUTES AT THE SAME TIME
I know that you've suggested before that you wouldn't put all of the
RDFa attributes onto one element in the way that I have done here,
but I'm afraid I don't think that is a legitimate argument, for
three reasons. First, as we just saw, there is actually no problem
when *all* attributes are present, so the argument would need to be
that we should avoid using 'most attributes'. :) But seriously, the
problem in the last example I gave didn't arise until we went from
using every attribute to removing @about. Likewise, in our earlier
examples the problem arose when we tried to add @rel to an element
that already had @instanceof, and so again was not a problem of
having 'all' attributes.
The second reason is that the rules need to be consistent under all
circumstances, and we can't simply say to people that they should
avoid certain patterns because they don't behave in the way that
they are expected to.
But the third reason is that I've not actually picked outlandish
examples here--I've used the examples that you've suggested Ben, so
as to create as much common terrain as possible. I hope you can see
from these examples that having lots of attributes present is really
not that unusual.
CONCLUSION
I think the fact that you effectively came up with the same idea as
chaining a 'second time' is pretty impressive! But I think that if
we are to reintroduce it--which I'm mostly in favour of--we need to
grab a couple of extra rules that we're currently missing.
I think it's worth looking at those in a separate thread, since I
don't think it affects this discussion; at core, this thread is
about whether @instanceof should apply to the object on an element,
if present, and as I've tried to argue, I think it would be a big
mistake if we made our attributes behave inconsistently in order to
support that rule, especially when we can actually fulfill all of
the use-cases that you (rightly) require.
Regards,
Mark
--
Mark Birbeck, formsPlayer
[EMAIL PROTECTED] | +44 (0) 20 7689 9232
http://www.formsPlayer.com | http://internet-apps.blogspot.com
standards. innovation.