W3C

RDF/A Primer 1.0

Examples of RDF/A Applied to XHTML2

note 10 January 2006

This version:
RDF/A Primer $Id: 2005-rdfa-primer.xml,v 1.4 2005/10/28 03:10:53 adida Exp $
Latest version:
RDF/A Primer-2006-01-10
Previous version:
RDF/A Primer-2005-10-27
Editors:
Ben Adida, Creative Commons <ben@creativecommons.org>
Mark Birbeck, x-port.net Ltd. <mark.birbeck@x-port.net>

Abstract

The aim of this document is to introduce the RDF/A syntax for adding RDF triples to XML dialects. Examples are provided in the context of XHTML2, the most immediate such XML dialect. The reader is expected to be fairly familiar with XHTML, and somewhat familiar with RDF.

Status of this Document

This is an internal draft produced by the RDF-in-HTML task force [RDFHTML], a joint task force of the Semantic Web Best Practices and Deployment Working Group [SWBPD-WG] and HTML Working Group [HTML-WG].

Last Modified: 2006-01-10

Table of Contents

1 Purpose of RDF/A
2 A Simple Scenario
    2.1 Setting Up the Web Page
    2.2 Adding Name and Contact Metadata
        2.2.1 Using URLs as Property Values
        2.2.2 Using Text As Property Values
        2.2.3 Complete Mark-up
    2.3 Adding A Departmental List
3 Simple Metadata
    3.1 Textual Properties
    3.2 Qualifying Links
4 Beyond the Current Document
    4.1 Qualifying Other Documents
    4.2 Qualifying Chunks of Documents
    4.3 Syntactic Sugar
    4.4 Inline Objects
5 Advanced RDF Concepts
    5.1 Bnodes
    5.2 Reification
6 Practical Examples
    6.1 Creative Commons
    6.2 FOAF
7 Bibliography


1 Purpose of RDF/A

RDF/A is a set of attributes that are used to augment existing XML dialect elements with RDF metadata. The primary goal of RDF/A is to embed RDF without repeating existing content of the XML dialect when that content is the metadata. This document will specifically consider XHTML2 as a host XML language, as that was the primary target for RDF/A. However, one should be able to use RDF/A with other XML dialects, e.g. SVG.

We note that RDF/A makes use of XML namespaces. In this document, we assume, for simplicity's sake, that the following namespaces are defined: dc for Dublin Core, foaf for FOAF, and cc for Creative Commons.

2 A Simple Scenario

Jo has lots of friends, family and work colleagues with which she would like to stay in touch during her busy schedule. She would like to set up a home-page for herself, where people who know her can find useful contact information, such as her phone number or work email.

2.1 Setting Up the Web Page

Jo's first stop is to create a page that contains information about her that can be read by anyone using a web browser. She begins with some details for people who might be trying to contact her at work:

<html>
    <head>
        <title>Jo Lamda's Home Page</title>
    </head>
    <body>
        <p>
            Hello. This is Jo Lamda's home page.
            <h2>Work</h2>
            If you want to contact me at work, you can
            either <a href="mailto:jo.lambda@example.org">email
                me</a>, or call +1 777 888 9999.
        </p>
    </body>
</html>
                    

Jo can now pass on the address of her home-page to her friends, which is http://jo-lamda.blogspot.com/.

2.2 Adding Name and Contact Metadata

One of Jo's friends, Terri, tells Jo that the address book software she uses can be automatically kept up-to-date with Jo's details. All Jo needs to do is to add some tags to her home page to help the system understand her data. The tags that Terri's address book understands come from a special list-often called a vocabulary-specifically for describing relationships between people. The particular vocabulary is called 'Friend-of-a-friend', or FoaF [FOAF].

The first thing that Jo needs to do is add an identifier to the top of her document that will make the FoaF vocabulary available to the rest of her home-page:

<html
  xmlns:foaf="http://xmlns.com/foaf/0.1/"
>
                    

