RDF/XML Syntax

This section will describe a method to specify RDF data in XML.

Storing RDF

In you aren't familiar with RDF, or only have a limited understanding of it, please read the previous section first. If you try to read this section first, you will likely have a difficult time understanding RDF.

You will usually have a need to store RDF in a file or transfer the data somewhere else. There is a common XML format for storing RDF. This format is called RDF/XML. There are several other ways of storing RDF data, but this format is the most common. Some people confusingly refer to this format just as RDF. Actually, the model as described in the previous section is RDF, whereas the syntax is properly called RDF/XML.

The basic RDF/XML file will look like that below. The RDF tag is the root node and surrounds the data. The triples aren't in the file yet; we'll add them in a moment. We declare namespaces on the RDF tag as with other XML vocabularies.

<?xml version="1.0"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:people="http://www.xulplanet.com/rdf/people/">
</rdf:RDF>

We declare two namespaces, the rdf one, and a 'people' namespace for our own purposes. You can use your own namespace, or one of a number of others that people have created for various purposes.

Resource to Literal Triples

First, let's look at a simple RDF triple:

  <http://www.xulplanet.com/rdf/people/Sandra>  ->  name  ->  Sandra

There are three pieces of information that will need to be stored, the resource subject, the predicate, and the target. In the previous section, we didn't put the 'name' pedicate in a namespace for simplicity. However, we will need to add a namespace, and for the purposes of this example, we will just make one up. Here is the information that will need to be stored:

  Subject:   <http://www.xulplanet.com/rdf/people/Sandra>
  Predicate: <http://www.xulplanet.com/rdf/people/name>
  Object:    Sandra

Let's add the triple from above to the file. It is a triple describing a resource to literal relationship. This type of relationship can be described using a single tag with two attributes:

<?xml version="1.0"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:people="http://www.xulplanet.com/rdf/people/">
  <rdf:Description rdf:about="http://www.xulplanet.com/rdf/people/Sandra"
                   people:name="Sandra"/>
</rdf:RDF>

The Description tag may used to describe a triple. This tag is in the rdf namespace. The about attribute is used to specify the subject in the triple. For the object of the triple, 'Sandra', we assign it to the 'people:name' attribute. With namespace qualification, this attribute expands to the value 'http://www.xulplanet.com/rdf/people/name', which is the predicate in the triple.

So, to specify a triple, we just take advantage of namespaces and assign target values to attributes with the same names as predicates. We could add an attribute for every triple we want to add that has the same subject:

<rdf:Description rdf:about="http://www.xulplanet.com/rdf/people/Sandra"
                 people:name="Sandra"
                 people:gender="female"/>

You don't need to repeat the Description tag every time; just add additional attributes to the same one. However, it isn't wrong to use multiple tags. For example, the following will result in the same thing:

<rdf:Description rdf:about="http://www.xulplanet.com/rdf/people/Sandra"
                 people:name="Sandra"/>
<rdf:Description rdf:about="http://www.xulplanet.com/rdf/people/Sandra"
                 people:gender="female"/>

Remember that in RDF, the order of the triples isn't important. This is why alternate syntax such as this is acceptable. Since the order doesn't matter, we could put the tags or attributes in a different order and the same triples would be created. RDF/XML has a number of alternative ways of specifying the same thing. Let's look at another one. Instead of using the attribute form, we could also use a tag to specify the predicate. For instance, the triple from above could be written:

<rdf:Description rdf:about="http://www.xulplanet.com/rdf/people/Sandra">
  <people:name>Sandra</people:name>
</rdf:Description>

Here the predicate attribute has been replaced by a tag. Both forms result in the same thing, but there may be a reason to prefer one or the other. The attribute form is shorter so it is useful when specifying lots of predicates. The tag form would be more practical when the value is longer for better readability. It also might be used if the value has quotes in it since you can't put those in an attribute without escaping them. In addition, the tag form allows you to use the same predicate multiple times:

