TobyInkster.co.uk

16/07/2008: Extending hCard with RDFa

hCard is an HTML-based format for describing contacts (people, organisations, etc) on web pages. It allows you to mark up which elements represent their name, their address, their birthday and so forth. Here’s an example:

<div class="vcard">
  <h1 class="fn">Toby Inkster</h1>
  <p>Birthday: <span class="bday">1980-06-01</span>.</p>
</div>

While hCard offers many useful properties that can be used to describe contacts, some are considered beyond the scope of the hCard specification. For example, there is no hCard property to mark up somebody’s height, or shoe size.

This is where RDFa comes in. RDFa is not a specialist format for describing people or organisations, but a more general format for describing anything. We can use RDFa to add in the extra information we want.

Now, one of the features of RDFa is that it’s difficult (not impossible though) to describe anything that doesn’t have a URL. So let’s give our example hCard a URL:

<div class="vcard" id="hcard_toby">
  <h1 class="fn">Toby Inkster</h1>
  <p>Birthday: <span class="bday">1980-06-01</span>.</p>
</div>

Now, if this hCard resided on http://example.com/page then the URL for the hCard itself would be: http://example.com/page#hcard_toby. Now that the hCard has a URL, we can use RDFa to add further information.

In our RDFa, firstly we need to state what thing we will be describing:

<div class="vcard" id="hcard_toby">
  <h1 class="fn">Toby Inkster</h1>
  <p>Birthday: <span class="bday">1980-06-01</span>.</p>
  <div about="http://example.com/page#hcard_toby">
    <!-- Our RDFa will go here. -->
  </div>
</div>

Now let’s add some information on my height. Firstly we need to find an “RDF vocabulary” that covers people’s heights. An RDF vocabulary is a set of terms like “height”, “weight”, “shoe size” with corresponding URLs, so that if somebody doesn’t know exactly what “height” means (it could mean how tall a person is, or the altitude they’re standing at above sea level), they can look up the URL and find out exactly what we mean by “height”.

Say, for example, that we find a vocabulary at http://example.net/people, such that http://example.net/people#height represents a person’s height, measured in metres. Also, http://example.net/people#shoes will represent a person’s shoe size, in UK sizes.

Now we can add this information to our hCard — notice the new property attribute:

<div class="vcard" id="hcard_toby">
  <h1 class="fn">Toby Inkster</h1>
  <p>Birthday: <span class="bday">1980-06-01</span>.</p>
  <div about="#hcard_toby"> <!-- I've reduced this to a relative URL -->
    My height is
    <span property="http://example.net/people#height">1.75</span><br />
    My shoe size is
    <span property="http://example.net/people#shoes">10</span>
  </div>
</div>

Let’s introduce a bit of syntactic sugar. You’ll notice we’re repeating that http://example.net/people# already — if we were to add a few more properties, this could become tiresome. RDFa allows us to use CURIEs to create abbreviated URLs — xmlns attributes are used to define short codes for URL prefixes, and then they can be used more freely. Using CURIEs we get:

<div class="vcard" id="hcard_toby"
xmlns:ex="http://example.net/people#">
  <h1 class="fn">Toby Inkster</h1>
  <p>Birthday: <span class="bday">1980-06-01</span>.</p>
  <div about="#hcard_toby">
    My height is <span property="ex:height">1.75</span><br />
    My shoe size is <span property="ex:shoes">10</span>
  </div>
</div>

Now, although to RDFa parsers this is unambiguous information — an RDF parser that understands ex:height will also understand that it is measured in metres — a human reader will probably need a bit more information to be displayed on the page. This is where the content attribute comes in:

<div class="vcard" id="hcard_toby"
xmlns:ex="http://example.net/people#">
  <h1 class="fn">Toby Inkster</h1>
  <p>Birthday: <span class="bday">1980-06-01</span>.</p>
  <div about="#hcard_toby"> <!-- I've reduced this to a relative URL -->
    My height is <span property="ex:height" content="1.75">175 cm</span><br />
    My shoe size is <span property="ex:shoes" content="10">10 (UK)</span>
  </div>
