random technical thoughts from the Nominet technical team

The Semantic Web: Web Ontology Language (OWL) example

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 4 out of 5)
Loading ... Loading ...
Posted by Al on Jun 6th, 2006

I have recently been exploring the Semantic Web,
looking at a few of the tools,
and also checking out the W3C’s Web Ontology Language (OWL),
by creating a simple example for WHOIS. The W3C also provide a useful overview of the OWL Web ontology language.

Useful tools
Looking at the tools out there, there are several editors/IDEs/validators, both commercial and non-commercial. Of course one can use any
XML editor/notepad to create OWL documents (which are essentially extended RDF), but code completion and validation features are useful.
For a rather exhaustive list, check out the useful if not slightly dated Xml.com
Ontology Tools Survey
(you might need a strong magnifying glass to read the table in it’s PDF form!).

I found the most useful to be SWeDE - an open source Eclipse Plugin.
This includes an OWL editor with helpful features like syntax highlighting, autocompletion, and error-detection.

Validation
A very useful validator I stumbled across was the mindswap OWL Consistency Checker, which allowed
for species validation (Lite, DL or Full) amd checked for ontology consistency.
The ability to validate by URI or pasted in test is handy too. It can also display ontologies in a tree like structure
which could well be useful for more complex ontologies.

Simple OWL example: WHOIS

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rdf:RDF [
<!ENTITY domain  "http://xml.nominet.org.uk/rdf/nom/domain#">
<!ENTITY rdf  "http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#">
<!ENTITY xsd  "http://www.w3.org/2001/XMLSchema#">
<!ENTITY owl  "http://www.w3.org/2002/07/owl#">
]>

<!-- entities are used to make URL modification easy
for the future -->
<rdf:RDF
xmlns="&owl;"
xml:base="&domain;"
xmlns:owl="&owl;"
xmlns:rdfs="&rdfs;"
xmlns:rdf="&rdf;"
xmlns:xsd="&xsd;"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<!-- ****************** -->
<!-- Ontology metadata -->
<!-- ****************** -->
<owl:Ontology rdf:about="">
<rdfs:comment>This is a simple ontology example to
describe WHOIS</rdfs:comment>
<rdfs:label>Nominet WHOIS Ontology example</rdfs:label>
</owl:Ontology>

<!-- domain name -->
<owl:Class rdf:ID="domainName">
<rdfs:label xml:lang="en">domain name</rdfs:label>
</owl:Class>

<owl:DatatypeProperty rdf:ID="domainNameValue">
<rdfs:domain rdf:resource="#domainName"/>
<rdfs:range rdf:resource="&xsd;string"/>
</owl:DatatypeProperty>

<!-- ****************** -->
<!-- registrant -->
<!-- ****************** -->
<owl:Class rdf:ID="registrant">
<rdfs:label>domain name registrant</rdfs:label>
</owl:Class>

<owl:DatatypeProperty rdf:ID="registrantName">
<rdfs:domain rdf:resource="#registrant"/>
<rdfs:range rdf:resource="&xsd;string"/>
</owl:DatatypeProperty>

<!-- These are the object properties of a domain name/
registrant -->
<owl:ObjectProperty rdf:ID="hasRegistrant">
<rdfs:domain rdf:resource="#domainName"/>
<rdfs:range rdf:resource="#registrant"/>
<owl:inverseOf rdf:resource="#registrantOf"/>
</owl:ObjectProperty>

<owl:ObjectProperty rdf:ID="registrantOf">
<rdfs:domain rdf:resource="#registrant"/>
<rdfs:range rdf:resource="#domainName"/>
<owl:inverseOf rdf:resource="#hasRegistrant"/>
</owl:ObjectProperty>

<!-- ****************** -->
<!-- trading as -->
<!-- ****************** -->
<owl:Class rdf:ID="tradingAs">
<rdfs:label xml:lang="en">
registrant trading as
</rdfs:label>
</owl:Class>

<owl:ObjectProperty rdf:ID="tradingNameOf">
<rdfs:domain rdf:resource="#registrant"/>
<rdfs:range rdf:resource="#tradingAs"/>
</owl:ObjectProperty>

<!-- ****************** -->
<!-- registration type and it's properties -->
<!-- ****************** -->
<owl:Class rdf:ID="registrantType"/>