Jo then looks through the FoaF vocabulary, and sees that the pieces of information that she has in her page—name, phone number and email address—all have names within FoaF. She therefore adds those names to her document, using the following approach:

  1. if the value we want to use for a property is in the href attribute of an <a> element, then the rel attribute can be added to the element, set to contain the name of the property;

  2. if the value to be used for a property that we want to add doesn't have an element to contain it, then one must be added;

  3. the name of the property used to describe the contents of an element is placed in an attribute called property.

Let's look at each of those rules.

2.2.1 Using URLs as Property Values

Jo has provided a link in her home-page to her email address, which is jo.lambda@example.org:

            .
            .
            .
            If you want to contact me at work, you can
            either <a href="mailto:jo.lambda@example.org">email
            .
            .
            .
                        

However, to ensure that Terri's address book software understands this, Jo can use the FoaF mailbox property:

            .
            .
            .
            If you want to contact me at work, you can
            either <a rel="foaf:mbox" href="mailto:jo.lambda@example.org">email
            .
            .
            .
                        

2.2.2 Using Text As Property Values

In addition to her email address, Jo also wants to add her name and phone number. Currently the values that she would like to use for these properties are not separated from the other text items so, as per rule 2, Jo adds some simple wrapper elements:

        <p>
            Hello. This is <span>Jo Lamda</span>'s home page.
            <h2>Work</h2>
            If you want to contact me at work, you can
            either <a rel="foaf:mbox" href="mailto:jo.lambda@example.org">email
                me</a>, or call <span>+1 777 888 9999</span>.
        </p>
                        

Now that the text is inside span elements it is easy to add the FoaF properties for name and phone number, using the RDF/A attribute property:

        <p>
            Hello. This is <span property="foaf:name">Jo Lamda</span>'s home page.
            <h2>Work</h2>
            If you want to contact me at work, you can
            either <a rel="foaf:mbox" href="mailto:jo.lambda@example.org">email
                me</a>, or call <span property="foaf:phone">+1 777 888 9999</span>.
        </p>
                        

2.2.3 Complete Mark-up

The completed document looks like this:

<html>
    <head>
        <title>Jo Lamda's Home Page</title>
    </head>
    <body>
        <p>
            Hello. This is <span property="foaf:name">Jo Lamda</span>'s
            home page.
            <h2>Work</h2>
            If you want to contact me at work, you can
            either <a rel="foaf:mbox" href="mailto:jo.lambda@example.org">email
                me</a>, or call <span property="foaf:phone">+1 777 888 9999</span>.
        </p>
    </body>
</html>
                    

Now all Terri needs to do is to provide the internet address for Jo's home page to her contact software, and it will be able to extract the following information about Jo:

foaf:name     = "Jo Lamda"
foaf:mbox     = "mailto:jo.lambda@example.org"
foaf:phone    = "+1 777 888 9999"
foaf:homepage = "http://jo-lamda.blogspot.com/"

Terri's software gets the final piece of data 'for free', since that was how Terri made the software aware of Jo's data in the first place. And from now on, synchronisation of Jo's data to Terri's address book will be automatic.

Emboldened by how easy it was to keep her friend Terri up-to-date with her information, Jo decides to encourage the same approach amongst her work colleagues. Jo is part of the widget development department at her company, and is currently working on a project to make the widgets shinier. She decides she wants this information to also be in a form that can be automatically kept up-to-date.

2.3 Adding A Departmental List

Jo's company intranet runs a Wiki, so it is quite straightforward to create a page for the department in which she works. On this page she wants, amongst other things, to have a list of the deparment's members. The page is http://intranet/WidgetDevelopmentDepartment.

The first step is to indicate in the header of the document that we are dealing with a FoaF group:

<html
    xmlns:foaf="http://xmlns.com/foaf/0.1/"
    >
    <head>
        <title>Widget Development Department</title>
        <link rel="rdf:type" href="[foaf:Group]" />
    </head>
                

