From 08ebd8b8b4ed291631293713bafa0cd4af6d5e4a Mon Sep 17 00:00:00 2001 From: Holger Knublauch Date: Tue, 3 Jun 2025 11:51:07 +0200 Subject: [PATCH 1/3] #160: Allow lists at sh:class and sh:datatype --- shacl12-core/index.html | 88 +++++++++++++++-- .../tests/core/node/datatype-003.ttl | 45 +++++++++ .../tests/core/node/manifest.ttl | 1 + .../tests/core/property/class-002.ttl | 98 +++++++++++++++++++ .../tests/core/property/datatype-004.ttl | 62 ++++++++++++ .../tests/core/property/manifest.ttl | 2 + 6 files changed, 287 insertions(+), 9 deletions(-) create mode 100644 shacl12-test-suite/tests/core/node/datatype-003.ttl create mode 100644 shacl12-test-suite/tests/core/property/class-002.ttl create mode 100644 shacl12-test-suite/tests/core/property/datatype-004.ttl diff --git a/shacl12-core/index.html b/shacl12-core/index.html index 8ee3e261..05c38155 100644 --- a/shacl12-core/index.html +++ b/shacl12-core/index.html @@ -3008,7 +3008,7 @@

Value Type Constraint Components

sh:class

- The condition specified by sh:class is that each value node is a SHACL instance of a given type. + The condition specified by sh:class is that each value node is a SHACL instance of the given type(s).

Constraint Component IRI: sh:ClassConstraintComponent @@ -3024,7 +3024,8 @@

sh:class

sh:class The type of all value nodes. - The values of sh:class in a shape are IRIs. + The values of sh:class in a shape are either IRIs + or blank nodes that are well-formed SHACL lists where all members are IRIs. @@ -3032,8 +3033,12 @@

sh:class

TEXTUAL DEFINITION
Let $class be a parameter value for sh:class. + Let classes be a set of IRIs so that + when $class is an IRI then the set only consists of exactly that IRI, + and when $class is a blank node SHACL list then the set consists of + exactly the members of the list.

For each value node - that is either a literal, or a non-literal that is not a SHACL instance of $class in the data graph, + that is either a literal, or a non-literal that is not a SHACL instance of any of the classes in the data graph, there is a validation result with the value node as sh:value.
@@ -3041,6 +3046,7 @@

sh:class

Note that multiple values for sh:class are interpreted as a conjunction, i.e. the values need to be SHACL instances of all of them. + Use lists for union semantics.

+

+ The following example illustrates the list-based syntax for sh:class, + meaning that the values of the property ex:pet must be either cats or dogs. +

+
@@ -3134,9 +3171,10 @@

sh:datatype

sh:datatype - The datatype of all value nodes (e.g., xsd:integer). - The values of sh:datatype in a shape are IRIs. + The allowed datatype(s) of all value nodes (e.g., xsd:integer). A shape has at most one value for sh:datatype. + The value of sh:datatype in a shape is either an IRI + or a blank node that is a well-formed SHACL list where all members are IRIs. @@ -3144,9 +3182,13 @@

sh:datatype

TEXTUAL DEFINITION
Let $datatype be a parameter value for sh:datatype. + Let datatypes be a set of IRIs so that + when $datatype is an IRI then the set only consists of exactly that IRI, + and when $datatype is a blank node SHACL list then the set consists of + exactly the members of the list.

For each value node - that is not a literal, or is a literal with a datatype that does not match $datatype, - there is a validation result with the value node as sh:value. + that is not a literal, or is a literal with a datatype that matches none of the datatypes, + there is a validation result with the value node as sh:value.

The datatype of a literal is determined following the datatype function of SPARQL 1.2. A literal matches a datatype if the literal's datatype has the same IRI and, for the datatypes supported by SPARQL 1.2, is not an ill-typed literal. @@ -3155,9 +3197,8 @@

sh:datatype

The remainder of this section is informative.

The values of sh:datatype are typically datatypes, such as xsd:string. - Note that using rdf:langString as value of sh:datatype can be used to test if value nodes have a language tag.

-
@@ -6656,6 +6725,7 @@

