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.