[This local archive copy mirrored from the canonical site: http://www.ccil.org/~cowan/XML/RDF-made-easy.html, 19980621; links may not have complete integrity, so use the canonical document at this URL if possible.]

RDF Made (Fairly) Easy

Disclaimer

This document reflects the W3C Working Draft Resource Description Framework (RDF) Model and Syntax: W3C Working Draft 16 February 1998. You should check the above URL; if it refers to some other Draft, then ignore this document or read it with a grain of salt.

There are or may be errors in this document. If you find any, please send email to John Cowan.

Introduction

Let me explain what this document is for. It isn't intended to replace the detailed formalism of the draft. Instead, it attempts to explain RDF from the simple cases to the general cases rather than the other way around. After reading this document, you should know how to encode metadata in XML in a way that complies with RDF. This document is structured rather like a newspaper article, with the most important material first. Consequently, you can stop reading it at any time, and hopefully you will still understand something about using RTF.

Rather than writing my own high-level introduction to RDF, I will refer you to Tim Bray's excellent RDF and Metadata explanation. Just imagine: if we had proper XLink support today, you'd actually see his document just above, transcluded into mine. But we don't, and you don't. So click on the link above, and when you are done reading it, come back here.

That was easy. You should now understand the terms "Resource", "Property", "PropertyType", "Vocabulary", and "Value", which will be used (capitalized) in this document a lot.

I'm assuming that you have a fair understanding of XML 1.0, and I won't spend any time explaining element types, elements, empty elements, attributes, or attribute values.

I also don't want to go into too much detail explaining namespaces, so just let me note one point here. I will be prefixing all RDF elements with RDF:. However, I won't be using RDF: on attributes, because it's assumed that attributes belong to the same namespace as their elements unless explicitly specified otherwise. So HREF means the same as RDF:HREF.

In your documents you can use whatever prefix you want (ending in a colon) as long as you insert a proper namespace declaration. The exact content of that namespace declaration hasn't been defined yet by the draft.

Finally, some URLs in this document appear in italics. That means that I have made them up, as the draft has not yet standardized them.

The Simplest RDF

Suppose you want to write some RDF giving a few Properties of a single Resource (remember that a Resource is anything you can locate with an URL or its persistent cousin, an URN). To be concrete, let's say you want to record some facts about this very document, whose URL is http://www.ccil.org/~cowan/XML/RDF-made-easy.html. The author of the document is John Cowan, and the title of the document is "RDF Made Easy". Here's one way of doing it:

    <RDF:RDF>
        <RDF:Description HREF="http://www.ccil.org/~cowan/XML/RDF-made-easy.html">
            <XX:Author>John Cowan</XX:Author>
            <XX:Title>RDF Made Easy</XX:Title>
        </RDF:Description>
    </RDF:RDF>

In other words, the PropertyTypes and Values are in sub-elements of the RDF:Description element, as element names and #PCDATA content respectively. The Resource is specified by the HREF attribute of the RDF:Description.

What's the XX: prefix all about? Well, we want to be able to distinguish between your use of Author and Title and other people's uses of the same names. So we suppose that your names are listed in a Vocabulary somewhere, and that the prefix used for that Vocabulary within this document is XX. Of course, you can use any prefix you like as long as you are consistent within a given document and provide a proper namespace declaration.

That's really all there is to it! You can have as many RDF:Description elements within a single RDF:RDF element as you want, and as many sub-elements within an RDF:Description element as you want, so you can describe lots of Properties of lots of Resources within one RDF document.

As a fairly minor convenience, you can use attributes of the RDF:Description element instead of child elements. So an equivalent form of the above example is:

    <RDF:RDF>
        <RDF:Description HREF="http://www.ccil.org/~cowan/XML/RDF-made-easy.html"
            XX:Author="John Cowan"
            XX:Title="RDF Made Easy"/>
    </RDF:RDF>

Here the RDF:Description element is empty, and has two extra properties XX:Author and XX:Title that give the PropertyTypes (as attribute names) and the Values (as attribute values) of the Properties.

You can't use the attribute names HREF, ID, or BAGID in this way, for reasons that will appear later.

Values Can Be Resources

Suppose you want the Value of a Property to be a Resource. You don't just put the URI of the Resource into the content of the child element that specifies the Property. Instead, you have to give that child element an HREF attribute. Don't confuse this one with the identically named attribute on an RDF:Description element.

Let's suppose you want to give the Home-Page of this document. You can write more RDF:

    <RDF:RDF>
        <RDF:Description HREF="http://www.ccil.org/~cowan/XML/RDF-made-easy.html">
            <XX:Home-Page HREF="http://www.ccil.org/~cowan"/>
        </RDF:Description>
    </RDF:RDF>

That tells you that the Home-Page of this document is http://www.ccil.org/~cowan. Note that since the child XX:Home-Page element has an HREF attribute, it mustn't also have #PCDATA content.

This method won't work with Properties specified as attributes. A Property specified as an attribute always has a simple string Value.

Making Collections

RDF provides a mechanism for creating collections, which are special kinds of Resources. A collection doesn't have to have its own URI, although it can. RDF supports three kinds of collections, bags, sequences, and alternatives, represented by RDF:Bag, RDF:Alt, and RDF:Seq elements respectively.

A bag is just a bunch of Values, either simple strings or Resources. To create a bag, use an RDF:Bag element containing RDF:LI elements. Here is a simple bag of color names:

    <RDF:RDF>
        <RDF:Bag>
           <RDF:LI>red</RDF:LI>
           <RDF:LI>green</RDF:LI>
           <RDF:LI>blue</RDF:LI>
        </RDF:Bag>
    </RDF:RDF>

And here's a bag of Resources:

    <RDF:RDF>
        <RDF:Bag>
           <RDF:LI HREF="http://www.xml.com/xml/pub/98/06/rdf.html"/>
           <RDF:LI HREF="http://www.ccil.org/~cowan"/>
           <RDF:LI HREF="http://www.w3.org/TR/WD-xml-names"/>
        </RDF:Bag>
    </RDF:RDF>

Note that RDF:LI elements use the same convention as property elements: either #PCDATA content for a simple string, or an HREF attribute for a Resource. A bag can contain a mixture of strings and Resources.

Sequences and alternatives are formally just like bags, except that order matters. In a sequence, the components are in the given order (bags have no order); in an alternative, the first RDF:LI element represents the default value of the collection and the other RDF:LI elements represent other possibilities. (Bags and sequences can be empty; alternatives can't, for there must be a default value available.)

Using Collections

How can you use a collection? A typical way to use it is as the immediate Value of a Property. You do this by placing the collection right inside a property element. Here's an example, where the Author of a paper is specified using a sequence. (Why not a bag? The order of authors on a paper is often important, that's why.)

    <RDF:RDF>
        <RDF:Description RDF:HREF="http://www.w3.org/TR/WD-rdf-syntax">
            <XX:Author>
                <RDF:Seq>
                    <RDF:LI>Tim Bray</RDF:LI>
                    <RDF:LI>Jean Paoli</RDF:LI>
                    <RDF:LI>C. M. Sperberg-McQueen</RDF:LI>
                <RDF:Seq>
            </XX:Author>
        </RDF:Description>
    </RDF:RDF>

In general, whenever a property element like XX:Author has neither #PCDATA content nor empty content, then its content must be some kind of RDF element, usually a collection.

If you don't want to put the collection directly into a property element, you can make it a child of an RDF:RDF element and give it an ID property. That gives the collection an actual URI, namely the URL of the document that contains it followed by #id where "id" is the value of the ID element, like this:

    <RDF:RDF>
        <RDF:Description HREF="http://www.w3.org/TR/WD-rdf-syntax">
            <XX:Author HREF="#XMLAuthors"/>
        </RDF:Description>
        <RDF:Seq ID="XMLAuthors">
            <RDF:LI>Tim Bray</RDF:LI>
            <RDF:LI>Jean Paoli</RDF:LI>
            <RDF:LI>C. M. Sperberg-McQueen</RDF:LI>
        <RDF:Seq>
    </RDF:RDF>

In this case, the HREF attribute on the XX:Author element refers to the current document (implicitly), and specifically the part of it defined by ID="XMLAuthors".

Of course, nothing says that the collection and the description have to be inside the same RDF:RDF element, or even in the same XML document. Nothing stops you from putting an ID attribute on a collection embedded inside a description, either.

Descriptions As Resources

An RDF:Description element can be considered as a Resource. In order to give it a name, we just use an ID attribute, just as we do for a collection.

A particularly interesting case is an RDF:Description with an ID attribute but no HREF attribute. In that case, the Resource described by the Properties in the description is the very RDF:Description element itself! Here's an example:

    <RDF:RDF>
        <RDF:Description ID="SelfDateable">
            <XX:Date>1998-06-18</XX:Date>
        </RDF:Description>
    </RDF:RDF>

This says that the Resource named http://www.ccil.org/~cowan/XML/RDF-made-easy.html#SelfDateable has an XX:Date property of "1998-06-18".

Reification: Properties as Resources

How about making a single Property into a Resource? That can be done too, and the Resource it turns into is an RDF:Description. If we have a single Property like:

    <RDF:RDF>
        <RDF:Description HREF="http://www.ccil.org/~cowan/XML/RDF-made-easy.html"
            XX:Author="John Cowan"
            XX:Title="RDF Made Easy"/>
    </RDF:RDF>

then we can reify it into the following Resource, an RDF:Description without an HREF attribute:

    <RDF:RDF>
        <RDF:Description>
            <RDF:InstanceOf HREF="http://www.w3.org/RDF/RDF-ns/Property"/>
            <RDF:PropName HREF="http://somewhere.net/XX-ns/Author"/>
            <RDF:PropObj HREF="http://www.ccil.org/~cowan/XML/RDF-made-easy.html"/>
            <RDF:Value>John Cowan</RDF:Value>
        </RDF:Description>
    </RDF:RDF>

So the four reserved PropertyTypes RDF:InstanceOf, RDF:PropName, RDF:PropObj, and RDF:Value are used to specify the parts of the Property, namely:

Normally, we don't explicitly reify Properties, but we could if we wanted to. Instead, reification is important because it lets us think about a Property as if it were a Resource, and so allows for Properties of Properties.

Collections As Descriptions

So now we have descriptions and collections, which are different but both useful. Well, it turns out that collections can be viewed as an alternate notation for descriptions, and descriptions can be viewed as collections!

How do we do that? Well, every collection with n elements can be viewed as composed of n+1 properties. Let's take the XMLAuthors sequence above, and describe it using RDF:Description elements. We get the following:

    <RDF:RDF>
        <RDF:Description           RDF:HREF="http://www.ccil.org/~cowan/XML/RDF-made-easy.html#XMLAuthors">
            <RDF:InstanceOf RDF:HREF="http://www.w3.org/RDF/RDF-ns/Seq"/>
            <RDF:1>Tim Bray</RDF:1>
            <RDF:2>Jean Paoli</RDF:2>
            <RDF:3>C. M. Sperberg-McQueen</RDF:3>
        </RDF:Description>
    </RDF:RDF>

In other words, the sequence named "XMLAuthors" is a Resource with four associated Properties. One uses the PropertyType RDF:InstanceOf and a Value that is a URI for RDF:Seq. The remaining Properties have PropertyTypes RDF:1, RDF:2, and RDF:3, and Values corresponding to the contents of the sequence.

Descriptions As Bags

Similarly, a description can be considered as a bag; a bag containing the URIs corresponding to the reified Properties. I will not give an example of such a bag spelled out explicitly. In order to refer to the bag by name, however, a BAGID attribute may be specified on an RDF:Description element; the value of this attribute provides a name for the bag implied by the description, as distinct from the ID attribute, whose value provides a name for the Resource that the description constitutes.

In this way, Properties of groups of Properties can be provided. Consider this description:

    <RDF:RDF>
        <RDF:Description BAGID="RDFMadeEasyBag" HREF="http://www.ccil.org/~cowan/XML/RDF-made-easy.html">
            <XX:Author>John Cowan</XX:Author>
            <XX:Title>RDF Made Easy</XX:Title>
        </RDF:Description>
        <RDF:Description HREF="#RDFMadeEasyBag">
            <XX:Authority>John Cowan</XX:Authority>
        </RDF:Description>
    </RDF:RDF>

The first description says that the author of the specified Resource is "John Cowan" and the title is "RDF Made Easy". The second description says that the XX:Authority property is also "John Cowan". But the Authority property isn't a property of the paper, but of the bag consisting of the previous two Properties. In other words, the authority for the author and title attributions is the same as the author.

Typed Descriptions

The special property RDF:InstanceOf always relates a Resource to another Resource. We have seen it used in the expanded form of collections, as well as in reified Properties. It is often desirable to specify an RDF:InstanceOf property that relates a description to some element of a Vocabulary that represents types.

This can be done by using the element name that represents the Vocabulary element in place of RDF:Description. The syntax of such an element, called a typed description, is the same as an RDF:Description element: it may contain property sub-elements, property attributes, or both. It can also have RDF:ID, RDF:BAGID, and RDF:HREF attributes as needed. (Note that the attributes must have explicit RDF: prefixes, because the element will almost always have a different prefix.

Here's an example:

    <RDF:RDF>
        <XX:AuthorTitleCard HREF="http://www.ccil.org/~cowan/XML/RDF-made-easy.html">
            <XX:Author>John Cowan</XX:Author>
            <XX:Title>RDF Made Easy</XX:Title>
        </XX:AuthorTitleCard>
    </RDF:RDF>

This description has the type XX:AuthorTitleCard, and therefore there is an implicit Property: namely, the Description is an instance of an author-title card.