Back to DAML homepage

Annotated DAML+OIL Ontology Markup

Feedback to www-rdf-logic, please.

DAML+OIL version (revision 3.2): Frank van Harmelen, ed.
DAML-ONT version (up to revision 2.0): Lynn Andrea Stein, Dan Connolly, and Deborah McGuinness, eds.
$Revision: 1.10 $ of $Date: 2001/01/16 20:39:43 $

This is an annotated walk through an example DAML+OIL Ontology. The example ontology demonstrates many of the features in DAML+OIL[DAML+OIL], but is not intended as a complete description of the language. For this, please refer to the reference document on DAML+OIL.

Superscripted text refers to notes at the end of this document. The original example ontology is available separately.

DAML+OIL builds on existing Web technologies like Extensible Markup Language[XML] and Uniform Resource Identifiers[URI]. The references and suggested reading section cites introductory materials as well as official specifications for these technologies.


Setting Up Namespaces

DAML+OIL, is written in RDF[RDF], i.e., DAML+OIL markup is a specific kind of RDF markup. RDF, in turn, is written in XML, using XML Namespaces[XMLNS], and URIs. If you are unfamiliar with RDF, the minimalist survival guide to XML and the minimalist survival guide to RDF below may help get you started.

Thus, our example begins with an RDF start tag including four namespace declarations:

  xmlns:rdf =""
  xmlns     =""

So in this document, the rdf: prefix should be understood as referring to things drawn from the namespace called This is a conventional RDF declaration appearing verbatim at the beginning of almost every rdf document.xmlns:rdf

The second declaration makes a similar statement about the RDF Schema namespace.

The third declaration says that in this document, elements prefixed with daml: should be understood as referring to things drawn from the namespace called This is a conventional DAML+OIL declaration that should appear verbatim at the beginning of the current generation of DAML+OIL documents.

The final declaration states that unprefixed elements refer to, which is the location of this document itself.

If you look at the bottom of this document, you'll see the matching closing tag, </rdf:RDF>.


The first thing we do inside this RDF document is to assert that this is an ontology.

<daml:Ontology rdf:about="">

This assertion is formulaic; the about attribute will typically be empty, indicating that the subject of this assertion is this document.Same-document reference

Then we give a couple of properties of this ontology for documentation purposes:

  <daml:versionInfo>$Id: daml+oil-walkthru.html,v 1.10 2001/01/16 20:39:43 kmbarber Exp $</daml:versionInfo>
  <rdfs:comment>An example ontology</rdfs:comment>

followed by...

  <daml:imports rdf:resource=""/>

Inside the Ontology element, we list any imported ontologies (using imports properties). This particular ontology depends only on the standard DAML+OIL ontology (used in the namespace definitions above).

Each imports statement references another DAML+OIL ontology that provides additional definitions (of classes, properties, axioms, etc.) for the resource in which it appears. These additional definitions should be used by DAML agents when reasoning about the resource which contains the imports statement. Imports statements are transitive, that is, if ontology A imports B, and B imports C, then A imports both B and C.

Note that namespaces only provide a mechanism for creating unique names for elements, and do not include definitions in the way that imports does. Similarly, imports statements do not set up a shorthand notation for names. Therefore, it is common to have imports statements that correspond to each namespace. However, additional imports may be used for ontologies that provide definitions without introducing any new names.

Note that this (imports) tag is an empty element; the same tag starts and ends the element, denoted by the trailing "/" just before the closing ">".


Defining Classes

Now, we begin our ontology definitions. In order to describe objects, it is useful to define some basic types. If we are working in a domain of animals, we will want to define a kind of thing called animal. To do this, we use a Class tag. Class

<rdfs:Class rdf:ID="Animal">

This asserts that there is a Class known as Animal. It doesn't say anything else about animal other than specifying an identifier. It is also not (necessarily) the sole source of information about Animals; we will see below how we can add to a definition made elsewhere.

However, by saying that its ID is Animal, we make it possible for others to refer to the definition of Animal we're giving here. (This is done using the uri of the containing page followed by #Animal.)

    This class of animals is illustrative of a number of ontological idioms.

These two lines introduce a label -- a brief identifier of the enclosing element, suitable for graphical representations of RDF, etc. -- and a comment -- a natural language (English, in this case) description of the element within which it is included. Neither a label nor a comment contributes to the logical interpretation of the language.