<rdf:Description rdf:about="http://www.xulplanet.com/rdf/people/Sandra">
  <people:name>Sandra</people:name>
  <people:name>Sandy</people:name>
</rdf:Description>

This creates two triples with the same subject resource and predicate but with different target values. We saw these triples in the previous section. We wouldn't be able to do this solely wth attributes, since a tag can't have the same attribute twice.

It is acceptable to mix the two forms as necessary. For example, the following would result in three triples:

<rdf:Description rdf:about="http://www.xulplanet.com/rdf/people/Sandra"
                 people:name="Sandra">
  <people:name>Sandy</people:name>
  <people:gender>female</people:gender>
</rdf:Description>

Resource to Resource Triples

You will also need to specify resource to resource relationships like the one below.

<http://www.xulplanet.com/rdf/people/Sandra>  ->  sibling  ->
      <http://www.xulplanet.com/rdf/people/Kevin>

You can't use the attribute form for these types of triples, since they can only be used for literal values. However, you can use a modified tag form. However, instead of putting the value inside the opening and closing predicate tags, you use the resource attribute.

<rdf:Description rdf:about="http://www.xulplanet.com/rdf/people/Sandra"
                 people:name="Sandra">
  <people:sibling rdf:resource="http://www.xulplanet.com/rdf/people/Kevin"/>
</rdf:Description>

Here, we using the resource attribute to indicate that the sibling of the Sandra resource is another resource <http://www.xulplanet.com/rdf/people/Kevin> Note that this attribute needs to be in the rdf namespace. This attribute is used to specify resource targets, whereas text inside the tag is used to specify literal targets. Note the similarity in form to the about attribute. The about attribute is used for subjects -- the left-hand side of a triple and the resource attribute is used for objects (targets) -- the right-hand side of the triple.

In the example above, we also specified Sandra's name with an attribute. It is usual to group all triples related to a single subject together in a file. If we wanted to add some triples for Kevin as well, we could use another Description tag:

<rdf:Description rdf:about="http://www.xulplanet.com/rdf/people/Sandra"
                 people:name="Sandra">
  <people:sibling rdf:resource="http://www.xulplanet.com/rdf/people/Kevin"/>
</rdf:Description>
<rdf:Description rdf:about="http://www.xulplanet.com/rdf/people/Kevin"
                 people:name="Kevin"/>

The second Description tag is used to declare another triple, this time for a different subject resource, since the about attribute is different. There is another form you can use however, since you'd likely want to describe two related people together in one file. Instead of using writing the second Description separately, we can just put it inside the sibling directly.

<rdf:Description rdf:about="http://www.xulplanet.com/rdf/people/Sandra"
                 people:name="Sandra">
  <people:sibling>
    <rdf:Description rdf:about="http://www.xulplanet.com/rdf/people/Kevin"
                     people:name="Kevin"/>
  </people:sibling>
</rdf:Description>

This will result in the same set of triples. However, instead of the sibling pointing to the resource and having it described separately, it includes the resource description directly. We don't need the resource attribute any more since the resource is specified inside with the about attribute.

You can continue to nest information inside other items to any level. However, you don't have to. Sometimes, you may prefer to describe them separately. Since the order of the triples doesn't matter in RDF, you are free the specify them in the manner that works best for that data. For instance, when describing people, you probably would put Kevin separately if you had lots of additional triples describing him, to improve readability.

You might wonder what would happen if you left out the about attribute above, as in the following fragment:

<rdf:Description rdf:about="http://www.xulplanet.com/rdf/people/Sandra">
  <people:sibling>
    <rdf:Description people:name="Kevin"/>
  </people:sibling>
</rdf:Description>

This will result in the same graph structure, meaning that Kevin will still be a sibling of Sandra, except that Kevin won't have a URI. This creates a blank node (or anonymous node), which doesn't have a URI, but is still a node in the RDF graph. When using an RDF API, you would be able to get a reference to a node via its URI, but you might not be able to get a blank node in this manner since it doesn't have a URI. Instead, you would need to tranverse the triples to find it.

