In OWL, class hierarchies are fundamental. A Customer that is a subclass of Organization inherits all of Organization's properties — companyName, phone, address, etc. You define each property once on the superclass, and every subclass gets it automatically through reasoning.
Customer
Organization
companyName
phone
address
SHACL doesn't work this way. Each shape is self-contained. If CustomerShape doesn't explicitly list companyName as a property, then SHACL will not validate (or in closed mode, will actively reject) companyName on Customer instances.
CustomerShape
This creates a mismatch:
OWL world: Organization ├── companyName ├── phone ├── website ← defined on Organization └── foundedYear ← defined on Organization Customer (subClassOf Organization) ├── (inherits companyName, phone, website, foundedYear) └── customerID ← own property SHACL world (WITHOUT flattening): OrganizationShape ├── companyName ✓ ├── phone ✓ ├── website ✓ └── foundedYear ✓ CustomerShape └── customerID ✓ ⊘ companyName not listed — validation fails or rejects it!
RDF Studio's OWL-to-SHACL translator solves this by flattening inherited properties — copying every property from superclass shapes down to subclass shapes.
After flattening:
SHACL world (WITH flattening): OrganizationShape ├── companyName ├── phone ├── website └── foundedYear CustomerShape ├── customerID ← own property ├── companyName ← flattened from Organization ├── phone ← flattened from Organization ├── website ← flattened from Organization └── foundedYear ← flattened from Organization
Now CustomerShape validates all the properties that a Customer instance actually has — both its own and its inherited ones.
The Northwind ontology demonstrates this perfectly. Organization is a superclass with shared properties, and three subclasses specialize it:
# Organization defines shared properties nwo:Organization a owl:Class . nwo:companyName a owl:DatatypeProperty ; rdfs:domain nwo:Organization ; rdfs:range xsd:string . nwo:website a owl:DatatypeProperty ; rdfs:domain nwo:Organization ; rdfs:range xsd:anyURI . nwo:foundedYear a owl:DatatypeProperty ; rdfs:domain nwo:Organization ; rdfs:range xsd:gYear . # Three subclasses nwo:Customer a owl:Class ; rdfs:subClassOf nwo:Organization . nwo:Supplier a owl:Class ; rdfs:subClassOf nwo:Organization . nwo:Shipper a owl:Class ; rdfs:subClassOf nwo:Organization .
OrganizationShape
SupplierShape
ShipperShape
Customers have companyName in the data (inherited from Organization via OWL), but CustomerShape doesn't list it → validation fails.
Now every shape has a complete picture of its instances' expected properties.
The algorithm walks the class hierarchy bottom-up:
rdfs:subClassOf
sh:datatype
sh:minCount
sh:class
Flattening works across multiple levels. If you had:
Thing └── Organization (companyName, website) └── Customer (customerID) └── PremiumCustomer (loyaltyTier)
Then PremiumCustomerShape would contain: loyaltyTier (own) + customerID (from Customer) + companyName, website (from Organization).
PremiumCustomerShape
loyaltyTier
customerID
website
The Northwind ontology uses two different patterns for sharing properties across classes:
nwo:contactName a owl:DatatypeProperty ; rdfs:domain [ owl:unionOf (nwo:Customer nwo:Supplier nwo:Shipper) ] ; rdfs:range xsd:string .
Here, contactName is directly assigned to three classes via owl:unionOf. No inheritance involved — the translator places a property shape on each listed class. This is explicit and clear.
contactName
owl:unionOf
nwo:website a owl:DatatypeProperty ; rdfs:domain nwo:Organization ; rdfs:range xsd:anyURI . nwo:Customer rdfs:subClassOf nwo:Organization .
Here, website belongs to Organization, and Customer gets it through inheritance. The translator must flatten it onto CustomerShape.
Both are valid OWL modeling approaches:
The Northwind ontology uses both — contactName and phone use union domains, while website and foundedYear use inheritance through Organization. RDF Studio's translator handles both patterns correctly.
foundedYear
After generating shapes in RDF Studio, you can verify flattening worked by: