Copyright © 2006 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark, document use, and software licensing rules apply.
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.
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
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
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.
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.
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/
.
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:
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;
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;
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.
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 . . .
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>
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.
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
.
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" .
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/> .
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.
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/> .
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.
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>
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" .
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.)
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" .
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>
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" .