Types

Since specifying the type of a node is done with a triple like all other information in RDF, you could use the same form for specifying the node type. Here is the triple we want to store:

<http://www.xulplanet.com/rdf/people/Sandra>  ->  rdf:type  ->
      <http://xmlns.com/wordnet/1.6/Person>

Here is that triple in RDF/XML form:

<?xml version="1.0"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:people="http://www.xulplanet.com/rdf/people/">
<rdf:Description rdf:about="http://www.xulplanet.com/rdf/people/Sandra"
  <rdf:type resource="http://xmlns.com/wordnet/1.6/Person"/>
</rdf:Description>
</rdf:RDF>

This is no different than specifying any other triple. We use the rdf:type predicate and point to the Person type. However, since types are commonly used in RDF, there is a special shortcut you can take.

<?xml version="1.0"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:wordnet="http://xmlns.com/wordnet/1.6/"
         xmlns:people="http://www.xulplanet.com/rdf/people/">
<wordnet:Person rdf:about="http://www.xulplanet.com/rdf/people/Sandra"/>
</rdf:RDF>

This means the same thing, but it much simpler. The about attribute is still present as before, but the Description tag has been replaced by the type itself. The 'wordnet' namespace has been added to the RDF tag. When qualified, that causes the 'wordnet:Person' tag to become 'http://xmlns.com/wordnet/1.6/Person', which you should note is the type we want.

The difference then is that the Description tag has been replaced by the type, which is how this form will be evaluated. It can be assumed that when you see a tag with an about element, that the tag is the type of that resource.

Really, you could say that when a Description tag is used, it means that the type is not known, or isn't important. When you want to specify the type of a resource, replace the Description tag form with the type of the resource. This is one reason that types are always resources since you couldn't use the tag if they were literals.

Of course, you could use the type syntax when nesting triples as well:

<wordnet:Person rdf:about="http://www.xulplanet.com/rdf/people/Sandra"
                 people:name="Sandra">
  <people:sibling>
    <wordnet:Person rdf:about="http://www.xulplanet.com/rdf/people/Kevin"
                     people:name="Kevin"/>
  </people:sibling>
</wordnet:Person>

Here, we indicate that both the Sandra and Kevin resources are of the Person type. One thing to watch out for is that is can be difficult to read if you use too much nesting since it may become unclear which tags are supposed to be types and which are predicates. However, they always alternate. In the example above, the outer tag is a type, the next inner tag is a predicate, and then a type again. The next tag should be a predicate again. This concept is sometimes called striping, because of the way the types and predicates alternate.

List Types

For the built-in list types, Seq, Bag and Alt, you can specify the type in the same manner. Just replace the Description tag or type name with rdf:Seq, for a Seq type.

<rdf:Seq rdf:about="http://www.xulplanet.com/rdf/people/KarensKids"/>

This is no different than specifying other types. The resource <http://www.xulplanet.com/rdf/people/KarensKids> is given a type of rdf:Seq. Naturally, we will want to add the children in the list to this resource:

<rdf:Seq rdf:about="http://www.xulplanet.com/rdf/people/KarensKids">
  <rdf:_1 rdf:resource="http://www.xulplanet.com/rdf/people/Sandra"/>
  <rdf:_2 rdf:resource="http://www.xulplanet.com/rdf/people/Kevin"/>
  <rdf:_3 rdf:resource="http://www.xulplanet.com/rdf/people/Jack"/>
</rdf:Seq>

As we do with all triples, we add them inside the resource and point them to the three child resources. Let's say that Karen had 20 kids instead. If we wrote this out and then realized we made a mistake and forgot a child, we would need to insert the child and renumber the others in the list. Remember, that this isn't necessary, since skipping numbers is fine. However, this would look unusual when read. RDF/XML provides an special tag just to solve this kind of problem.