</div>

OK, we’ve looked at how RDFa can be used to add additional pieces of information to an hCard. Now we’ll look at RDFa’s use of the rel and rev attributes to indicate relationships between things. In this case, we’ll look at the relationship between a person and a document. We want to say that the person made the document.

Here’s my document now:

<html xmlns:ex="http://example.net/people#">
  <!-- Note that I've moved the xmlns attribute up to the top. It's generally
       useful to keep them all together up here - you'll often want to use
       more than one! -->
  ...
  <h1>My Document</h1>
  ...
  <div class="vcard" id="hcard_toby">
    <h2 class="fn">Toby Inkster</h2>
    <p>Birthday: <span class="bday">1980-06-01</span>.</p>
    <div about="#hcard_toby">
      My height is <span property="ex:height" content="1.75">175 cm</span><br />
      My shoe size is <span property="ex:shoes" content="10">10 (UK)</span>
    </div>
  </div>
  ...
</html>

Now, we can add a <link> element to link down to my hCard at the bottom of the page, so that we have a link from the document to its author:

<html xmlns:ex="http://example.net/people#">
  <link rel="author" href="#hcard_toby" />
  ...
  <h1>My Document</h1>
  ...
  <div class="vcard" id="hcard_toby">
    <h2 class="fn">Toby Inkster</h2>
    <p>Birthday: <span class="bday">1980-06-01</span>.</p>
    <div about="#hcard_toby">
      My height is <span property="ex:height" content="1.75">175 cm</span><br />
      My shoe size is <span property="ex:shoes" content="10">10 (UK)</span>
    </div>
  </div>
  ...
</html>

Actually, that’s all that’s required, because RDFa includes author in its list of predefined relationships which it understands, but for the purposes of this example, we’ll also introduce a vocabulary called FOAF which includes two useful terms, foaf:maker and foaf:made.

Let’s add foaf:maker which has almost exactly the same meaning as author, so can be added in the same way:

<html xmlns:ex="http://example.net/people#" xmlns:foaf="http://xmlns.com/foaf/0.1/">
  <link rel="author" href="#hcard_toby" />
  <link rel="foaf:maker" href="#hcard_toby" />
  ...

But wait! HTML actually allows us to use an abbreviated format for listing multiple <link> elements where the link target is the same:

<html xmlns:ex="http://example.net/people#" xmlns:foaf="http://xmlns.com/foaf/0.1/">
  <link rel="author foaf:maker" href="#hcard_toby" />
  ...

Better. Now let’s add the reverse relationship — if the document’s foaf:maker is Toby, then it’s equally true that Toby foaf:made the document. Here’s two ways of doing that. Firstly, we could add a forward link from my hCard to the document:

<html xmlns:ex="http://example.net/people#" xmlns:foaf="http://xmlns.com/foaf/0.1/">
  <link rel="author foaf:maker" href="#hcard_toby" />
  ...
  <h1>My Document</h1>
  ...
  <div class="vcard" id="hcard_toby">
    <h2 class="fn">Toby Inkster</h2>
    <p>Birthday: <span class="bday">1980-06-01</span>.</p>
    <div about="#hcard_toby">
      My height is <span property="ex:height" content="1.75">175 cm</span><br />
      My shoe size is <span property="ex:shoes" content="10">10 (UK)</span><br />
      I made <a rel="foaf:made" href="http://example.com/page">this document</a>
    </div>
  </div>
  ...
</html>

As an alternative (or in addition — it doesn’t hurt to state the same thing twice) we could make use of the rev attribute on the <link> tag at the top:

<html xmlns:ex="http://example.net/people#" xmlns:foaf="http://xmlns.com/foaf/0.1/">
  <link rel="author foaf:maker" rev="foaf:made" href="#hcard_toby" />
  ...
  <h1>My Document</h1>
  ...
  <div class="vcard" id="hcard_toby">
    <h2 class="fn">Toby Inkster</h2>
    <p>Birthday: <span class="bday">1980-06-01</span>.</p>
    <div about="#hcard_toby">
      My height is <span property="ex:height" content="1.75">175 cm</span><br />
      My shoe size is <span property="ex:shoes" content="10">10 (UK)</span><br />
      I made <a rel="foaf:made" href="http://example.com/page">this document</a>
    </div>
  </div>
  ...
