Copyright © 2004 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark, document use, and software licensing rules apply.
The aim of this document is to outline a syntax for layering RDF information on any XML document, via attributes.
1 Motivation
2 Terms and Abbreviations
2.1 Namespaces
2.2 RDF Terminology
2.2.1 N-Triples
2.3 Using xml:base
3 Introduction to the structure of RDF/A
3.1 General Approach
3.2 Using RDF/A in other namespace documents
3.3 Global statements
3.4 Qualifying statements
3.5 Mixing global and qualifying statements
4 RDF/A in detail
4.1 Processing
4.2 Establishing the subject
4.2.1 Using the about attribute
4.2.2 Using the attribute nodeID
4.2.3 Using an attribute of type xml:id
4.2.4 Using the [context statement]s subject
4.2.4.1 Using the [context statement]'s nodeID attribute
4.2.4.2 Using the [context statement]'s about attribute
4.2.4.3 Using the [context statement]'s id attribute
4.2.4.4 Generating implicit [unique anonymous ID]s
4.3 Establishing the predicate
4.3.1 Using the property attribute
4.3.2 Using the rel attribute
4.3.3 Using the rev attribute
4.3.4 Using the [context statement]'s predicate
4.3.4.1 Using the [context statement]'s predicate
4.3.4.2 Using hasReferenceTo
4.4 Establishing the object
4.4.1 Using the content attribute
4.4.2 Using the href attribute
4.4.3 Providing an object to the [context statement]
4.5 Summary
5 RDF Concepts
5.1 Literals as Objects
5.1.1 Plain Literals
5.1.1.1 Language Tags
5.1.2 Typed Literals
5.1.2.1 XML Literals
5.2 Blank nodes
6 Examples
6.1 Creative Commons
7 Rules
8 Bibliography
The syntax is almost complete, but there are still some issues to resolve now that we have tried to 'bridge' the 'clickable and semantic webs'.
The main issue is in determining when some element is providing mark-up for its parent element (what we have called the [context statement]) and when it is providing mark-up for itself. For example, in this statement:
<blockquote rel="dc:source" href="..."> ... </blockquote>
we are obviously saying something about the quote's origin. Similarly here, we probably mean the same thing:
<blockquote> <link rel="dc:source" href="..." /> ... </blockquote>
This latter example 'works' because link
has a default style of display: none;
.
A natural extension would be to provide a live link to the source of the quote:
<blockquote> <a rel="dc:source" href="...">Source</a> ... </blockquote>
which we would probably want to mean the same thing as the earlier
examples. This is OK, but the problem is that there is no obvious way
to differentiate this structure from the earlier one with blockquote
. We do have two or three suggestions as to how to solve this, which
will be presented separately.
Resolution:
None recorded.
RDF/XML [RDF-SYNTAX] provides sufficient flexibility to represent all of the abstract concepts in RDF [RDF-CONCEPTS]. However, it presents two challenges; first it is difficult or impossible to validate documents that contain RDF/XML using XML Schemas or DTD's, which makes it difficult to import RDF/XML into other markup languages. Whilst newer schema languages such as RELAX NG [RELAXNG] do provide a way to validate documents that contain arbitrary RDF/XML, it will be a while before they gain wide support.
The second challenge is that the syntax of RDF/XML is too unwieldy for use as a mechanism for adding metadata to a document about the document itself. RDF/XML's primary purpose is as a document format for transporting RDF, and it fulfills this role admirably. But when we have a document of some other type -- XHTML, SVG, SSML, and so on -- to which we would like to add arbitrary metadata, RDF/XML is awkward to use.
The resolution is usually to 'hard-wire'
attributes directly into the XML language, to represent specific
concepts. For example, in XHTML 1.1 and HTML there is a cite
attribute. The attribute allows an author to add information to a document
to indicate the origin of a quote. The following example comes from [HTML], although it has been reformatted as XHTML [XHTML]:
<blockquote cite="http://www.mycom.com/tolkien/twotowers.html"> <p>They went in single file, running like hounds on a strong scent, and an eager light was in their eyes. Nearly due west the broad swath of the marching Orcs tramped its ugly slot; the sweet grass of Rohan had been bruised and blackened as they passed.</p> </blockquote>
The problem here is that we have had to add a specific attribute to designate citation, and further, both the browser and some metadata processor need to have knowledge of this attribute, and its position within the mark-up.
The RDF/XML solution is to take the citation out as a specific statement about the quote. Our source document may now look like this:
<blockquote id="q1"> <p>They went in single file, running like hounds on a strong scent, and an eager light was in their eyes. Nearly due west the broad swath of the marching Orcs tramped its ugly slot; the sweet grass of Rohan had been bruised and blackened as they passed.</p> </blockquote>
and the RDF/XML looks like this:
<rdf:Description about="#q1"> <xh11:cite href="http://www.mycom.com/tolkien/twotowers.html" /> </rdf:Description>
Whilst this approach gives unlimited flexibility, it has not been widely adopted outside the RDF community. It is certainly more difficult for an SVG or HTML author to learn, and so their documents tend to contain little 'extra' metadata. The motivation of RDF/A was to devise a means by which documents could be augmented with metadata, using property values from the growing range of available taxonomies. In RDF/A, one way that the example given above could be marked-up is as follows:
<blockquote> <link rel="dc:source" href="http://www.mycom.com/tolkien/twotowers.html" /> <p>They went in single file, running like hounds on a strong scent, and an eager light was in their eyes. Nearly due west the broad swath of the marching Orcs tramped its ugly slot; the sweet grass of Rohan had been bruised and blackened as they passed.</p> </blockquote>
We feel this proposal contributes to standardisation, and takes the pressure off language authors to anticipate all the metadata requirements users of their language might have -- in this example we have used "source" from the Dublin Core [DC] list, rather than inventing our own citation attribute which would be unknown to other languages. For example, the source could still be determined if the same quote were marked-up in SVG:
<svg:text> <link rel="dc:source" href="http://www.mycom.com/tolkien/twotowers.html" /> They went in single file, running like hounds on a strong scent, and an eager light was in their eyes. Nearly due west the broad swath of the marching Orcs tramped its ugly slot; the sweet grass of Rohan had been bruised and blackened as they passed. </svg:text>
We feel these aspects of our proposal are crucial to the future of the Semantic Web, and the place of mark-up documents within it.
This proposal therefore outlines a new XML syntax for RDF that relies only on XML attributes, and so can be easily imported into other markup languages allowing them to carry arbitrary RDF.
In the following examples, for brevity assume that the following namespace prefixes are defined:
cc: | http://web.resource.org/cc/ |
dc: | http://purl.org/dc/elements/1.1/ |
ex: | http://example.org/ |
foaf: | http://xmlns.com/foaf/0.1/ |
rdf: | http://www.w3.org/1999/02/22-rdf-syntax-ns# |
rdfs: | http://www.w3.org/2000/01/rdf-schema# |
svg: | http://www.w3.org/2000/svg |
xh11: | http://www.w3.org/1999/xhtml |
xsd: | http://www.w3.org/2001/XMLSchema# |
This document uses the following terminology defined in [RDF-CONCEPTS]:
URI reference
literal
plain literal
typed literal
XML literal
XML value
node
blank node
triple
RDF graph
We also add two further concepts, an [RDF/A element] and the [context statement] both of which are explained in the processing section.
The aim of RDF/A is to allow [RDF graph]s to be carried in XML documents of any type. An [RDF graph] comprises [node]s linked by relationships. The basic unit of a graph is a [triple], in which a subject [node] is linked to an object [node] via a [predicate]. The subject [node] is always either an [RDF URI reference] or a [blank node], the predicate is always an [RDF URI reference], and the object of a statement can be an [RDF URI reference], a [literal], or a [blank node].
In RDF/A, an [RDF URI
reference] is indicated using the attribute about
and predicates are represented using one of the attributes
property
, rel
, or rev
. Objects which are [RDF URI reference]s
are represented using the attribute href
, whilst objects that are [literal]s are represented either with the
attribute content
, or the content of the element in question.
Most of the examples in this document are shown translated into N-Triples [N-TRIPLES] syntax, with a slight variation in that QNames can be used to replace a URI reference. To tell them apart, the QName will have no angle brackets, e.g. the triple:
<http://internet-apps.blogspot.com/> dc:creator "Mark Birbeck" .
should be read as an abbreviation for the N-Triples syntax:
<http://internet-apps.blogspot.com/> <http://purl.org/dc/elements/1.1/creator> "Mark Birbeck" .
Datatypes can also be abbreviated, so the following:
<> dc:title "E = mc<sup>2</sup>: The Most Urgent Problem of Our Time"^^rdf:XMLLiteral .
should be read as an abbreviation for this N-Triples statement:
<> <http://purl.org/dc/elements/1.1/creator> "E = mc<sup>2</sup>: The Most Urgent Problem of Our Time"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral> .
xml:base
All [RDF URI references] are subject to xml:base
[XML-BASE]. Note
that this means that in the absence of an xml:base
attribute, the document containing the RDF statements is
itself the base.
An example follows to show how xml:base
affects the subject:
<span xml:base="http://internet-apps.blogspot.com/"> <link about="" rel="dc:creator" href="http://www.blogger.com/profile/1109404"> <meta property="dc:title" content="Internet Applications" /> </link> </span>
The triples generated would be as follows:
<http://internet-apps.blogspot.com/> dc:creator <http://www.blogger.com/profile/1109404> . <http://internet-apps.blogspot.com/> dc:title "Internet Applications" .
The main idea behind the syntax for RDF/A is that it should be possible to represent a [triple] using only one XML element. In this way it owes more to 'flat' syntaxes like RDF/N3 [N3-PRIMER] than it does to RDF/XML [RDF-SYNTAX], despite its use of XML.
RDF/A provides a set of attributes that can be used to indicate the different parts of a [triple] on an element. For example, to indicate the creator of the blog 'Internet Applications' (using the Dublin Core taxonomy), we could use one of the following constructs:
<meta about="http://internet-apps.blogspot.com/" property="dc:creator" content="Mark Birbeck" />
or:
<link about="http://internet-apps.blogspot.com/" rel="dc:creator" href="http://www.blogger.com/profile/1109404" />
or:
<link about="http://www.blogger.com/profile/1109404" rev="dc:creator" href="http://internet-apps.blogspot.com/" />
Each of these statements contains a subject, predicate and object. In
the case where the predicate is designated by property
the object is a [plain literal], whilst in the case
of rel
or rev
the object is an [RDF URI reference]. The
[triple]s generated from these examples are:
<http://internet-apps.blogspot.com/> dc:creator "Mark Birbeck" . <http://internet-apps.blogspot.com/> dc:creator <http://www.blogger.com/profile/1109404> . <http://internet-apps.blogspot.com/> dc:creator <http://www.blogger.com/profile/1109404> .
Note that the second and third examples generate exactly the same [triple]s.
This is because when rev
is used for the predicate, a [triple] is generated with the subject and object
reversed.
It is also perfectly valid to have both attributes on the same element:
<link about="http://internet-apps.blogspot.com/" rel="dc:creator" rev="foaf:homepage" href="http://www.blogger.com/profile/1109404" />
If both attributes are provided -- as in this example -- then two [triple]s are generated, as follows:
<http://internet-apps.blogspot.com/> dc:creator <http://www.blogger.com/profile/1109404> . <http://www.blogger.com/profile/1109404> foaf:homepage <http://internet-apps.blogspot.com/> .
And it's also possible to go further and add the attributes used for denoting statements in which the object is a [literal]. For example:
<link about="http://internet-apps.blogspot.com/" rel="dc:creator" rev="foaf:homepage" href="http://www.blogger.com/profile/1109404" property="dc:title" content="Internet Applications" />
The triples generated would be as follows:
<http://internet-apps.blogspot.com/> dc:creator <http://www.blogger.com/profile/1109404> . <http://www.blogger.com/profile/1109404> foaf:homepage <http://internet-apps.blogspot.com/> . <http://internet-apps.blogspot.com/> dc:title "Internet Applications" .
It's possible to do all of this without ambiguity, since the property
attribute always denotes a predicate in a
statement in which the object is a [literal], whilst the rel
and rev
attributes always denote a predicate
in a statement in which the object
is a [URI reference]. Put a different way, property
always works with content
, whilst rel
and rev
work with
href
.
Note:
This last example illustrates that although in this document we generally use meta
to designate statements about [literal]s
and link
to designate statements about [RDF URI reference]s this is merely a convention, and it is in fact the attributes
that do all the work, not the elements that contain them.
A second feature of RDF/A is that it is possible to use parts of the host document to provide the [subject] of a [triple]. This marks RDF/A from other approaches to serialising RDF, in that the the same syntax can now be used to make statements about parts of a document, and external documents.
Although it is possible to make these statements using the syntax introduced in the examples above, we provide an alternative -- and more flexible -- approach. For example, we could simply indicate the source of a quote using the following mark-up:
<html xmlns:dc="http://purl.org/dc/elements/1.1/"> <head> <title>On <em>Crime and Punishment</em></title> <link about="#q1" rel="dc:source" href="urn:isbn:0140449132" /> </head> <body> <blockquote id="q1"> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote> </body> </html>
However, RDF/A provides another mechanism, which is that if a link
or meta
element is used, and no [subject]
is present, then
the [triple] concerns the parent of the element. This allows the example above to be recast as follows:
<html xmlns:dc="http://purl.org/dc/elements/1.1/"> <head> <title>On <em>Crime and Punishment</em></title> </head> <body> <blockquote id="q1"> <link rel="dc:source" href="urn:isbn:0140449132" /> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote> </body> </html>
This syntax only applies to the elements link
and meta
, which means that even without an id
attribute, the following
statement is still 'about' the blockquote
element, and not the body
element:
<blockquote rel="dc:source" href="urn:isbn:0140449132"> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote>
Although originally motivated for XHTML 2 The attributes and elements described in this document allow metadata to be layered onto XML elements from other namespaces. A typical example -- shown above -- might be to describe the source of a quote in an XHTML document:
<html xmlns:dc="http://purl.org/dc/elements/1.1/"> <head> <title>On <em>Crime and Punishment</em></title> </head> <body> <blockquote rel="dc:source" href="urn:isbn:0140449132"> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote> </body> </html>
If
more than one piece of metadata needs to be attached to the same
element, then the attributes can be attached to child elements.
Although any elements could be used to carry the attributes, in this
document we generally use the elements meta
and link
, so as to
highlight whether the statement is about a [literal] or a [URI reference]:
<html xmlns:dc="http://purl.org/dc/elements/1.1/"> <head> <title>On <em>Crime and Punishment</em></title> </head> <body> <blockquote> <link rel="dc:source" href="urn:isbn:0140449132" /> <meta property="dc:creator" content="Fyodor Dostoevsky" /> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote> </body> </html>
Now we have attached two pieces of metadata to the blockquote
element -- the source of the quote, and its
author.
Note:
We say nothing here about how this metadata is used. In the previous example, the information may be of use to an RDF/A-aware browser, and it could be made available to the user accessing the page via a mechanism such as tooltips. But it may also be the case that the document is parsed by some external processor and the output stored as a set of [triple]s. In the latter case the [triple]s generated by the previous example would have a [unique anonymous ID] as the subject of each statement, as follows:
_:a dc:source <urn:isbn:0140449132> . _:a dc:creator "Fyodor Dostoevsky" .
The previous section shows two types of [RDF/A statement]s. The first is a [global statement], which is self-contained, in that it produces a complete [triple]. It is possible to place this statement anywhere in the containing document, and still generate the same [triple].
This is illustrated in the following two examples; the first locates the metadata statement inside the actual quote:
<html xmlns:dc="http://purl.org/dc/elements/1.1/"> <head> <title>On <em>Crime and Punishment</em></title> </head> <body> <blockquote> <meta about="urn:isbn:0140449132" property="dc:creator" content="Fyodor Dostoevsky" /> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote> </body> </html>
whilst the second places it in the head
element:
<html xmlns:dc="http://purl.org/dc/elements/1.1/"> <head> <title>On <em>Crime and Punishment</em></title> <meta about="urn:isbn:0140449132" property="dc:creator" content="Fyodor Dostoevsky" /> </head> <body> <blockquote> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote> </body> </html>
The [triple]s generated are in both cases:
<urn:isbn:0140449132> dc:creator "Fyodor Dostoevsky" .
For an [RDF/A statement] using link
or meta
to be a [global statement], a subject must
be present, otherwise it is a [qualifying statement] (see below). However, if any other element is used in a
[RDF/A statement] then the statement will always be a [global statement]. For example:
<html xmlns:dc="http://purl.org/dc/elements/1.1/"> <head> <title>On <em>Crime and Punishment</em></title> </head> <body> <blockquote rel="dc:source" href="urn:isbn:0140449132"> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote> </body> </html>
Here the blockquote
element has no subject, but since it is neither link
nor meta
, the predicate
and object refer to the element itself, and so an anonymous node is created:
_:a dc:source <urn:isbn:0140449132> .
Note:
The idea that it does not matter where [global statement]s appear in the document is true even
if the [global statement] is contained within a link
or meta
element. The
following two sets of mark-up therefore generate exactly the same [triple]s:
<link about="mailto:daniel.brickley@bristol.ac.uk" rel="foaf:knows" href="mailto:libby.miller@bristol.ac.uk" /> <link about="mailto:libby.miller@bristol.ac.uk" rel="foaf:knows" href="mailto:ian.sealy@bristol.ac.uk" />
<link about="mailto:daniel.brickley@bristol.ac.uk" rel="foaf:knows" href="mailto:libby.miller@bristol.ac.uk"> <link about="mailto:libby.miller@bristol.ac.uk" rel="foaf:knows" href="mailto:ian.sealy@bristol.ac.uk" /> </link>
The second type of statement shown in the previous section is a [qualifying statement]. This is a statement that cannot stand on its own, but provides information about its parent element. It was illustrated in the previous section by the following example:
<html xmlns:dc="http://purl.org/dc/elements/1.1/"> <head> <title>On <em>Crime and Punishment</em></title> </head> <body> <blockquote> <link rel="dc:source" href="urn:isbn:0140449132" /> <meta property="dc:creator" content="Fyodor Dostoevsky" /> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote> </body> </html>
A [qualifying statement] is any statement made using meta
or link
that does not have a subject. This means that
the subject will be derived in some way from the parent element.
Further metadata is often available to qualify a statement that has been made. In the previous example we said that a quote is from the book Crime and Punishment, and that the quote was by Dostoevsky:
<blockquote> <link rel="dc:source" href="urn:isbn:0140449132" /> <meta property="dc:creator" content="Fyodor Dostoevsky" /> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote>
However, we could have more accurately indicated the origin of the quote, and then gone on to add that the book was written by Dostoevsky:
<blockquote> <link rel="dc:source" href="urn:isbn:0140449132" /> <meta about="urn:isbn:0140449132" property="dc:creator" content="Fyodor Dostoevsky" /> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote>
Now our triples would be as follows:
_:a dc:source <urn:isbn:0140449132> . <urn:isbn:0140449132> dc:creator "Fyodor Dostoevsky" .
In this example, the [qualifying statement] does not depend on the
[global statement] in any way, which means that the meta
element (the [global statement]) could be placed anywhere in the document to obtain the same [triple]s.
In this section we look in more detail at the [triple]s that are generated when using RDF/A attributes and elements. We've already said that the aim is to make it possible to generate a [triple] with one element. However, we also saw that if our various attributes and elements are used as children of some element then they augment that element with their values. We therefore need to understand how the subject, predicate and object parts of a [triple] are established from our syntax.
An [RDF/A element] is defined as any XML element that contains one or more RDF/A attributes. Processing proceeds by examining each [RDF/A element] in turn. The [RDF/A element] under consideration at any time is the [current statement], and its parent element is the [context statement]. Note that the [context statement] does not need to be an [RDF/A element].
As each [RDF/A element] is examined the processor tries to establish as many sets of subject, predicate and object -- based on the the rules outlined in the remainder of this section -- as it can. For each set established a triple is generated, so whilst this means that more than one triple might be generated for an [RDF/A element], it is also valid for no [triple]s to be generated. This allows certain useful abbreviations to be used.
about
attribute
The subject of a triple is usually indicated using the about
attribute, as follows:
<link about="mailto:daniel.brickley@bristol.ac.uk" rel="foaf:knows" href="mailto:libby.miller@bristol.ac.uk" /> <link about="mailto:libby.miller@bristol.ac.uk" rel="foaf:knows" href="mailto:ian.sealy@bristol.ac.uk" />
This syntax will usually be used when the statements being made are not pertinent to the document containing them, as shown here:
<blockquote> <meta about="urn:isbn:0140449132" property="dc:creator" content="Fyodor Dostoevsky" /> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote>
However, it is possible to use this syntax to refer to parts of the
containing document, provided the element being referred to has an
attribute of type xml:id
. For example, we could once again indicate the source of a quote, using the following
syntax:
<html xmlns:dc="http://purl.org/dc/elements/1.1/"> <head> <title>On <em>Crime and Punishment</em></title> <link about="#q1" rel="dc:source" href="urn:isbn:0140449132" /> </head> <body> <blockquote id="q1"> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote> </body> </html>
Our triples would be:
<#q1> dc:source <urn:isbn:0140449132> .
nodeID
Although the FOAF [FOAF-PROJECT] example used in the previous section is valid, it is more common to say 'a person knows the person with the email address of ...', than it is to say that 'a resource with the [URI reference] of A knows the resource with a [URI reference] of B'.
The triples generated by our previous example, would be.
<mailto:daniel.brickley@bristol.ac.uk> foaf:knows <mailto:libby.miller@bristol.ac.uk> . <mailto:libby.miller@bristol.ac.uk> foaf:knows <mailto:ian.sealy@bristol.ac.uk> .
but the following would be more accurate:
_:a foaf:mbox <mailto:daniel.brickley@bristol.ac.uk> . _:b foaf:mbox <mailto:libby.miller@bristol.ac.uk> . _:a foaf:knows _:b .
In other words, the 'thing' with an email address of A knows the 'thing' with an email address of B.
A [node] with no [URI reference] is a [blank node], but RDF provides
the notion of a [unique anonymous ID] to allow [blank node]s to be
distinguished from each other. RDF/A allows the creation of [unique
anonymous ID]s either explicitly, using the nodeID
attribute, or implicitly, as described in section 4.2.4.4.
The nodeID
attribute could be used to mark-up the two [blank node]s in our previous example, as follows:
<link nodeID="a" rel="foaf:mbox" href="mailto:daniel.brickley@bristol.ac.uk" /> <link nodeID="b" rel="foaf:mbox" href="mailto:libby.miller@bristol.ac.uk" />
To refer to the [blank node]s we use an XPointer Framework [XPOINTER-FRAMEWORK] scheme-based pointer of "bnode", as illustrated here:
<link about="#bnode(a)" rel="foaf:knows" href="#bnode(b)" />
[1] | BnodeSchemeData | ::= | (NCName) |
An implementation of the bnode() scheme can return a [unique anonymous
ID] in any valid format that meets the requirements of [RDF-CONCEPTS]. However, the same processor should always return the same value for the same input. In addition, it is not
an error if the parameter does not refer to a value used in a nodeID
attribute.
xml:id
If an [RDF/A element] does not contain an about
attribute, but does contain an attribute of type xml:id
then this is used for the subject. With this syntax, the previous
example could also be represented as follows:
<html xmlns:dc="http://purl.org/dc/elements/1.1/"> <head> <title>On <em>Crime and Punishment</em></title> </head> <body> <blockquote id="q1" rel="dc:source" href="urn:isbn:0140449132"> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote> </body> </html>
This generates exactly the same [triple] as before:
<#q1> dc:source <urn:isbn:0140449132> .
If neither an about
attribute, nor a nodeID
attribute, nor an attribute of type xml:id
is present,
then the subject of the
[context statement] is used. If the [context statement] has a nodeID
attribute, this is used first; if it has an
about
attribute that is used next, and if an attribute of type xml:id
is present, that is used. If no explicit subject
is present, a [unique anonymous ID] is generated, based on the [context statement].
nodeID
attributeIf the [context statement] had its subject set with a nodeID
attribute, then that is used for the subject. The following
example shows an omitted subject, but since there is a nodeID
attribute
present on the parent element, this is used as the subject:
<blockquote nodeID="a"> <link rel="dc:source" href="urn:isbn:0140449132" /> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote>
The triples generated are:
_:a dc:source <urn:isbn:0140449132> .
about
attributeIn the following example we have omitted about
from line 2, but since the parent element contains
an about
attribute, that becomes the subject of both the nested statement, and the parent statement:
<link about="http://internet-apps.blogspot.com/" rel="dc:creator" href="http://www.blogger.com/profile/1109404"> <meta property="dc:title" content="Internet Applications" /> </link>
This is exactly equivalent to making two separate statements, as follows:
<link about="http://internet-apps.blogspot.com/" rel="dc:creator" href="http://www.blogger.com/profile/1109404" /> <meta about="http://internet-apps.blogspot.com/" property="dc:title" content="Internet Applications" />
The triples generated are as follows:
<http://internet-apps.blogspot.com/> dc:creator <http://www.blogger.com/profile/1109404> . <http://internet-apps.blogspot.com/> dc:title "Internet Applications" .
Note:
This pair of triples could also have been marked-up in this way:
<meta about="http://internet-apps.blogspot.com/" content="Internet Applications"> <link rel="dc:creator" href="http://www.blogger.com/profile/1109404" /> </meta>
However, this syntax should be used with some caution, since as we shall see later, if the content
attribute is omitted then the object is obtained from the mark-up inside the meta
element, and the datatype is set to a [typed literal] with a datatype
of [XML literal]. This would mean that if the previous example were
modified to remove the content
attribute, as shown here:
<meta about="http://internet-apps.blogspot.com/"> <link rel="dc:creator" href="http://www.blogger.com/profile/1109404" /> </meta>
then the mark-up would now only represent one [triple] and not two:
<http://internet-apps.blogspot.com/> dc:title '<link rel="dc:creator" href="http://www.blogger.com/profile/1109404" />'^^rdf:XMLLiteral .
id
attributeIt's also possible that the [context statement] had its subject set with an attribute of type xml:id
. The following
example shows once
again an omitted subject, but in this case since there is an attribute of type xml:id
present on the [context statement], this is used as the subject:
<blockquote id="q1"> <link rel="dc:source" href="urn:isbn:0140449132" /> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote>
The triples generated are exactly as with our earlier examples using xml:id
:
<#q1> dc:source <urn:isbn:0140449132> .
If the [context statement] also has no subject, then the subject is a [unique anonymous ID]. The following example was shown earlier:
<blockquote> <link rel="dc:source" href="urn:isbn:0140449132" /> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote>
and generates the following triples:
_:a dc:source <urn:isbn:0140449132> .
Note that the [unique anonymous ID] is generated for the [context statement] and not for the [current statement]. This allows further statements to be made about the same [blank node]. For example:
<blockquote> <link rel="dc:source" href="urn:isbn:0140449132" /> <meta property="dc:creator" content="Fyodor Dostoevsky" /> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote>
would generate these triples:
_:a dc:source <urn:isbn:0140449132> . _:a dc:creator "Fyodor Dostoevsky" .
and not these:
_:a dc:source <urn:isbn:0140449132> . _:b dc:creator "Fyodor Dostoevsky" .
However, if the second statement was nested within the first:
<blockquote> <link rel="dc:source" href="urn:isbn:0140449132"> <meta property="dc:creator" content="Fyodor Dostoevsky" /> </link> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote>
then we would indeed obtain the following triples:
_:a dc:source <urn:isbn:0140449132> . _:b dc:creator "Fyodor Dostoevsky" .
The predicate of a statement is usually specified using a property
, rel
or rev
attribute. These attributes can be placed on any element in a document,
and -- although readability may suffer -- can even co-exist on the same
element.
property
attribute
If the predicate is expressed using the property
attribute, then the object of the statement will be a [literal]. The
actual value of the [literal] is discussed in a later section. The
following example indicates the name of the author responsible for the
text being quoted:
<html xmlns:dc="http://purl.org/dc/elements/1.1/"> <head> <title>On <em>Crime and Punishment</em></title> </head> <body> <blockquote property="dc:creator" content="Fyodor Dostoevsky"> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote> </body> </html>
rel
attribute
If the predicate is expressed using the rel
attribute, then the object of the statement will be a [URI reference].
The actual value of the [URI reference] is discussed in the next
section. The following example indicates that one 'FOAF person' knows
another:
<link about="mailto:daniel.brickley@bristol.ac.uk" rel="foaf:knows" href="mailto:libby.miller@bristol.ac.uk" />
The triple generated is:
<mailto:daniel.brickley@bristol.ac.uk> foaf:knows <mailto:libby.miller@bristol.ac.uk> .
rev
attribute
If the predicate is expressed using the rev
attribute, then the three parts of the [triple] generated have the same values
as they would have had, had the rel
attribute been used, except that the subject and object are reversed. The following
example indicates that one
'FOAF person' knows another:
<link about="mailto:daniel.brickley@bristol.ac.uk" rev="foaf:knows" href="mailto:libby.miller@bristol.ac.uk" />
and the [triple] generated is essentially a reversal of our previous example:
<mailto:libby.miller@bristol.ac.uk> foaf:knows <mailto:daniel.brickley@bristol.ac.uk> .
If a predicate is not specified for a particular object then the predicate of the statement is determined from the property with the same name in the [context statement]. If there isn't one, then a default predicate of "hasReferenceTo" is used.
In the following example we have a FOAF person that knows some other people:
<link about="mailto:daniel.brickley@bristol.ac.uk" rel="foaf:knows" href="mailto:libby.miller@bristol.ac.uk"> <link rel="foaf:knows" href="mailto:ian.sealy@bristol.ac.uk" /> <link rel="foaf:knows" href="mailto:m.l.poulter@bristol.ac.uk" /> </link>
According to our rules for setting the subject, all of the statements contained by the outer element will have a subject of <mailto:daniel.brickley@bristol.ac.uk>. However, it is also possible to make use of the predicate on the containing element, as follows:
<link about="mailto:daniel.brickley@bristol.ac.uk" rel="foaf:knows" href="mailto:libby.miller@bristol.ac.uk"> <link href="mailto:ian.sealy@bristol.ac.uk" /> <link href="mailto:m.l.poulter@bristol.ac.uk" /> </link>
A further refinement would be to place all of the objects inside the container:
<link about="mailto:daniel.brickley@bristol.ac.uk" rel="foaf:knows"> <link href="mailto:libby.miller@bristol.ac.uk" /> <link href="mailto:ian.sealy@bristol.ac.uk" /> <link href="mailto:m.l.poulter@bristol.ac.uk" /> </link>
The triples generated for all of the preceding examples are:
<mailto:daniel.brickley@bristol.ac.uk> foaf:knows <mailto:libby.miller@bristol.ac.uk> . <mailto:daniel.brickley@bristol.ac.uk> foaf:knows <mailto:ian.sealy@bristol.ac.uk> . <mailto:daniel.brickley@bristol.ac.uk> foaf:knows <mailto:m.l.poulter@bristol.ac.uk> .
Note:
As can be seen this is an application of two rules, in that we are inheriting both the predicate and subject. Whilst this is the most likely usage, the following permutation is also valid, although may be slightly more difficult for the human reader to decipher:
<!-- Let's make loads of 'FOAF knows' statements: --> <link about="mailto:daniel.brickley@bristol.ac.uk" rel="foaf:knows" rev="foaf:knows" href="mailto:libby.miller@bristol.ac.uk"> <link about="mailto:libby.miller@bristol.ac.uk" href="mailto:ian.sealy@bristol.ac.uk" /> <link about="mailto:ian.sealy@bristol.ac.uk" href="mailto:m.l.poulter@bristol.ac.uk" /> <link href="mailto:ian.sealy@bristol.ac.uk" /> <link href="mailto:m.l.poulter@bristol.ac.uk" /> </link>
The triples generated are below (note that each element actually generates two triples, since both rel
and
rev
are present):
<mailto:daniel.brickley@bristol.ac.uk> foaf:knows <mailto:libby.miller@bristol.ac.uk> . <mailto:libby.miller@bristol.ac.uk> foaf:knows <mailto:daniel.brickley@bristol.ac.uk> . <mailto:libby.miller@bristol.ac.uk> foaf:knows <mailto:ian.sealy@bristol.ac.uk> . <mailto:ian.sealy@bristol.ac.uk> foaf:knows <mailto:libby.miller@bristol.ac.uk> . <mailto:ian.sealy@bristol.ac.uk> foaf:knows <mailto:m.l.poulter@bristol.ac.uk> . <mailto:m.l.poulter@bristol.ac.uk> foaf:knows <mailto:ian.sealy@bristol.ac.uk> . <mailto:daniel.brickley@bristol.ac.uk> foaf:knows <mailto:ian.sealy@bristol.ac.uk> . <mailto:ian.sealy@bristol.ac.uk> foaf:knows <mailto:daniel.brickley@bristol.ac.uk> . <mailto:daniel.brickley@bristol.ac.uk> foaf:knows <mailto:m.l.poulter@bristol.ac.uk> . <mailto:m.l.poulter@bristol.ac.uk> foaf:knows <mailto:daniel.brickley@bristol.ac.uk> .
If the predicate is omitted, and the [context statement] also has no predicate, then a default value of "hasReferenceTo" is used if the object is a [literal]. The most common usage of this syntax is to indicate that some text in a document actually has a useful value that is different to the actual text. Through this mechanism it is possible to provide normalised values, such as dates, names for countries and people, and so on.
An example may make this clearer. If we have an article that refers to :
Editorial note | |
Need to find a few good examples. |
The object of the statement can be set using one of the attributes content
or href
. Which attribute is
used depends on how the predicate was set. If the predicate was set using property
then the object will be a [literal],
and its value will come from the content
attribute. If the predicate was set with either rel
or rev
, then
the object will be a [URI reference], and its value will come from the href
attribute.
content
attributeThe content
attribute can be used to indicate a [plain literal] as follows:
<meta about="http://internet-apps.blogspot.com/" property="dc:creator" content="Mark Birbeck" />
href
attributeThe href
attribute can be used to indicate a [URI reference] as follows:
<link about="mailto:daniel.brickley@bristol.ac.uk" rel="foaf:knows" href="mailto:libby.miller@bristol.ac.uk" /> <link about="mailto:daniel.brickley@bristol.ac.uk" rev="foaf:knows" href="mailto:libby.miller@bristol.ac.uk" />
During the processing of each statement, a check is made on the [context statement] to see if it has a predicate but no object. If it does, then a triple is generated which has the subject and predicate provided by the [context statement], but with the object set to the subject of the statement being evaluated.
For example, given the following mark-up :
<link nodeID="a" rel="foaf:depiction"> <link about="http://www.ilrt.bristol.ac.uk/people/cmdjb/events/dc7/orig/eric.png"> <link rel="rdf:type" href="http://xmlns.com/foaf/0.1/Image" /> <link rel="dc:thumbnail" href="http://www.ilrt.bristol.ac.uk/people/cmdjb/events/dc7/orig/eric.png" /> <meta property="dc:title" content="Eric Miller, relaxing." /> <meta property="dc:description" content="Eric Miller, relaxing." /> <meta property="dc:format" content="image/png" /> </link> </link>
a processor would proceed as follows:
The first line does not contain an object, so nothing is generated.
The second line does not contain a predicate or an object, so nothing is generated. However, the [context statement] has no object so a [triple] is generated with the subject and object provided by the [context statement], and the object provided by the subject in the statement being evaluated. The [triple] generated would be:
_:a foaf:depiction <http://www.ilrt.bristol.ac.uk/people/cmdjb/events/dc7/orig/eric.png> .
The third line does not contain a subject, so the subject for the [context statement] is used, yielding the following triples:
<http://www.ilrt.bristol.ac.uk/people/cmdjb/events/dc7/orig/eric.png> rdf:type foaf:Image .
The remaining lines also do not contain subjects, so in each case the subject for the [context statement] is used, giving the following triples:
<http://www.ilrt.bristol.ac.uk/people/cmdjb/events/dc7/orig/eric.png> dc:thumbnail <http://www.ilrt.bristol.ac.uk/people/cmdjb/events/dc7/orig/eric.png> . <http://www.ilrt.bristol.ac.uk/people/cmdjb/events/dc7/orig/eric.png> dc:title "Eric Miller, relaxing." . <http://www.ilrt.bristol.ac.uk/people/cmdjb/events/dc7/orig/eric.png> dc:description "Eric Miller, relaxing." . <http://www.ilrt.bristol.ac.uk/people/cmdjb/events/dc7/orig/eric.png> dc:format "image/png" .
Note also that although in each case the [context statement] does not contain an object, since it also does not contain a predicate then no further triples are generated.
Having established the different parts of the syntax of RDF/A, we will now look at the various aspects of the RDF Abstract Syntax, and see how they can be represented in RDF/A.
When the object of a statement is a [plain literal], then the value of the object
is provided by the content
attribute. For example, say the author of a blog is
represented by the following triples:
<http://internet-apps.blogspot.com/> dc:creator "Mark Birbeck" .
If the blog was marked up using XHTML 1.1, then this triple could be encoded with RDF/A as follows:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Internet Applications</title> <meta about="http://internet-apps.blogspot.com/" property="dc:creator" content="Mark Birbeck" /> </head> <body>My blog.</body> </html>
RDF allows [plain literal]s to have a language tag, as illustrated by the following example from [RDFTESTS-RDFMS-XMLLANG-TEST006]:
<http://example.org/node> <http://example.org/property> "chat"@fr .
In RDF/A the XML language attribute -- xml:lang
-- is used to add this information:
<meta about="http://example.org/node" property="ex:property" xml:lang="fr" content="chat" />
Note that the value can be inherited as defined in [XML-LANG], so the following syntax will give the same triple as above:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr"> <head> <title xml:lang="en">Example</title> <meta about="http://example.org/node" property="ex:property" content="chat" /> </head> ... </html>
RDF allows [literal]s to be given a data type, as illustrated by the following example from [RDFTESTS-DATATYPES-TEST001]:
<http://example.org/foo> <http://example.org/bar> "10"^^<http://www.w3.org/2001/XMLSchema#integer> .
This can be represented in RDF/A as follows:
<meta about="http://example.org/foo" property="ex:bar" content="10" datatype="xsd:integer" />
XML documents cannot contain XML mark-up in their attributes, which
means it is not possible to represent XML within the content
attribute. The following would cause an XML parser to generate an error:
<head about=""> <meta property="dc:creator" content="Albert Einstein" /> <meta property="dc:title" content="E = mc<sup>2</sup>: The Most Urgent Problem of Our Time" /> </head>
It does not help to escape the content, since the output would simply be a string of text containing numerous ampersands:
<> dc:title "E = mc<sup>2</sup>: The Most Urgent Problem of Our Time" .
RDF does, however, provide a datatype for indicating [XML literal]s. RDF/A therefore adds this datatype to any [literal] that is indicated using child text nodes on the [RDF/A statement]. For example:
<head about=""> <meta property="dc:creator" content="Albert Einstein" /> <meta property="dc:title">E = mc<sup>2</sup>: The Most Urgent Problem of Our Time</meta> </head>
would generate:
<> dc:creator "Albert Einstein" . <> dc:title "E = mc<sup>2</sup>: The Most Urgent Problem of Our Time"^^rdf:XMLLiteral .
A [blank node] is generated either when the attribute nodeID
is present, or when both the [current statement] and the [context
statement] have no subject. In the latter case, the [unique anonymous
ID] generated to identify the [blank node] is associated with the
[context statement], and not the statement currently being evaluated.
This allows a number of statements to be made about the same [blank
node], as shown in an earlier example, and repeated here:
<blockquote> <link rel="dc:source" href="urn:isbn:0140449132" /> <meta property="dc:creator" content="Fyodor Dostoevsky" /> <p> Rodion Romanovitch! My dear friend! If you go on in this way you will go mad, I am positive! Drink, pray, if only a few drops! </p> </blockquote>
This would generate the following [triple]s:
_:a dc:source <urn:isbn:0140449132> . _:a dc:creator "Fyodor Dostoevsky" .
To establish relationships between [blank node]s the [unique anonymous
ID] must be either set explicity using the nodeID
attribute, or the statements must be nested.
statements. For example, if our desired output is the following [triple]s:
_:a foaf:mbox mailto:daniel.brickley@bristol.ac.uk . _:b foaf:mbox mailto:libby.miller@bristol.ac.uk . _:a foaf:knows _:b .
we could either use explicit [unique anonymous ID]s:
<link nodeID="a" rel="foaf:mbox" href="mailto:daniel.brickley@bristol.ac.uk" /> <link nodeID="b" rel="foaf:mbox" href="mailto:libby.miller@bristol.ac.uk" /> <link about="#bnode(a)" rel="foaf:knows" href="#bnode(b)" />
or implicit [unique anonymous ID]s, by nesting the statements:
<link rel="foaf:mbox" href="mailto:daniel.brickley@bristol.ac.uk"> <link rel="foaf:knows"> <link rel="foaf:mbox" href="mailto:libby.miller@bristol.ac.uk" /> </link> </link>
The processing steps for the implicit approach, are:
The first line has no explicit subject, so a triple with a [unique anonymous ID] for the subject, is generated:
_:a foaf:mbox mailto:daniel.brickley@bristol.ac.uk .
The second line has no subject, but since it also has no object, nothing is generated.
The third line has no explicit subject, so a triple with a [unique anonymous ID] for the subject, is generated:
_:b foaf:mbox mailto:libby.miller@bristol.ac.uk .
Whilst processing the third line, a check is also made for on the [context statement] for a predicate with no object. Since this is the case, a triple is generated with the subject and predicate from the [context statement] and with the object set to the value of the subject from the [current statement]. Note that the subject of the second line is evaluated in the usual way, and so is actually the subject of the first line, which in this case is the first [unique anonymous ID]:
_:a foaf:knows _:b .
One of the advantages of using the same syntax to make general statements as well as statements about a document is that in many cases a document can carry its own metadata. For example, if an XHTML document contains a navigable link to the Creative Commons license, this link can also be used to express metadata:
<p> 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>. </p>
The statements are not, however, about the document -- the two anchors in this example will generate two unique [anonymous node]s:
_:a cc:license <http://creativecommons.org/licenses/by-sa/2.0/> _:b dc:creator <http://ben.adida.net>
Editorial note | |
The following is now slightly out of sync with the text above. |
Editorial note | |
The following will be converted to a GRDDL format. |
<!-- CS is the [current statement], and CTX is the [context statement] --> <!-- A function for establishing the subject given an element --> function subj(e) { var s = null; var p = e.parent; if (e.about) s = e.about; else if (e.nodeID) s = "_:" + e.nodeID; else if (e.id) s = base + "#" + e.id; else if (p.about) s = p.about; else if (p.nodeID) s = "_:" + p.nodeID; else if (p.id) s = base + "#" + p.id; return s; } <!-- Establish the subject of this statement --> s = subj(CS); <!-- If we failed to establish a subject generate a bnode based on CTX. Also set the 'target' for CTX, if it needs it --> if (s) t = s; else { s = generated-blank-node-id(CTX); t = generated-blank-node-id(CS); } <!-- If CTX has @rel or @rev, with no @href, then use the 'target' set above to 'fill in the gaps'. --> sctx = subj(CTX); if (!sctx) sctx = generated-blank-node-id(CTX.parent); if (CTX.rel AND !CTX.href) generate-triple(sctx, CTX.rel, t), if (CTX.rev AND !CTX.href) generate-triple(sctx, CTX.rev, t), <!-- Now we can generate triples for CS --> if (CS.href) { o = CS.href; if (CS.rel OR CS.rev) { p1 = CS.rel; p2 = CS.rev; } else { if (CTX.rel OR CTX.rev) { p1 = CTX.rel; p2 = CTX.rev; } } if (s && p1 && o) generate-triple(s, p1, o); if (s && p2 && o) generate-triple(o, p2, s); } if (CS.content) { p = null; o = CS.content; if (CS.property) p = CS.property; else { if (CTX.property) p = CTX.property; } if (s && p && o) generate-triple(s, p, o); }