There are two types of animals, Male and Female.

<rdfs:Class rdf:ID="Male">
  <rdfs:subClassOf rdf:resource="#Animal"/>

The subClassOf element asserts that its subject -- Male -- is a subclass of its object -- the resource identified by #Animal. SubClassOf

<rdfs:Class rdf:ID="Female">
  <rdfs:subClassOf rdf:resource="#Animal"/>
  <daml:disjointWith rdf:resource="#Male"/>

Some animals are Female, too, but nothing can be both Male and Female (in this ontology) because these two classes are disjoint (using the disjointWith tag)

It perfectly admissible for a class to have multiple superclasses: A Man is a Male Person

<rdfs:Class rdf:ID="Man">
  <rdfs:subClassOf rdf:resource="#Person"/>
  <rdfs:subClassOf rdf:resource="#Male"/>

...and a Woman is a Female Person.

<rdfs:Class rdf:ID="Woman">
  <rdfs:subClassOf rdf:resource="#Person"/>
  <rdfs:subClassOf rdf:resource="#Female"/>

As always in DAML+OIL, conjoining statements without an explicit connective means that the statements must be read conjunctively, in this case: Woman is a subclass of Person and is a subclass of Female.

Defining Properties

Next, we define a property. A property -- or binary relation -- connects two items. In this case, we're defining the hasParent relation which will be used to connect two animals. Property

<rdf:Property rdf:ID="hasParent">

The property definition begins by stating that there is a property called hasParent. Note, however, that this is not a closing tag; there's more to this definition. (There is a matching </Property> tag below.)

  <rdfs:domain rdf:resource="#Animal"/>

Like all embedded elements, this is understood to describe its enclosing element. So, this element describes the Property whose ID is hasParent. It says that the domain of the hasParent relation is Animal. That is, we're defining hasParent as a property that applies to animals.

  <rdfs:range rdf:resource="#Animal"/>

Similar to the domain, we also declare the range of the hasParent relation to be Animal. That is, we're defining hasParent as a property whose value can only be animals.

It is allowed in DAML+OIL to state multiple ranges. Again, such multiple statements must be read conjunctively: the values of the property must satisfy all the range statements (and similar for multiple domain statements). Note that in this aspect, DAML+OIL departs from the RDF Schema semantics for domain and range. See the reference document for more details.

(Note the comment below which points out that there is an alternative for such domain and range restrictions)

We do this by asserting that there's a thing which is a domain -- the things to which this property applies, ie. the things that can have parents -- and saying that this domain is the resource known as #Animal. What is the resource attribute? It is a reference to something. Note that the ID attributes that we created for each entry until now serve as reference-able descriptions; resource refers to such descriptions. In this case, it refers to names in this document, since its reference begins with a #.


That's all we have to say about this Property (whose ID = hasParent).

Next, we state that hasFather is a property that is a kind of hasParent property, i.e., x's father is also x's parentsubProperty. In addition, range is used to ensure that x's father must be a Male.

<rdf:Property rdf:ID="hasFather">
  <rdfs:subPropertyOf rdf:resource="#hasParent"/>

  <rdfs:range rdf:resource="#Male"/>

(Note the comment below which points out that there is an alternative for such range restrictions)

Defining property restrictions

Now we'll define a Class with some attributes.

<rdfs:Class rdf:ID="Person">

This element describes a kind of thing called a Person, and is referenceable as such.

  <rdfs:subClassOf rdf:resource="#Animal"/>

A Person is a kind of Animal (referring to the definition of Animal above).

The next few lines describe a class-specific range restriction. In particular, the parent of a Person is also a Person.

  <rdfs:subClassOf rdf:resource="#Animal"/>
      <daml:onProperty rdf:resource="#hasParent"/>
      <daml:toClass rdf:resource="#Person"/>

What happens here is that the Restriction defines an anonymous class, namely the class of all things that satisfy the restriction. In this case: the class of all things whose parent is a Person. We then demand that the class Person is a subClassOf this (anonymous) class. In other words: we demand that every Person must satisfy this Restriction, which in this case amounts to demanding that Persons have only Persons as their parents.