The title of the group is also set:

    <body>
        <p>
            Hello. Welcome to the
            <span property="foaf:name">Widget Development Department.</span>
        </p>
                    

We have now established a foaf:group with the foaf:name of "Widget Development Department". The next step is to list each member of the group. The best way to do this is to add a link to a member's details, since then anyone synchronising their address book with the departmental list will also remain synchronised with the contact details of each member, just as Terri is synchronised with Jo's information:

        <p>
            <h2>Departmental Members</h2>
            <ul>
                <li>
                    <a rel="foaf:member" href="http://jo-lamda.blogspot.com/">Jo Lamda</a>
                </li>
                    

Of course, not everyone will be as up-to-the-minute as Jo, with her home-page doubling up as an automatic source of FoaF information; so for people without available contact information, details can still be added inline:

                <li id="andrew" about="#andrew">
                    <link rel="rdf:type" href="[foaf:member]" />
                    <span property="foaf:firstname">Andrew</span>
                    <span property="foaf:surname">Smith</span> can be contacted on
                    <span property="foaf:phone">+1 777 888 9998</span>
                </li>
            </ul>
        </p>
    </body>
</html>
                

Note that if the list item (li) does not have an about attribute, then the foaf:surname, foaf:firstname and foaf:phone properties would apply to the foaf:group and not to the individual member of the group. Also, the type of the entry needs to be set to foaf:member.

3 Simple Metadata

3.1 Textual Properties

Consider a simple XHTML2 document fragment:

<h1>RDF/A Examples</h1>
<h2>Ben Adida</h2>

The rendered information about the document, specifically its title and author, can be easily marked up as RDF properties:

<h1 property="dc:title">RDF/A Examples</h1>
<h2 property="dc:creator">Ben Adida</h2>

which provides the following RDF triples:

<> dc:title "RDF/A Examples" .
<> dc:creator "Ben Adida" .

3.2 Qualifying Links

Consider an XHTML2 document fragment that links to a copyright license defining its terms of redistribution:

This document is available under a
<a href="http://creativecommons.org/licenses/by-nc-nd/2.5/">
  Creative Commons License
</a>.

This clickable link has an intended semantic meaning: it is the document's license. RDF/A quickly allows for the typing of this clickable link:

This document is available under a
<a rel="cc:license"
   href="http://creativecommons.org/licenses/by-nc-nd/2.5/">
  Creative Commons License
</a>.

In RDF/A, the href attribute can contain a Compact URI (CURIE), which makes the expression of numerous metadata statements far more compact. To differentiate the CURIE from a typical URI, we use square brackets (as per [CURIE]).

This document is available under a
<a xmlns:cclicenses="http://creativecommons.org/licenses/"
   rel="cc:license"
   href="[cclicenses:by-nc-nd/2.5/]">Creative Commons License</a>.

Both of these RDF/A-augmented snippets of XHTML yield the following triple:

<> cc:license <http://creativecommons.org/licenses/by-nc-nd/2.5/> .

4 Beyond the Current Document

The above examples casually swept under the rug the issue of the RDF triple subject. However, not all RDF triples in a given XHTML2 document will be about that document itself. Without any further guidance, the subject of an RDF/A assertion defaults to the current document. However, there are easy ways to override this default.

The about attribute is used for defining the subject.

4.1 Qualifying Other Documents

One may wish to make metadata statements about other documents altogether. This is particularly useful in the case of inline images:

A bunch of photos:
<ul>
  <li> <img src="photo1.jpg" /> taken by photographer 
       <span about="photo1.jpg" 
             property="dc:creator">Mark Birbeck</span></li>

  <li> <img src="photo2.jpg" /> taken by photographer 
       <span about="photo2.jpg" 
             property="dc:creator">Steven Pemberton</span></li>
</ul>

The above XHTML2 and RDF/A yield the following triples:

<photo1.jpg> dc:creator "Mark Birbeck" .
<photo2.jpg> dc:creator "Steven Pemberton" .

