W3C home > Mailing lists > Public > public-rdf-in-xhtml-tf@w3.org > November 2007

Re: chaining-friendly rules for @instanceof

From: Mark Birbeck <mark.birbeck@formsPlayer.com>
Date: Wed, 14 Nov 2007 23:14:11 +0000
Message-Id: <AFCAE5D0-6FC9-4C81-9C18-4B56DEAF8790@formsPlayer.com>
Cc: RDFa <public-rdf-in-xhtml-tf@w3.org>
To: Ben Adida <ben@adida.net>

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

   mark.birbeck@formsPlayer.com | +44 (0) 20 7689 9232
   http://www.formsPlayer.com | http://internet-apps.blogspot.com

   standards. innovation.
Received on Wednesday, 14 November 2007 23:14:45 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Tuesday, 8 January 2008 14:15:18 GMT