The syntax used here is a cliche, i.e., it is always used as shown, except for (i) the name of the resource in the OnProperty element, which will give the name of the Property to be restricted, and (ii) the resource associated with the toClass element, which will give the name of the Class to which the Property is restricted.

Note: When restricting the range of a property, as we are doing here, there is an important difference between using a toClass restriction and using rdfs:range (as we did for the hasFather property). An rdfs:range element has a global scope: any use of the hasFather property for any class must always yield a male. A toClass restriction (as used in the Person class) on the other hand has a local scope: the parent of a person must be person, but the parent of any other class (e.g. the parent of an elephant) need not be a person.

The class Person comes with another example of a restriction:

    <daml:Restriction daml:cardinality="1">
      <daml:onProperty rdf:resource="#hasFather"/>

This requires that any person must have exactly 1 father. Again, this is done by first using a Restriction to define an anonymous class (in this case the class of all things that have exactly one father), and then demanding that Person is a subClassOf this anonymous class (ie demanding that every Person satisfies this Restriction).

Following the same cliche syntax as before, this could also have read:

      <daml:onProperty rdf:resource="#hasFather"/>
This would have carried exactly the same meaning. In fact, the first is simply an alternative RDF syntax for the second
Alternative syntax, designed to avoid browsers displaying any of the meta-data annotations in a document. Both syntactic forms result in exactly the same underlying RDF datamodel, and carry exactly the same DAML+OIL semantics. Note that daml:cardinality must be prefixed; unprefixed attributes don't pick up the default namespace the way unprefixed elements do.

Again, this cardinality restriction has a local scope: the above only enforces that a Person has exactly 1 father. This still leaves open the (unlikely) possibility that other classes have more or fewer than one father.

Besides toClass and cardinality, other restrictions are possible. These are all discussed reference document on DAML+OIL.


That's the end of the Person class.

A key feature of any web-based ontology language is that statements about entities such as classes and properties can be distributed among different locations. For example, if we wanted to add to the Animal class (defined above) that all animals have exactly 2 parents, we need not modify the above statement, but we can simply add the following, referring to the statement with its ID:

<rdfs:Class rdf:about="#Animal">
    Animals have exactly two parents, ie:
    If x is an animal, then it has exactly 2 parents 
    (but it is NOT the case that anything that has 2 parents is an animal).
    <daml:Restriction daml:cardinality="2">
      <daml:onProperty rdf:resource="#hasParent"/>

Such an assertion "about" the class Animals has exactly the same logical status as the assertions made within the <rdfs:Class rdf:ID="Animal"> element about vs. ID.

Note that if this statement had lived in another file, we should have referred to the class Animal with a fully qualified URL: rdf:about=""

The cardinality property specifies a precise cardinality. But sometimes we want to bound the cardinality without precisely specifiying it. A person may have zero or one spouse, but no more:

<rdfs:Class rdf:about="#Person">
    <daml:Restriction daml:maxcardinality="1">
      <daml:onProperty rdf:resource="#hasSpouse"/>

Of course, a minimal value for the cardinality of a property can be expressed in a similar way.

If no minimum cardinality is specified, a minimum cardinality of 0 is assumed. Thus, <Restriction daml:mincardinality="0"> would not need to be asserted.

A more sophisticated version of a cardinality constraint on a property not only specifies a maximum, minimum or precise number of values for that property, but also enforces the type that these property values must have:

<rdfs:Class rdf:about="#Person">
    <daml:Restriction daml:maxcardinalityQ="1">
      <daml:onProperty rdf:resource="#hasOccupation"/>
      <daml:hasClassQ rdf:resource="#FullTimeOccupation"/>

This states that a Person may have at most one occupation that is a FullTimeOccupation. (This still allows for the possibility that they may have multiple jobs of other types than FullTimeOccupation).

Of course, such qualified cardinality constraints can be stated as well for minimal cardinalities and exact cardinalities.

Notations for properties

The next several annotations illustrate various notations for properties:

HasMother is defined similarly to hasFather, but using a variant notation. A UniqueProperty is one with cardinality 1, so we can omit the cardinality sub-element from HasMother's definition.

<daml:UniqueProperty rdf:ID="hasMother">
  <rdfs:subPropertyOf rdf:resource="#hasParent"/>
  <rdfs:range rdf:resource="#Female"/>