Changes between SHACL 1.0 Core and SHACL 1.2 Core

  • Added the new class sh:ShapeClass for implicit class targets, see Issue 212
  • Moved SPARQL-based validators from Core to an Appendix of SHACL-SPARQL, see Issue 271
  • Added the new constraint component sh:expression, see Issue 357
  • +
  • The values of sh:class and sh:datatype can now also be lists, indicating a union of choices, see Issue 160
  • diff --git a/shacl12-test-suite/tests/core/node/datatype-003.ttl b/shacl12-test-suite/tests/core/node/datatype-003.ttl new file mode 100644 index 00000000..25865f34 --- /dev/null +++ b/shacl12-test-suite/tests/core/node/datatype-003.ttl @@ -0,0 +1,45 @@ +@prefix dash: . +@prefix ex: . +@prefix mf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix sht: . +@prefix xsd: . + +ex:TestShape + rdf:type sh:NodeShape ; + sh:datatype ( xsd:string rdf:langString ) ; + sh:targetNode "Hello"^^rdf:HTML ; + sh:targetNode "G'day"@en-AU ; + sh:targetNode "Hallo"@de ; + sh:targetNode "Hello" ; +. +<> + rdf:type mf:Manifest ; + mf:entries ( + + ) ; +. + + rdf:type sht:Validate ; + rdfs:label "Test of sh:datatype at node shape 003" ; + mf:action [ + sht:dataGraph <> ; + sht:shapesGraph <> ; + ] ; + mf:result [ + rdf:type sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode "Hello"^^rdf:HTML ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape ex:TestShape ; + sh:value "Hello"^^rdf:HTML ; + ] ; + ] ; + mf:status sht:approved ; +. diff --git a/shacl12-test-suite/tests/core/node/manifest.ttl b/shacl12-test-suite/tests/core/node/manifest.ttl index 2499c99e..2c30a106 100644 --- a/shacl12-test-suite/tests/core/node/manifest.ttl +++ b/shacl12-test-suite/tests/core/node/manifest.ttl @@ -14,6 +14,7 @@ mf:include ; mf:include ; mf:include ; + mf:include ; mf:include ; mf:include ; mf:include ; diff --git a/shacl12-test-suite/tests/core/property/class-002.ttl b/shacl12-test-suite/tests/core/property/class-002.ttl new file mode 100644 index 00000000..50ae0562 --- /dev/null +++ b/shacl12-test-suite/tests/core/property/class-002.ttl @@ -0,0 +1,98 @@ +@prefix dash: . +@prefix ex: . +@prefix mf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix sht: . +@prefix xsd: . + +ex:InvalidResource1 + rdf:type rdfs:Resource ; + ex:testProperty ex:InvalidResource1 ; + ex:testProperty "A string" ; +. +ex:OtherClass + rdf:type rdfs:Class ; +. +ex:OtherClassInstance + rdf:type ex:OtherClass ; +. +ex:SubClass + rdf:type rdfs:Class ; + rdfs:subClassOf ex:SuperClass ; +. +ex:SubClassInstance + rdf:type ex:SubClass ; +. +ex:SuperClass + rdf:type rdfs:Class ; +. +ex:SuperClassInstance + rdf:type ex:SuperClass ; +. +ex:TestShape + rdf:type sh:NodeShape ; + sh:property ex:TestShape-testProperty ; + sh:targetNode ex:InvalidResource1 ; + sh:targetNode ex:ValidResource1 ; + sh:targetNode ex:ValidResource2 ; +. +ex:TestShape-testProperty + sh:path ex:testProperty ; + rdfs:label "test property" ; + sh:class ( ex:SuperClass ex:OtherClass ) ; +. +ex:ValidResource1 + rdf:type rdfs:Resource ; + ex:testProperty ex:OtherClassInstance ; + ex:testProperty ex:SubClassInstance ; + ex:testProperty ex:SuperClassInstance ; +. +ex:ValidResource2 + rdf:type rdfs:Resource ; + ex:testProperty [ + rdf:type ex:SubClass ; + ] ; + ex:testProperty [ + rdf:type ex:SuperClass ; + ] ; +. +<> + rdf:type mf:Manifest ; + mf:entries ( + + ) ; +. + + rdf:type sht:Validate ; + rdfs:label "Test of sh:class at property shape 002" ; + mf:action [ + sht:dataGraph <> ; + sht:shapesGraph <> ; + ] ; + mf:result [ + rdf:type sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:InvalidResource1 ; + sh:resultPath ex:testProperty ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:ClassConstraintComponent ; + sh:sourceShape ex:TestShape-testProperty ; + sh:value ex:InvalidResource1 ; + ] ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:InvalidResource1 ; + sh:resultPath ex:testProperty ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:ClassConstraintComponent ; + sh:sourceShape ex:TestShape-testProperty ; + sh:value "A string" ; + ] ; + ] ; + mf:status sht:approved ; +. diff --git a/shacl12-test-suite/tests/core/property/datatype-004.ttl b/shacl12-test-suite/tests/core/property/datatype-004.ttl new file mode 100644 index 00000000..7d39af51 --- /dev/null +++ b/shacl12-test-suite/tests/core/property/datatype-004.ttl @@ -0,0 +1,62 @@ +@prefix dash: . +@prefix ex: . +@prefix mf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix sht: . +@prefix xsd: . + +ex:InvalidInstance1 + ex:value 42 ; +. +ex:TestShape + rdf:type sh:NodeShape ; + sh:property ex:TestShape-value ; + sh:targetNode ex:InvalidInstance1 ; + sh:targetNode ex:ValidInstance1 ; + sh:targetNode ex:ValidInstance2 ; + sh:targetNode ex:ValidInstance3 ; +. +ex:TestShape-value + sh:path ex:value ; + sh:datatype ( xsd:string rdf:langString ) ; +. +ex:ValidInstance1 + ex:value "A" ; +. +ex:ValidInstance2 + ex:value "A" ; +. +ex:ValidInstance3 + ex:value "A"@en ; +. +<> + rdf:type mf:Manifest ; + mf:entries ( + + ) ; +. + + rdf:type sht:Validate ; + rdfs:label "Test of sh:datatype at property shape 004" ; + mf:action [ + sht:dataGraph <> ; + sht:shapesGraph <> ; + ] ; + mf:result [ + rdf:type sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:InvalidInstance1 ; + sh:resultPath ex:value ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape ex:TestShape-value ; + sh:value 42 ; + ] ; + ] ; + mf:status sht:approved ; +. diff --git a/shacl12-test-suite/tests/core/property/manifest.ttl b/shacl12-test-suite/tests/core/property/manifest.ttl index 5648df92..2ab26040 100644 --- a/shacl12-test-suite/tests/core/property/manifest.ttl +++ b/shacl12-test-suite/tests/core/property/manifest.ttl @@ -7,9 +7,11 @@ rdfs:label "Tests converted from http://datashapes.org/sh/tests/tests/core/property" ; mf:include ; mf:include ; + mf:include ; mf:include ; mf:include ; mf:include ; + mf:include ; mf:include ; mf:include ; mf:include ; From 44d90f6e69255a100f554394baf17b8f880174f8 Mon Sep 17 00:00:00 2001 From: Holger Knublauch Date: Thu, 12 Jun 2025 15:40:55 +0200 Subject: [PATCH 2/3] Update shacl12-core/index.html Co-authored-by: Ted Thibodeau Jr --- shacl12-core/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shacl12-core/index.html b/shacl12-core/index.html index 05c38155..582b2cce 100644 --- a/shacl12-core/index.html +++ b/shacl12-core/index.html @@ -6722,10 +6722,10 @@

    Changes between SHACL 1.0 Core and SHACL 1.2 Core

    From 4eebdad51b1e7994ea5f95737a39af93ce10a564 Mon Sep 17 00:00:00 2001 From: Holger Knublauch Date: Tue, 17 Jun 2025 07:35:25 +0200 Subject: [PATCH 3/3] Update shacl12-core/index.html Co-authored-by: Ted Thibodeau Jr --- shacl12-core/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shacl12-core/index.html b/shacl12-core/index.html index 582b2cce..698ee74b 100644 --- a/shacl12-core/index.html +++ b/shacl12-core/index.html @@ -3045,7 +3045,7 @@

    sh:class

    The remainder of this section is informative.

    Note that multiple values for sh:class are interpreted as a conjunction, - i.e. the values need to be SHACL instances of all of them. + i.e., the values need to be SHACL instances of all of them. Use lists for union semantics.