See also: List of existing extensions for GoodRelations
This document explains how ontologies describing product and services categories plus their attributes must be designed in order to be compatible with the GoodRelations ontology.
In order to use this document, you should be familiar with ontology engineering in RDF-S and OWL and respective tools (e.g. Protégé).
The GoodRelations ontology consists of two parts:
a) a set of elements for describing Web offerings. Web offerings are basically statements made via a Web resource that some legal entity is offering to e.g. sell, lease out, or repair a certain good, or to provide a certain service and
b) a small top-level ontology for products and services ontologies. This part defines a few very important abstract elements which are meant to be specialized by a particular products or services ontology.
In this document, we describe the top-level part of GoodRelations only (b), because that must be the basis for every products or services ontology. While it may also make sense to import and refine part a) of GoodRelations in some scenarios, this is outside the scope of this document.
Each product or services ontology typically defines elements of the following fundamental types:
Product or Services Classes:Categories of products or services that provide the same functionality or benefit, or that are of the same nature. Examples are "TV set", "digital Camera", "laptop computer", etc. Services classes summarize activities, e.g. "hairdressing" or "dry cleaning". Note that such classes are vendor-neutral and not to be mixed up with product models (like a particular car make and model - "Ford T" or "VW Golf").
Properties: An instance of a products or services class can be described in more detail using properties. For example, a TV set can be described by its screen size, a laptop computer by its weight, etc.
Properties can be either qualitative or quantitative: Qualitative properties are such that refer to a single value from a given set of possible values, or such that refer to text data or simple yes/no decision s (e.g., that are of type boolean).
Quantitative propertiesare such that refer to a quantitative measurement, which can at least theoretically be specified as a range. Examples are screen size, weight, seating capacity, operating voltage, etc.
Value sets and Values:For qualitative values, it is often helpful to define the allowed values as a fine set of individuals. For example, if cellphones have the qualitative property "hasBatteryType", it may make sense to define a class for all battery types named "BatteryType" and two allowed value instances "Lithium-ion" and "Nickel metal hydride" .
In GoodRelations, we know the following three fundamental types of properties for product features:
For reasons explained in more detail in the GoodRelations technical report, datatypeProductOrServicePropertyis an owl:DatatypeProperty, and both qualitativeProductOrServiceProperty and quantitativeProductOrServicePropertyare owl:ObjectProperties. In short this is because ranges are represented in GoodRelations as instances of a QuantitativeValue class, for they can otherwise hardly be represented in OWL.
The basic approach for building a domain-specific products and services ontology is pretty straightforward:
Hint on Naming: We suggest that you use lower caps for the initial character of properties and capitals for the initial character of classes and values. Also, use singular for all product classes rather than plural ("TV set" instead of "TV sets", and start property names with "has" ("hasScreenSize" instead of "screenSize").
1. Define all classes of products and services types that you need.
Example: TVSet, !ComputerMouse, Apartment
2. Collect all relevant properties (typical product features) for each class:
Example:
3. Determine for all properties which type of property they are, i.e.
Also, determine the proper range for each property.
Example:
4. For all value types that have to be defined for qualitativeProductOrServiceProperties, define a suitable class and collect all relevant values as instances:
Example: We have to define a class for the special value type "InterfaceType"and instances thereof like "USB", "PS2", and "RS232", reflecting typical interface types.
Note: GoodRelations supports multiple units of measurements for quantitative properties. You do not need to and should not define the intended unit of measurement as part of the property. If you want users to employ only a single unit, add a respective recommendation in the textual description of the property.
Click to enlarge.
Now, create the OWL ontology using a tool of your choice by using the following procedure:
1. Create a new OWL ontology file.
2. Import the GoodRelations ontology from <http://purl.org/goodrelations/v1>
3. Define a namespace prefix "gr:" for "http://purl.org/goodrelations/v1#"
4. Create one owl:Class for each class of product or service, and make each class an rdfs:subClassOf gr:ProductOrService
Example:
5. Create respective properties for each of your product properties using the following schema
a) For a datatypeProductOrServiceProperty, create an owl:DatatypeProperty and make it an rdfs:subPropertyOf gr:datatypeProductOrServiceProperty
b) For a qualitativeProductOrServiceProperty, create an owl:ObjectProperty and make it an rdfs:subPropertyOf gr:qualitativeProductOrServiceProperty
c) For a quantitativeProductOrServiceProperty, create an owl:ObjectProperty (!!!) and make it an rdfs:subPropertyOf gr:quantitativeProductOrServiceProperty
Example:
6. Create an owl:Class for all value types that you have defined, make it and rdfs:subClassOf gr:QualitativeValue, and create instances thereof for all relevant values
Example:
7. Specify property ranges properly
For each of your properties, you should define the ranges accordingly. Despite the weird OWL/RDF-S semantics of ranges and domains (see below for details), specifying ranges helps tools suggest suitable values and creating forms for entering data.
Use the following schema:
a) For a datatypeProductOrServiceProperty
Examples are properties like "hasPhoneNumber" or other cases wherre the integer value cannot be understood as a quantity.
Such cases are rather rare, and often the correct modeling choice will be to change the property to quantitativeProductOrServiceProperty (if whart you really model are quantities) or qualitativeProductOrServiceProperty (if what you really model are enumerated values).
b) For a qualitativeProductOrServiceProperty
Example: The range of ex:hasInterfaceType is ex:InterfaceType. It could also be simply set to gr:QualitativeValue.
c) For a quantitativeProductOrServiceProperty
8. Specify property domains if necessary
As for all properties, the domain is by default set to ProductOrService. You can narrow down the domain of one of your properties to a single class or combination of classes. However, this is often hard to achieve, because it requires a very clean taxonomy of goods and still often creates redundancy or nasty inconsistencies. Also, note that the semantics of domains in OWL and RDF-S is inferring additional class membership (!), which usually has unwanted side-effects instead of warning the user of inconsistencies. (In a nutshell, if you define the domain of "hasScreenSize" as "TV Set", and someone applies "hasScreenSize" to a "Window", then the system will assume that the window is also a TV Set, instead of warning or forbidding that usage.)
9. Save your ontology, test it, and publish it!
Recommendations on how to publish your ontology are e.g. given here: http://www.w3.org/TR/swbp-vocab-pub/
The following is the full code of the example used in this tutorial in RDF/XML.
<!-- Created with Protege (with OWL Plugin 3.3.1, Build 430) http://protege.stanford.edu -->
<?xml version="1.0"?>
rdf:RDF
<ns="http://www.heppnetz.de/ontologies/examples/toy#"
xmlns:protege="http://protege.stanford.edu/plugins/owl/protege#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:gr="http://purl.org/goodrelations/v1#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xml:base="http://www.heppnetz.de/ontologies/examples/toy">
owl:Ontology rdf:about="">
<dc:rights rdf:datatype="http://www.w3.org/2001/XMLSchema#string">
<
This toy ontology is available under the Creative Commons Attribution 3.0 license;
see http://creativecommons.org/licenses/by/3.0/.dc:rights>
</owl:imports rdf:resource="http://purl.org/goodrelations/v1"/>
<dc:creator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">
<
Martin Hepp, http://www.heppnetz.dedc:creator>
</owl:Ontology>
</owl:Class rdf:ID="Apartment">
<rdfs:subClassOf rdf:resource="http://purl.org/goodrelations/v1#ProductOrService"/>
<owl:Class>
</owl:Class rdf:ID="TVSet">
<rdfs:subClassOf rdf:resource="http://purl.org/goodrelations/v1#ProductOrService"/>
<owl:Class>
</owl:Class rdf:ID="ComputerMouse">
<rdfs:subClassOf rdf:resource="http://purl.org/goodrelations/v1#ProductOrService"/>
<owl:Class>
</owl:Class rdf:ID="InterfaceType">
<rdfs:subClassOf rdf:resource="http://purl.org/goodrelations/v1#QualitativeValue"/>
<owl:Class>
</owl:ObjectProperty rdf:ID="hasOperatingValue">
<rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#quantitativeProductOrServiceProperty"/>
<rdfs:domain rdf:resource="#TVSet"/>
<rdfs:range rdf:resource="http://purl.org/goodrelations/v1#QuantitativeValueInteger"/>
<owl:ObjectProperty>
</owl:ObjectProperty rdf:ID="hasWeight">
<rdfs:domain rdf:resource="#ComputerMouse"/>
<rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#quantitativeProductOrServiceProperty"/>
<rdfs:range rdf:resource="http://purl.org/goodrelations/v1#QuantitativeValueFloat"/>
<owl:ObjectProperty>
</owl:ObjectProperty rdf:ID="hasScreenSize">
<rdfs:domain rdf:resource="#TVSet"/>
<rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#quantitativeProductOrServiceProperty"/>
<rdfs:range rdf:resource="http://purl.org/goodrelations/v1#QuantitativeValueFloat"/>
<owl:ObjectProperty>
</owl:ObjectProperty rdf:ID="hasSize">
<rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#quantitativeProductOrServiceProperty"/>
<rdfs:range rdf:resource="http://purl.org/goodrelations/v1#QuantitativeValueFloat"/>
<rdfs:domain rdf:resource="#Apartment"/>
<owl:ObjectProperty>
</owl:ObjectProperty rdf:ID="hasInterface">
<rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#qualitativeProductOrServiceProperty"/>
<rdfs:domain rdf:resource="#ComputerMouse"/>
<rdfs:range rdf:resource="#InterfaceType"/>
<owl:ObjectProperty>
</owl:DatatypeProperty rdf:ID="hasVideoInput">
<rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#datatypeProductOrServiceProperty"/>
<rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#boolean"/>
<rdfs:domain rdf:resource="#TVSet"/>
<owl:DatatypeProperty>
</owl:DatatypeProperty rdf:ID="hasKitchen">
<rdfs:domain rdf:resource="#Apartment"/>
<rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#boolean"/>
<rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#datatypeProductOrServiceProperty"/>
<owl:DatatypeProperty>
</owl:DatatypeProperty rdf:ID="hasBrandname">
<rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/>
<rdfs:domain rdf:resource="#ComputerMouse"/>
<rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#datatypeProductOrServiceProperty"/>
<owl:DatatypeProperty>
</InterfaceType rdf:ID="PS2"/>
<InterfaceType rdf:ID="RS232"/>
<InterfaceType rdf:ID="USB"/>
<rdf:RDF>
</<!-- Created with Protege (with OWL Plugin 3.3.1, Build 430) http://protege.stanford.edu -->
The following is the full code of the example used in this tutorial in N3 Notation. Note: In a real case, you should add rdfs:label and rdfs:comment properties to all conceptual elements.
# Base: http://www.heppnetz.de/ontologies/examples/toy#
@prefix gr: <http://purl.org/goodrelations/v1#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix default: <http://www.heppnetz.de/ontologies/examples/toy#> .
@prefix protege: <http://protege.stanford.edu/plugins/owl/protege#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
<http://www.heppnetz.de/ontologies/examples/toy>
a owl:Ontology ;
rdfs:label "Toy ontology"@en;
dc:creator "Martin Hepp, http://www.heppnetz.de";
dc:rights """This toy ontology is available under the Creative Commons Attribution 3.0
license; see http://creativecommons.org/licenses/by/3.0/."""@en ;
owl:imports <http://purl.org/goodrelations/v1> .
# Classes for types of products
default:Apartment
a owl:Class ;
rdfs:subClassOf gr:ProductOrService .
default:ComputerMouse
a owl:Class ;
rdfs:subClassOf gr:ProductOrService .
default:TVSet
a owl:Class ;
rdfs:subClassOf gr:ProductOrService .
# Properties
default:hasOperatingValue
a owl:ObjectProperty ;
rdfs:domain default:TVSet ;
rdfs:range gr:QuantitativeValueInteger ;
rdfs:subPropertyOf gr:quantitativeProductOrServiceProperty .
default:hasVideoInput
a owl:DatatypeProperty ;
rdfs:domain default:TVSet ;
rdfs:range xsd:boolean ;
rdfs:subPropertyOf gr:datatypeProductOrServiceProperty .
default:hasKitchen
a owl:DatatypeProperty ;
rdfs:domain default:Apartment ;
rdfs:range xsd:boolean ;
rdfs:subPropertyOf gr:datatypeProductOrServiceProperty .
default:hasWeight
a owl:ObjectProperty ;
rdfs:domain default:ComputerMouse ;
rdfs:range gr:QuantitativeValueFloat ;
rdfs:subPropertyOf gr:quantitativeProductOrServiceProperty .
default:hasSize
a owl:ObjectProperty ;
rdfs:domain default:Apartment ;
rdfs:range gr:QuantitativeValueFloat ;
rdfs:subPropertyOf gr:quantitativeProductOrServiceProperty .
default:hasScreenSize
a owl:ObjectProperty ;
rdfs:domain default:TVSet ;
rdfs:range gr:QuantitativeValueFloat ;
rdfs:subPropertyOf gr:quantitativeProductOrServiceProperty .
default:hasInterface
a owl:ObjectProperty ;
rdfs:domain default:ComputerMouse ;
rdfs:range default:InterfaceType ;
rdfs:subPropertyOf gr:qualitativeProductOrServiceProperty .
default:hasBrandname
a owl:DatatypeProperty ;
rdfs:domain default:ComputerMouse ;
rdfs:range xsd:string ;
rdfs:subPropertyOf gr:datatypeProductOrServiceProperty .
# Value classes and their instances
default:InterfaceType
a owl:Class ;
rdfs:subClassOf gr:QualitativeValue .
default:PS2
a default:InterfaceType .
default:RS232
a default:InterfaceType .
default:USB
a default:InterfaceType .
You can always extend GoodRelations in your own namespace if you need additional properties. There is no need to wait for us to add new elements if you have more data or more granular data. Simply define the additional elements in your own site, ideally directly in RDFa in a special "vocabulary" page, e.g.
For instance, for adding a new property "hasNACE" to the gr:BusinessEntity class, it is sufficient to add this block of markup to your http://acme.com/vocabulary/ page:
<!-- Example of extending GoodRelations with site-specific properties
Step 1: Define a new property; this should be on a central page
e.g. http://acme.com/vocabulary/ -->
div typeof="owl:DatatypeProperty"
< about="http://acme.com/vocabulary/#hasNACE">
span property="rdfs:label">hasNACE</span>
<div rel="rdfs:domain"
< resource="http://purl.org/goodrelations/v1#BusinessEntity"></div>
div rel="rdfs:range"
< resource="http://www.w3.org/2001/XMLSchema#string"></div>
div> </
Then, you can use the property anywhere on your site or even globally. E.g. you could use it in the markup of your main page:
<!-- Attach it to a company -->
div xmlns:acme="http://acme.com/vocabulary/#" typeof="gr:BusinessEntity" about="#company">
<span property="gr:legalName">ACME Inc.</span>
<
NACE code:div property="acme:hasNACE" datatype="xsd:string">0123456</div>
<div> </
If the extensions are new properties or new classes for types of products or services, your modeling pattern should follow the recipe shown here:
That means that for those properties, you will have to make the properties and classes specializations of the meta-model from GoodRelations, i.e.
Example: We want to define a new property hasWifi for indicating Wifi support of a product. The range will be a boolean value, so following from the extensions recipe, it must be an owl:DatatypeProperty and an rdfs:subPropertyOf gr:datatypeProductOrServiceProperty.
On the vocabulary page, we define a new product property:
div typeof="owl:DatatypeProperty"
< about="http://acme.com/vocabulary/#hasWifi">
div rel="rdfs:subPropertyOf"
< resource="http://purl.org/goodrelations/v1#datatypeProductOrServiceProperty"></div>
span property="rdfs:label">hasWifi</span>
<div rel="rdfs:domain"
< resource="http://purl.org/goodrelations/v1#ProductOrService"></div>
div rel="rdfs:range"
< resource="http://www.w3.org/2001/XMLSchema#boolean"></div>
div> </
Then, we can use it on item pages with the full property URI or by defining a namespace prefix for our site:
<!-- Attach it to a product datasheet -->
div xmlns:acme="http://acme.com/vocabulary/#" typeof="gr:ProductOrServiceModel" about="#product">
<span property="gr:name">ACME Anvil with Wifi</span>
<
Wifi:div property="acme:hasWifi" content="true" datatype="xsd:boolean">yes</div>
<div> </