Since a UniqueProperty has cardinality 1, each subject uniquely identifies the object (value) of the property (ie. the identity of a person determines their mother). Conversely, an UnambiguousProperty is a property whose object uniquely identifies its subject. (The inverse of any UniqueProperty is always an UnambiguousProperty).

Notice that UniqueProperty and UnambiguousProperty specify global cardinality restrictions. That is, no matter what class the property is applied to, the cardinality constraints must hold, unlike the cardinality restrictions illustrated above, which are part of a class element, and are only enforced on the property when applied to that class.

If x's parent is y, then y is x's child. This is defined using the inverseOf tag.

<rdf:Property rdf:ID="hasChild">
  <daml:inverseOf rdf:resource="#hasParent"/>

The hasAncestor and hasDescendant properties are intended as transitive versions of the hasParent and hasChild properties.

<daml:TransitiveProperty rdf:ID="hasAncestor">

<daml:TransitiveProperty rdf:ID="hasDescendant"/>

Note that this only states that hasAncestor is transitive, but not yet that hasAncestor is the transitive version of hasParent (and ditto for hasDescendant and hasChild). Additional DAML+OIL statements (i.e., subPropertyOf statements) would be needed to enforce these connections.

Sometimes, we like to refer to mothers using the synonym mom. The tag samePropertyAs allows us to establish this synonymy:

<rdf:Property rdf:ID="hasMom">
  <daml:samePropertyAs rdf:resource="#hasMother"/>

Notations for classes

Classes, too, can be annotated in various ways:

<rdfs:Class rdf:ID="Car">
  <rdfs:comment>no car is a person</rdfs:comment>

We want to state that cars can never be persons, in other words: cars are a subclass of non-persons. The thing that Car is a subClassOf (ie non-persons) could in principle be specified using a resource= attribute. In this case, however, there is no pre-existing succinct name for the thing we want (the class of non-persons). We build this by introducing a new -- anonymous -- Class definition described using the complementOf tag:

      <daml:complementOf rdf:resource="#Person"/>

In other words: Car is a Class that is a specialization of another (anonymous) Class, namely the Class consisting of all things except Persons.

... and this finishes the definition of the class Car.

In effect, the above makes the class Car disjoint from the class Person (since Car is declared to be a subClass of the complementOf Person). Because such disjointness statements among classes occur very frequently, DAML+OIL has a specific vocabulary for this special case. The same fact could have been stated using the disjointWith tag that we already saw above in the definition of Female.

An even more compact idiom is to state that a whole set of classes are all pairwise disjoint. Rather than stating the individual disjointness relations, this can be stated for a set of classes in a single statement:

<daml:Disjoint rdf:parseType="daml:collection">
  <rdfs:Class rdf:about="#Car"/>
  <rdfs:Class rdf:about="#Person"/>
  <rdfs:Class rdf:about="#Plant"/>

Note that the Disjoint element contains multiple subelements. The parseType="daml:collection" indicates that these subelements are to be treated as a unit (namely as a single collection) RDF extension.

Besides stating that classes are disjoint, we can also identify a Class with the disjoint union of a set of other classes. In this case, we identify the Class Person with the disjoint union of the Classes Man and Woman.

<rdfs:Class rdf:about="#Person">
  <rdfs:comment>every person is a man or a woman</rdfs:comment>
  <daml:disjointUnionOf rdf:parseType="daml:collection">
    <rdfs:Class rdf:about="#Man"/>
    <rdfs:Class rdf:about="#Woman"/>

This is also another example of further specifying a previously defined element by using the about attribute. Note also that disjointUnionOf again uses the non-standard parseType="daml:collection" construct.

We have already seen that we can construct a new class by taking the complementOf another class. In the same way, we can construct classes out of the intersection of other classes:

<rdfs:Class rdf:ID="TallMan">
  <daml:intersectionOf rdf:parseType="daml:collection">
    <rdfs:Class rdf:about="#TallThing"/>
    <rdfs:Class rdf:about="#Man"/>
This states that the class TallMan is exactly equal to the intersection of Man and TallThing. (See below for the definition of the class TallThing). Note that we can take the intersectionOf an arbitrary number of classes (parseType="daml:collection").

Similarly, we can construct a class as the unionOf a set of classes.

