Search code examples
linked-datashacl

How to restrict units in property shapes?


I'm looking to make some SHACL shapes for certain properties in my ontology that have a speicified unit. Example:

My instance data would look something like this:

otlc:surgeprotector_1
  rdf:type otlc:Surgeprotector ;
  otlc:Nominal_voltage[
      rdf:type otlc:QuantityValue ;
      rdf:value "225"^^xsd:float ;
      otlc:hasUnit unit:KiloV ;
    ] ;
.

I then have some shapes to validate this data:

otlc:Nominal_voltageShape
  rdf:type sh:PropertyShape ;
  sh:path otlc:Nominal_voltage ;
  sh:class otlc:QuantityValue ;
  **otlc:hasUnit unit:KiloV ;**
  sh:maxCount 1 ;
  sh:minCount 1 ;
.

otlc:SurgeprotectorShape
  rdf:type sh:NodeShape ;
  sh:property otlc:Nominal_voltageShape ;
  sh:targetClass otlc:Surgeprotector ;
.

My question: How can I specify the unit given for the predicate "otlc:hasUnit" in the instance data for each property in my ontology? My desired end result is to have a nodeshape for the surgeprotector, and a propertyshape for the property "nominal_voltage", to restrict the value for nominal_voltage to unit:KiloV. I'm hoping there is some kind of shacl keyword I had not heard of/realized I can use here, to add onto my propertyshape (right now, i put in what I would imagine exists for shacl in **). (for example, sh:pattern can be used to specify the value with regex, but I want to specify the value of a piece of metadata of my value, if that makes sense...)

Thanks in advance! Robin


Solution

  • I believe you can replace your highlighted line with

    sh:property [
        sh:path otlc:hasUnit ;
        sh:hasValue unit:KiloV ;
    ] ;
    

    This would mean that this property shape must apply to all values of the surrounding property shape, i.e. all values of otlc:Nominal_voltage.

    Alternative, you could use a path expression in a property shape one level higher up, e.g.

    otlc:SurgeprotectorShape
        ...
        sh:property [
            sh:path ( otlc:Nominal_voltage otlc:hasUnit ) ;
            sh:hasValue unit:KiloV ;
        ] ;
    

    Note that sh:hasValue also implies sh:minCount 1, i.e. the value must be present. You may want to add sh:maxCount 1 as extra protection.