<rdf:Seq rdf:about="http://www.xulplanet.com/rdf/people/KarensKids">
  <rdf:li rdf:resource="http://www.xulplanet.com/rdf/people/Sandra"/>
  <rdf:li rdf:resource="http://www.xulplanet.com/rdf/people/Kevin"/>
  <rdf:li rdf:resource="http://www.xulplanet.com/rdf/people/Jack"/>
</rdf:Seq>

Instead of using the numbers, we can use the li tag which will do the counting for us. The first item will be labeled 1 (actually rdf:_1 as above), the second 2, and the third 3. We can insert a child without adjusting the others. This tag is modeled after the similarly named tag from HTML for creating lists.

The li tags aren't used directly as predicates. If you were to use an RDF API to query the data, you won't find any li predicates, they will have been translated into the number form. This tag is used only as a convenience when writing RDF in XML.

Note that the li tag has a resource attribute, as several earlier examples had. As always, this indicates that <http://www.xulplanet.com/rdf/people/Sandra> is the target of the triple. Like before, we could also nest items inside this tag:

<rdf:li>
  <wordnet:Person rdf:about="http://www.xulplanet.com/rdf/people/Sandra" people:name="Sandra"/>
</rdf:li>

This combines a variety of concepts from above. The target child in the list is still the resource <http://www.xulplanet.com/rdf/people/Sandra>, but it has been given a name and a type.

Complete Example

Here is a complete example of Karen's family:

<?xml version="1.0"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:wordnet="http://xmlns.com/wordnet/1.6/"
         xmlns:people="http://www.xulplanet.com/rdf/people/">
<wordnet:Person rdf:about="http://www.xulplanet.com/rdf/people/Karen" people:name="Karen">
  <people:children>
    <rdf:Seq rdf:about="http://www.xulplanet.com/rdf/people/KarensKids">
      <rdf:li>
        <wordnet:Person rdf:about="http://www.xulplanet.com/rdf/people/Sandra" people:name="Sandra"/>
      </rdf:li>
      <rdf:li>
        <wordnet:Person rdf:about="http://www.xulplanet.com/rdf/people/Kevin" people:name="Kevin"/>
      </rdf:li>
      <rdf:li>
        <wordnet:Person rdf:about="http://www.xulplanet.com/rdf/people/Jack" people:name="Jack"/>
      </rdf:li>
    </rdf:Seq>
  </people:children>
</wordnet:Person>
</rdf:RDF>

This will create the triples from the previous section, along with a few others. It will create a total of 13 triples. One name for each of the four people, one type for each person, one type for the Seq, one for each of the three list items, and one for the 'children' predicate.

There are some other bits of syntax involved with RDF/XML, however that should be all that is necessary for a basic understanding.

Mozilla RDF Notes

Mozilla's RDF parser was written before the RDF specification was finalized. Thus, there are two differences. The first is that the parser is slightly more lax than it might be, so the resource and about attributes don't need to be in the RDF namespace to work. The second is that for Seq, Bag and Alt types, the predicate 'rdf:instanceOf' from an earlier draft of RDF is used instead of 'rdf:type'. This only applies to the list types, not to other types.

Neither of these issues should cause you any problems, however, you might want to be aware of them.

Add a note User Contributed Notes
February 11, 2005, 1:44 am donatas at viesulas dot ktu dot lt
There is double "u" in "about" in the last comment's example:

<rdf:Description rdf:abouut="urn:foo">
November 15, 2004, 11:59 pm rook at nospam dot roo dot k dot pl
I foud out that

<rdf:Description rdf:abouut="urn:foo">
<rdf:instanceOf
rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq"/>
</rdf:Description>

is not enough for the template builder to treat "urn:foo" as a list.

<rdf:Description rdf:abouut="urn:foo">
<rdf:instanceOf
rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq"/>
<rdf:nextVal>1</rdf:nextVal>
</rdf:Description>

does the job

Copyright © 1999 - 2005 XULPlanet.com