As already indicated, the intersectionOf construction makes the named class exactly equal to the result of the intersection. This construction is frequently used as an idiom if we want to state not only necessary but also sufficient conditions for a class. For example, a MarriedPerson is a Person with a spouse, but also vice versa: any Person with a spouse is a MarriedPerson. Such necessary and sufficient conditions can be enforced using intersectionOf:

<rdfs:Class rdf:ID="MarriedPerson">
  <daml:intersectionOf rdf:parseType="daml:collection">
    <rdfs:Class rdf:about="#Person"/>
    <daml:Restriction daml:cardinality="1">
      <daml:onProperty rdf:resource="#hasSpouse"/>

Note the use of the cardinality Restriction to specify an anonymous class. This anonymous class (the class of all things that have exactly one spouse) is intersected with the Person class to yield exactly all Persons that have one spouse.

Just as for properties, a mechanism exists for declaring synonyms for classes:

<rdfs:Class rdf:ID="HumanBeing">
  <daml:sameClassAs rdf:resource="#Person"/>

Defining individuals

We can also define individuals, e.g., Adam:

<Person rdf:ID="Adam">
  <rdfs:comment>Adam is a person.</rdfs:comment>

A Person has a property called hasHeight, which is a Height. (hasHeight is a Property, or relation; Height is a Class, or kind of thing.)

<rdf:Property rdf:ID="hasHeight">
  <rdfs:range rdf:resource="#Height"/>

Height is a Class described by an explicitly enumerated set. We can describe this set using the oneOf element. Like disjointUnionOf, oneOf uses the RDF-extending parsetype="daml:collection". RDF extension

<rdfs:Class rdf:ID="Height">
  <daml:oneOf rdf:parseType="daml:collection">
    <Height rdf:ID="short"/>
    <Height rdf:ID="medium"/>
    <Height rdf:ID="tall"/>

Finally, TallThing is exactly the class of things whose hasHeight has the value tall:

<rdfs:Class rdf:ID="TallThing">
      <daml:onProperty rdf:resource="#hasHeight"/>
      <daml:hasValue rdf:resource="#tall"/>
From the inside out, this says first that TallThings must have the value tall as value for their hasHeight property, ie having the value tall as your height is a necessary condition for being a TallThing. Secondly, we say that TallThing is exactly the same class as the the class of all such objects (ie all objects having tall as their value for hasHeight), in other words: besides being necessary, this condition is also sufficient for being a TallThing.

Consider what would have happened if we had used subClassOf instead of sameClassAs. This would have resulted in a necessary but not sufficient condition for the definition of the class TallThing. Thus, a necessary-only and a necessary-and-sufficient class definition now differ simply in their outermost element.

Finally, we end our specfication with the rdf:RDF element.



This draft draws on the work of many of the researchers in the DAML project, and from discussion with and review by Jim Hendler, Tim Berners-Lee, Ralph R. Swick, Pat Hayes, Drew McDermott, Stefan Decker, Richard Fikes, Jeff Heflin, and Ian Horrocks.

A minimalist survival guide to XML

This appendix is intended for those unfamiliar with RDF. It contains only enough information to enable you to read the annotated DAML+OIL markup example, and is not intended as a complete introduction to RDF, XML, or any other of the technologies on which DAML+OIL is based. See the suggested readings below for more information.

RDF is built on XML, which makes use of tags to structure information. Here are some example tags:



<anotherTag with="an attribute">...</anotherTag>

<aTag>with <anemptyTag/> inside it</aTag>


The first thing after the open angle bracket is the tag name. The whole tag is often referred to by this name. So

<Class ID="Animal">

is a Class tag.

A tag ends with a closing angle bracket.

Some tags are start tags, and have matching end tags. The end tag has the same tag name as the opening tag, but begins with </ rather than simply <. For example,

<Class ID="Animal">

would be closed by the matching end tag


From an opening tag to its matching closing tag is an element. Other tags can be embedded inside the element, but all such embedded elements must be closed inside the enclosing element. So <rdf:RDF> would begin an element that runs until an </rdf:RDF>. In this case, anything between the <rdf:RDF> and the matching </rdf:RDF> would be enclosed in the scope of this element.

An alternate way to specify an element that has nothing between its opening and its closing tag is to use a single tag with a slash immediately before the closing angle-bracket. Thus, the self-closing tag

<Class ID="Animal"/>

is the same as