</html>

So there we have it, RDFa can be used to add extra information to hCards, and also to express relationships between people, organisations, documents and things.

Comments

Comment 001

While I can understand that this is certainly an interesting use of RDFa and Microformats in the same document, I don’t understand why the document author wouldn’t use pure RDFa to mark up the information instead since there are vocabularies that support everything the VCARD uF supports?

— manu

Author: Anonymous Coward [96.240.163.205]
Date: Thursday, 17th July 2008, 3:28am (BST)

Comment 002

Cool. Now … does this also look ok for XFN? I’m wondering in particular about rel=me…

Author: Anonymous Coward [72.244.136.18]
Date: Thursday, 17th July 2008, 5:04am (BST)

Comment 003

Very good!
Just a question: Is it really necessary in your examples to add the about=”#…” to the div? I think, this is unnecessary here, because this div is inside the vcard div. It would be necessary if this div would be outside the vcard div.
Of cource putting it here is not wrong. Just unnecessary, i think.

Author (Unverified): Siegfried [87.167.47.179]
Date: Friday, 18th July 2008, 3:36pm (BST)

Comment 004

Yes the about attribute is necessary.

To clarify, hCard needs a “container element” for the properties like fn and bday to sit inside. The way to specify this container element is by setting class="vcard".

Similarly, RDFa needs a “container element” for its attributes (property, etc) to sit inside — it provides several different mechanisms for specifying this container (and in the absence of any of these, the document as a whole acts as the container). The about attribute is one way of specifying such a container, and is the easiest one to teach in a mini-tutorial such as this.

If you’re interested in learning more about RDFa, then the W3C’s RDFa Primer is a very good introduction. For the really nitty gritty details, the Syntax and Processing document is the definitive reference.

Author: Toby Inkster
Date: Friday, 18th July 2008, 4:12pm (BST)

Comment 005

Um, yes. The RDF primer (and other documents) allow an empty about string, if f.ex. the content of the RDF triples is about the current document.

Hmmm, you’re right in that the about attribute itself is necessary. But it may be empty in such cases.

Author (Unverified): Siegfried [87.167.47.179]
Date: Friday, 18th July 2008, 6:57pm (BST)

Comment 006

@Anonymous Coward: Regarding XFN and rel=”me”. I think this is somewhat similar to rel=”author” or rel=”foaf:maker”. But not identical. A rel=”author” states that the person about whom this data record is is the author of the page. This may be different to rel=”me” in case where the page is about person A, while person B made the page for person A. But that aside this could be used similar as described here (rel=”author”, rel=”foaf:maker). And, just to complete it, similar to rel=”dc:creator”.

Author (Unverified): Siegfried [87.167.47.179]
Date: Friday, 18th July 2008, 7:32pm (BST)

Comment 008

@Anonymous Coward: I’m actually working on an example of hCard, hCalendar, XFN and RDFa for marking up genealogy. It’s quite a comprehensive (i.e. long, thus taking a long time to complete) document, but I’ll be sure to post a link on my blog when I’m done.

Author: Toby Inkster
Date: Friday, 25th July 2008, 9:56am (BST)

Comments are moderated and may take one or two days to show up on the site. You can bypass comment moderation by signing up as a registered user.

  1. Comment
  2. Login
  3. Your Details

Comment

Login

Your Details

Google Search

Article Details

Author:Toby Inkster
Licence:All rights reserved
Created:Wed, 16 Jul 2008
Status:Standard
Permalink:Permalink

Next & Previous

Next:

Previous:

July 2008

M T W T F S S
30 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 1 2 3

Blogroll

Here are some other sites. Some might be good; some might be rubbish. You decide.