This same approach applies to statements with non-literal objects. For example, a photo might have its own copyright license:

A bunch of photos:
<ul>
  <li> <img src="photo1.jpg" /> taken by photographer 
       <span about="photo1.jpg" 
	     property="dc:creator">
	 Mark Birbeck
       </span>,
       licensed under a
       <a about="photo1.jpg" rel="cc:license"
	  href="http://creativecommons.org/licenses/by-nc-nd/2.5/">
	 Creative Commons License
       </a>.
  </li>
...

Considering only this single photo (photo1.jpg) in the above example, the following triples are obtained:

<photo1.jpg> dc:creator 
             "Mark Birbeck" .
<photo1.jpg> cc:license 
             <http://creativecommons.org/licenses/by-nc-nd/2.5/> .

Note that the about attribute is repeated in the above example. RDF/A allows the value of this attribute to be inherited from parent elements. Thus, the markup for the above example can be simplified to:

A bunch of photos:
<ul>
  <li about="photo1.jpg"> <img src="photo1.jpg" />
    taken by photographer 
    <span property="dc:creator">Mark Birbeck</span>,
    licensed under a
    <a rel="cc:license"
       href="http://creativecommons.org/licenses/by-nc-nd/2.5/">
      Creative Commons License
    </a>.
  </li>
...

which yields the same triples as the previous example, though, in this case, one can easily see the parallel to the corresponding N3 shorthand:

<photo1.jpg> dc:creator "Mark Birbeck" ;
             cc:license <http://creativecommons.org/licenses/by-nc-nd/2.5/> .

4.2 Qualifying Chunks of Documents

In certain cases, one wants to include multiple RDF elements in a given document, each with their own type and metadata. It's also important to be able to relate them. The prime example of this is FOAF.

For this purpose, RDF/A offers link and meta, which behave in a special way : they only apply to their immediate parent element.

<section id="person">
  <link rel="rdf:type" href="[foaf:Person]" />
  <h1 property="foaf:name">Dan Brickley</h1>
  <link rel="foaf:homepage" href="" />
</section>

which yields:

<#person> rdf:type foaf:Person ;
          foaf:name "Dan Brickley" ;
          foaf:homepage <> .

Alternatively, if one wishes to express this same metadata about #person without actually having that chunk of HTML represent the person in question, then one can write:

<section about="#person">
   <link rel="rdf:type" href="[foaf:Person]" />
   <meta property="foaf:name" content="Dan Brickley" />
   <link rel="foaf:homepage" href="" />
</section>

This yields the exact same triples. Note how the meta and link apply to the parent node's about if that about exists.

4.3 Syntactic Sugar

@@TODO: finalize whether this is acceptable syntactic sugar

Extrapolating from the above examples, it's quite easy to see how XHTML elements might represent RDF entities on a regular basis. Thus, RDF/A offers syntactic sugar for the rdf:type relationship, using the well-established class attribute. The above XHTML2 can thus be simplified to:

<section about="#person" class="[foaf:Person]">
   <meta property="[foaf:name]" content="Dan Brickley" />
   <link rel="[foaf:homepage]" href="" />
</section>

4.4 Inline Objects

@@TODO: this issue is not yet resolved: Current Issues. And there are some weird consequences: the inside of the img element is not rendered, so what of renderable XHTML elements with metadata? We may want to only enable link and meta...

Images and Objects in XHTML2 are loaded from the src attribute. Adding some metadata relevant to these inline objects is a natural extension of previous examples. In the absence of an about attribute, the src attribute serves as the subject. For example, the following XHTML with RDF/A:

<img src="photo1.jpg">
   <link rel="cc:license" 
	 href="http://creativecommons.org/licenses/by-nc-nd/2.5/" />
   <meta property="dc:creator" content="Mark Birbeck" />
</img>
  

which yields the following triples:

<photo1.jpg> cc:license <http://creativecommons.org/licenses/by-nc-nd/2.5/> ;
             dc:creator "Mark Birbeck" .
  

