diff --git a/shacl12-core/index.html b/shacl12-core/index.html index 6aeb016e..91434c80 100644 --- a/shacl12-core/index.html +++ b/shacl12-core/index.html @@ -5899,6 +5899,7 @@

sh:xone

A SHACL list of shapes to validate the value nodes against. Each value of sh:xone in a shape is a SHACL list. Each member of such list must be a well-formed shape. + There should be at least one member of such list. @@ -7299,6 +7300,7 @@

sh:in

A SHACL list that has the allowed values as members. Each value of sh:in in a shape is a SHACL list. A shape has at most one value for sh:in. + There should be at least one member of such list. diff --git a/shacl12-test-suite/tests/core/node/in-002.ttl b/shacl12-test-suite/tests/core/node/in-002.ttl new file mode 100644 index 00000000..7b55364f --- /dev/null +++ b/shacl12-test-suite/tests/core/node/in-002.ttl @@ -0,0 +1,46 @@ +@prefix ex: . +@prefix mf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix sht: . +@prefix xsd: . + +ex:Instance + rdf:type ex:TestShape ; +. +ex:TestInUnsatisfiableShape + rdf:type rdfs:Class ; + rdf:type sh:NodeShape ; + rdfs:comment "Unsatisfiable due to empty sh:in list. SHACL-SHACL would raise a warning about the empty list."@en ; + rdfs:label "Test shape" ; + sh:in () ; +. +<> + rdf:type mf:Manifest ; + mf:entries ( + + ) ; +. + + rdf:type sht:Validate ; + rdfs:label "Test of sh:in at node 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:Instance ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:InConstraintComponent ; + sh:sourceShape ex:TestShape ; + sh:value ex:Instance ; + ] ; + ] ; + mf:status sht:approved ; +. diff --git a/shacl12-test-suite/tests/core/node/in-003.ttl b/shacl12-test-suite/tests/core/node/in-003.ttl new file mode 100644 index 00000000..0f9def74 --- /dev/null +++ b/shacl12-test-suite/tests/core/node/in-003.ttl @@ -0,0 +1,55 @@ +@prefix ex: . +@prefix mf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix sht: . +@prefix xsd: . + +ex:TestInUnsatisfiableShape + rdf:type rdfs:Class ; + rdf:type sh:NodeShape ; + rdfs:label "Test shape" ; + sh:in rdf:nil ; +. +shsh:inSubjectsShape + a sh:NodeShape ; + rdfs:isDefinedBy shsh: ; + sh:property shsh:inSubjectsShapeXonePropertyShape ; + sh:targetSubjectsOf sh:in ; + . +shsh:inSubjectsShapeInPropertyShape + a sh:PropertyShape ; + rdfs:isDefinedBy shsh: ; + sh:path sh:in ; + sh:minListLength 1 ; + sh:severity sh:Warning ; + . +<> + rdf:type mf:Manifest ; + mf:entries ( + + ) ; +. + + rdf:type sht:Validate ; + rdfs:label "Test of sh:in 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 ex:TestInUnsatisfiableShape ; + sh:resultSeverity sh:Warning ; + sh:sourceConstraintComponent sh:MinListLengthConstraintComponent ; + sh:sourceShape shsh:inSubjectsShapeInPropertyShape ; + sh:value rdf:nil ; + ] ; + ] ; + mf:status sht:approved ; +. diff --git a/shacl12-test-suite/tests/core/node/xone-002.ttl b/shacl12-test-suite/tests/core/node/xone-002.ttl new file mode 100644 index 00000000..d17f8db1 --- /dev/null +++ b/shacl12-test-suite/tests/core/node/xone-002.ttl @@ -0,0 +1,45 @@ +@prefix ex: . +@prefix mf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix sht: . +@prefix xsd: . + +ex:Bob + rdf:type ex:Person ; +. +ex:TestXoneUnsatisfiableShape + rdf:type sh:NodeShape ; + rdfs:comment "Unsatisfiable due to empty sh:xone list. SHACL-SHACL would raise a warning about the empty list."@en ; + sh:targetClass ex:Person ; + sh:xone () ; +. +<> + rdf:type mf:Manifest ; + mf:entries ( + + ) ; +. + + rdf:type sht:Validate ; + rdfs:label "Test of sh:xone at node 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:Bob ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:XoneConstraintComponent ; + sh:sourceShape ex:TestXoneUnsatisfiableShape ; + sh:value ex:Bob ; + ] ; + ] ; + mf:status sht:approved ; +. diff --git a/shacl12-test-suite/tests/core/node/xone-003.ttl b/shacl12-test-suite/tests/core/node/xone-003.ttl new file mode 100644 index 00000000..f2932671 --- /dev/null +++ b/shacl12-test-suite/tests/core/node/xone-003.ttl @@ -0,0 +1,55 @@ +@prefix ex: . +@prefix mf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix shsh: . +@prefix sht: . +@prefix xsd: . + +ex:TestXoneUnsatisfiableShape + rdf:type sh:NodeShape ; + sh:targetClass ex:Person ; + sh:xone rdf:nil ; +. +shsh:xoneSubjectsShape + a sh:NodeShape ; + rdfs:isDefinedBy shsh: ; + sh:property shsh:xoneSubjectsShapeXonePropertyShape ; + sh:targetSubjectsOf sh:xone ; + . +shsh:xoneSubjectsShapeXonePropertyShape + a sh:PropertyShape ; + rdfs:isDefinedBy shsh: ; + sh:path sh:xone ; + sh:minListLength 1 ; + sh:severity sh:Warning ; + . +<> + rdf:type mf:Manifest ; + mf:entries ( + + ) ; +. + + rdf:type sht:Validate ; + rdfs:label "Test of sh:xone 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 ex:TestXoneUnsatisfiableShape ; + sh:resultSeverity sh:Warning ; + sh:sourceConstraintComponent sh:MinListLengthConstraintComponent ; + sh:sourceShape shsh:xoneSubjectsShapeXonePropertyShape ; + sh:value rdf:nil ; + ] ; + ] ; + mf:status sht:approved ; +. diff --git a/shacl12-vocabularies/shacl-shacl.ttl b/shacl12-vocabularies/shacl-shacl.ttl index 31f7e7a5..882e56f2 100644 --- a/shacl12-vocabularies/shacl-shacl.ttl +++ b/shacl12-vocabularies/shacl-shacl.ttl @@ -164,7 +164,6 @@ shsh:ShapeShape sh:property [ sh:path sh:in ; sh:maxCount 1 ; # in-maxCount - sh:minListLength 1 ; # in-minListLength ] ; sh:property [ sh:path sh:languageIn ; @@ -294,7 +293,7 @@ shsh:ShapeShape ] ; sh:property [ sh:path sh:xone ; - sh:memberShape shsh:ShapeShape ; # xone-memberShape + sh:memberShape shsh:ShapeShape ; # xone-members-node ] . shsh:NodeShapeShape @@ -347,6 +346,35 @@ shsh:ShapesListShape sh:targetObjectsOf sh:xone ; # xone-members-node sh:memberShape shsh:ShapeShape . +# Values of sh:in and sh:xone should have length >= 1. +shsh:inSubjectsShape + a sh:NodeShape ; + rdfs:comment "A shape that raises warnings on unsatisfiable lists. If some use case requires a length-0 list on 'sh:in', this graph should be supplemented with 'shsh:inSubjectsShape sh:deactivated true .'."@en ; + sh:property shsh:inSubjectsShapeInPropertyShape ; + sh:targetSubjectsOf sh:in ; + . + +shsh:inSubjectsShapeInPropertyShape + a sh:PropertyShape ; + sh:path sh:in ; + sh:minListLength 1 ; # in-minListLength + sh:severity sh:Warning ; + . + +shsh:xoneSubjectsShape + a sh:NodeShape ; + rdfs:comment "A shape that raises warnings on unsatisfiable lists. If some use case requires a length-0 list on 'sh:xone', this graph should be supplemented with 'shsh:xoneSubjectsShape sh:deactivated true .'."@en ; + sh:property shsh:xoneSubjectsShapeXonePropertyShape ; + sh:targetSubjectsOf sh:xone ; + . + +shsh:xoneSubjectsShapeXonePropertyShape + a sh:PropertyShape ; + sh:path sh:xone ; + sh:minListLength 1 ; # xone-minListLength + sh:severity sh:Warning ; + . + # A path of blank node path syntax, used to simulate recursion _:PathPath sh:alternativePath (