<owl:DatatypeProperty rdf:ID="type">
<rdfs:domain rdf:resource="#registrantType"/>
<rdfs:range rdf:resource="&xsd;string"/>
</owl:DatatypeProperty>

<owl:DatatypeProperty rdf:ID="numberType">
<rdfs:domain rdf:resource="#registrantType"/>
<rdfs:range rdf:resource="&xsd;string"/>
</owl:DatatypeProperty>

<owl:DatatypeProperty rdf:ID="organisationNumber">
<rdfs:domain rdf:resource="#registrantType"/>
<rdfs:range rdf:resource="&xsd;int"/>
</owl:DatatypeProperty>

<!-- registrant type can be either company or charity -->
<owl:Class rdf:ID="companyRegistrant">
<rdfs:subClassOf rdf:resource="#registrantType" />
</owl:Class>

<owl:Class rdf:ID="charityRegistrant">
<rdfs:subClassOf rdf:resource="#registrantType" />
</owl:Class>

<owl:Class rdf:ID="schoolRegistrant">
<rdfs:subClassOf rdf:resource="#registrantType" />
</owl:Class>

<owl:Class rdf:ID="generalRegistrant">
<rdfs:subClassOf rdf:resource="#registrantType" />
</owl:Class>

<!-- define the restrictions that make a registrant type
company or charity -->
<owl:Class rdf:about="#companyRegistrant">
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#type" />
<owl:hasValue rdf:datatype="&xsd;string">UK Limited Company</owl:hasValue>
<owl:minCardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:minCardinality>
</owl:Restriction>
</rdfs:subClassOf>

<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#numberType" />
<owl:hasValue rdf:datatype="&xsd;string">Company Number</owl:hasValue>
<owl:cardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:cardinality>
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>

<owl:Class rdf:about="#charityRegistrant">
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#type" />
<owl:hasValue rdf:datatype="&xsd;string">UK Registered Charity</owl:hasValue>
<owl:cardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:cardinality>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#numberType" />
<owl:hasValue rdf:datatype="&xsd;string">Charity Number</owl:hasValue>
<owl:cardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:cardinality>
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>

<owl:Class rdf:about="#schoolRegistrant">
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#type" />
<owl:hasValue rdf:datatype="&xsd;string">UK Registered School</owl:hasValue>
<owl:cardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:cardinality>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#numberType" />
<owl:hasValue rdf:datatype="&xsd;string">Charity Number</owl:hasValue>
<owl:cardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:cardinality>
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>

<!-- ****************** -->
<!-- Registrant Address -->
<!-- ****************** -->

<owl:Class rdf:ID="registrantAddress">
<rdfs:comment>This is the registrant's recorded address</rdfs:comment>
<rdfs:label>registrant Address</rdfs:label>
</owl:Class>

<owl:DatatypeProperty rdf:ID="addressLine1">
<rdfs:comment>First line of the registrant's address</rdfs:comment>
<rdfs:label>address line 1</rdfs:label>
<rdfs:domain rdf:resource="#registrantAddress"/>
<rdfs:range rdf:resource="&xsd;string"/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID="addressLine2">
<rdfs:comment>Second line of the registrant's address</rdfs:comment>
<rdfs:label>address line 2</rdfs:label>
<rdfs:domain rdf:resource="#registrantAddress"/>
<rdfs:range rdf:resource="&xsd;string"/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID="addressLine3">
<rdfs:comment>Third line of the registrant's address</rdfs:comment>
<rdfs:label>address line 3</rdfs:label>
<rdfs:domain rdf:resource="#registrantAddress"/>
<rdfs:range rdf:resource="&xsd;string"/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID="addressLine4">
<rdfs:comment>Fourth line of the registrant's address</rdfs:comment>
<rdfs:label>address line 4</rdfs:label>
<rdfs:domain rdf:resource="#registrantAddress"/>
<rdfs:range rdf:resource="&xsd;string"/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID="postcode">
<rdfs:comment>Registrant's address postcode</rdfs:comment>
<rdfs:label>registrant postcode</rdfs:label>
<rdfs:domain rdf:resource="#registrantAddress"/>
<rdfs:range rdf:resource="&xsd;string"/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID="country">
<rdfs:comment>Registrant's address country</rdfs:comment>
<rdfs:label>country</rdfs:label>
<rdfs:domain rdf:resource="#registrantAddress"/>
<rdfs:range rdf:resource="&xsd;string"/>
</owl:DatatypeProperty>