5 Advanced RDF Concepts

5.1 Bnodes

The progression to bnodes is natural. In the above examples of Section 3 where link and meta are used to attach metadata to their parent element, one wonders what would happen if the parent element had neither id nor about attribute. The result is exactly a bnode: an XHTML element that isn't addressable from the outside:

<section>
   <link rel="rdf:type" href="[foaf:Person]" />
   <h1 property="foaf:name">Dan Brickley</h1>
   <link rel="foaf:homepage" href="" />
</section>

Alternatively, one can make the about an explicit bnode using the CURIE notation:

<section about="[_:person]">
   <link rel="rdf:type" href="[foaf:Person]" />
   <h1 property="foaf:name">Dan Brickley</h1>
   <link rel="foaf:homepage" href="" />
</section>

Both of these yield:

_:person rdf:type foaf:Person ;
         foaf:name "Dan Brickley" ;
         foaf:homepage <> .

(Technically, it's unlikely that the first would magically yield a bnode name of _:person. It would likely be something like _:section0. But the result is really the same.)

5.2 Reification

When a meta or link is used within another meta or link, the internal triple has, as subject, the external triple. This is reification.

<link about="" rel="cc:license" 
      href="http://creativecommons.org/licenses/by-nc-nd/2.5/">
   <meta property="dc:date" content="2005-10-18" />
</link>

which yields:

[ rdf:subject <>;
  rdf:predicate cc:license ;
  rdf:object <http://creativecommons.org/licenses/by-nc-nd/2.5/> ]
dc:date "2005-10-18" .

6 Practical Examples

6.1 Creative Commons

Describing the licensing of a document with Creative Commons metadata is, in some sense, an extension of Dublin Core, since Creative Commons usually hands out a number of Dublin Core attributes in addition to the license relationship. Thus, a Creative Commons RDF/A chunk would be:

<div about="">
    This document is licensed under a
    <a rel="cc:license" 
       href="http://creativecommons.org/licenses/by-sa/2.0/">
        Creative Commons License
    </a>
    which, among other things, requires that you provide 
    attribution to the author,
    <a rel="dc:creator" 
       href="http://ben.adida.net">Ben Adida</a>.
</div>
            

which will generate:

<> cc:license <http://creativecommons.org/licenses/by-sa/2.0/>
<> dc:creator <http://ben.adida.net>
            

6.2 FOAF

FOAF requires the definition of at least two RDF entities: the FOAF person, and the FOAF homepage, which cannot be the same. Thus, the following XHTML can be used to represent a FOAF record:

<html xmlns...>
    <head>
      <title property="dc:title">Dan's home page</title>
    </head>
    <body>
      <section id="person">
        <span about="[_:geolocation]">
          Dan is located at latitude
          <meta property="geo:lat">51.47026</meta>
          and longitude
          <meta property="geo:long">-2.59466</meta>
        </span>
        <link rel="rdf:type" href="[foaf:Person]" />
        <link rel="foaf:homepage" href="" />
        <link rel="foaf:based_near" href="[_:geolocation]" />
        <h1 property="foaf:name">Dan Brickley</h1>
      </section>
    </body>
</html>
            

which yields the correct FOAF triples:

<> dc:title "Dan's home page" .
_:geolocation geo:lat "51.47026" .
_:geolocation geo:long "-2.59466" .
<#person> rdf:type foaf:Person .
<#person> foaf:homepage <> .
<#person> foaf:based_near _:geolocation .
<#person> foaf:name "Dan Brickley" .
            

7 Bibliography

RDFHTML
RDF-in-HTML Task Force (See http://w3.org/2001/sw/BestPractices/HTML/.)
SWBPD-WG
Semantic Web Best Practices and Deployment Working Group (See http://w3.org/2001/sw/BestPractices/.)
HTML-WG
HTML Working Group (See http://w3.org/MarkUp/Group/.)