<Class ID="Animal"></Class>

with nothing inside it.

An opening tag (or a self-closing tag) may contain things other than the tag name. These things after the tag name are attributes. Each attribute has a name, an equal sign, and an attribute value (generally enclosed in double quotes). So, for example, in the Class tag above,


is the attribute,


is the attribute name, and


is the attribute value. Attributes are read as properties of the element in which they appear.

A minimalist survival guide to RDF

An RDF document is a collection of assertions in subject verb object (SVO) form. Within the obligatory RDF declaration (typically a tag that begins something like <rdf:RDF ...), each topmost element is the subject of a sentence. The next level of enclosed elements represent verb/object pairs for this sentence:

<Class ID="Male">
  <subClassOf resource="#Animal"/>

Male is a subclass of Animal.

<Class ID="Female">
  <subClassOf resource="#Animal"/>
  <disjointWith resource="#Male"/>

Female is a subclass of Animal AND Female is disjoint from Male. The single subject -- Female -- is used to begin each of the verb-object assertions

 <subClassOf resource="#Animal"/>


<disjointWith resource="#Male"/>

A few attributes here require explanation.

ID creates a referenceable name, corresponding to the attribute value. So, for example, ID="Male" means that you can refer to Male and mean the thing described by the Class element above. Similarly, Female is a referenceable name.

The resource attribute, then, is simply a reference to such a name. In

<disjointWith resource="#Male"/>

the resource attribute is used to indicate that the object of the assertion "Female is disjoint from" is the thing identified with the name Male. Note the prepended # to refer to the name. This indicates a reference to a name within the same containing document, i.e., a local name. It is also possible (e.g., by prepending a url before the #) to refer to a name defined elsewhere.

In the above example, each verb tag is self-closing. It is also possible to embed elements inside these verb elements, making objects which are themselves the subjects of subordinate clauses. This causes an alternation of subject verb subject verb ... sometimes called RDF striped syntax.


The namespace prefix rdf is arbitrary here; you can call the namespace associated with whatever you want. Since this is the conventional namespace for rdf syntax, rdf is a common way to spell this prefix.
Unprefixed attribute names are not associated with the default namespace name the way unprefixed element names are. See myth #4 in Namespace Myths Exploded.
Same-document reference
See section 4.2 Same-document References of [URI].
Strictly speaking, DAML+OIL Class is declared as a subclass of RDF Schema Class. However, the semantics of daml:Class and rdfs:Class are exactly the same. To promote backward compatability with RDF Schema, we have used rdfs:Class instead of daml:Class.
A similar remark applies to daml:subClassOff and rdfs:subClassOff as made about daml:Class and rdfs:Class.
Again, rdf:Property is used instead of daml:Property to achieve maximal backward compatability with RDF agents.
A similar remark applies here as to Property.
RDF extension
This is a proper extension of RDF 1.0 syntax. Existing tools (at the time of this writing) are unlikely to support this.
Alternative syntax
The relevant part of the RDF specification is in the section on abbreviated syntax where it says: "Three forms of abbreviation are defined for the basic serialization syntax. The first is usable for properties that are not repeated within a Description and where the values of those properties are literals".
about vs. ID
In fact, using either "about=" or "ID=" results in exactly the same set of RDF triples, and perforce the DAM+OIL meaning of these different notations is the same.

References and Suggested Reading

Official definition of the language in RDF Schema form at daml+oil.daml,
also: example ontology
Extensible Markup Language (XML) 1.0
W3C Recommendation Feb 1998
what you really need to know:
more background
Extensible Markup Language (XML) at W3C
Uniform Resource Identifiers (URI): Generic Syntax
IETF Draft Standard August 1998 (RFC 2396) T. Berners-Lee, R. Fielding, L. Masinter
what you really need to know:
more background
Web Naming and Addressing Overview (URIs, URLs, ...) at W3C
Namespaces in XML
W3C Recommendation Jan 1999
what you really need to know:
more background
Extensible Markup Language (XML) at W3C
Resource Description Framework (RDF) Model and Syntax Specification
World Wide Web Consortium Recommendation, 1999 Lassila, Swick [eds]

background: RDF: Resource Description Framework at W3C

Resource Description Framework (RDF) Schema Specification 1.0
W3C Candidate Recommendation 27 March 2000.