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
attributeThe 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
attributeIf 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
attributeIf 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
attributeIf 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); }