<!-- ****************** -->
<!-- Registrant's agent -->
<!-- ****************** -->
<!-- The Tag class and its properties -->
<owl:Class rdf:ID="tag" />
<owl:ObjectProperty rdf:ID="hasRegistrationAgent">
<rdfs:domain rdf:resource="#domainName"/>
<rdfs:range rdf:resource="#tag"/>
<owl:inverseOf rdf:resource="#agentFor"/>
</owl:ObjectProperty>

<!-- this next bit could easily be inferred, but is included for completeness -->
<owl:ObjectProperty  rdf:ID="agentFor">
<rdfs:domain rdf:resource="#tag"/>
<rdfs:range rdf:resource="#domainName"/>
<owl:inverseOf rdf:resource="#hasRegistrationAgent"/>
</owl:ObjectProperty>

<owl:DatatypeProperty rdf:ID="publicURL">
<rdfs:comment>tag holder URL</rdfs:comment>
<rdfs:label>publicURL</rdfs:label>
<rdfs:domain rdf:resource="#tag" />
<rdfs:range rdf:resource="&xsd;anyURI"/>
</owl:DatatypeProperty>

<!-- ****************** -->
<!-- relevant dates -->
<!-- ****************** -->
<owl:DatatypeProperty rdf:ID="registeredOn">
<rdfs:domain rdf:resource="#domainName"/>
<rdfs:range rdf:resource="&xsd;date"/>
</owl:DatatypeProperty>

<owl:DatatypeProperty rdf:ID="renewalDue">
<rdfs:domain rdf:resource="#domainName"/>
<rdfs:range rdf:resource="&xsd;date"/>
</owl:DatatypeProperty>

<owl:DatatypeProperty rdf:ID="lastUpdated">
<rdfs:domain rdf:resource="#domainName"/>
<rdfs:range rdf:resource="&xsd;date"/>
</owl:DatatypeProperty>

<!-- certain dates are mandatory -->
<owl:Class rdf:about="#domainName">
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#registeredOn" />
<owl:cardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:cardinality>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#lastUpdated" />
<owl:cardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:cardinality>
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>

<!-- ****************** -->
<!-- registration status -->
<!-- ****************** -->
<owl:DatatypeProperty rdf:ID="hasStatus">
<rdfs:domain rdf:resource="#domainName"/>
<rdfs:range rdf:resource="&xsd;string"/>
</owl:DatatypeProperty>

<!-- ****************** -->
<!-- Name servers -->
<!-- ****************** -->
<!-- add the name server property -->
<owl:DatatypeProperty rdf:ID="nameServer">
<rdfs:domain rdf:resource="#domainName"/>
<rdfs:range rdf:resource="&xsd;string"/>
</owl:DatatypeProperty>

<!-- specify how many nameservers a domain name can have -->
<owl:Restriction>
<owl:onProperty rdf:resource="#nameServer" />
<owl:minCardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:minCardinality>
<owl:maxCardinality rdf:datatype="&xsd;nonNegativeInteger">10</owl:maxCardinality>
</owl:Restriction>

</rdf:RDF>

One bug with SWeDE I found was that it incorrectly flagged references to datatypes: <rdfs:range rdf:resource="&xsd;string"/> as being incorrect when validating.
This seems to have already been logged as a bug, yet to be resolved.
Passing the example through the validator shows it to be correct however.

3 Responses

  1. Stéphane Bortzmeyer Says:

    For the RDF-impaired like me, is it possible to explain the purpose of this exercice in more practical terms?Will it make the search engines able to index properly the output of a whois server, and query it in a meaningful way?

  2. Nodalities » Blog Archive » This Week’s Semantic Web Says:

    […] WHOIS Ontology, Who’s who description vocabulary, BIO: A vocabulary for biographical information […]

  3. Pawel Says:

    Have you tried to edit OWL ontologies with Controlled Natural Language instead of old-fashioned, xml-based OWL editors?!
    Recently Cognitum from Poland released FluentEditor for OWL - a Tool for manipulating complex ontologies with Controlled English:

    http://www.cognitum.eu/Products/FluentEditor/

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.

Recent Posts

Highest Rated

Categories

Archives

Meta: