Skip to content

Commit f2f1ccb

Browse files
committed
Add sh:nodeByExpression to spec
1 parent 5e715ec commit f2f1ccb

File tree

1 file changed

+216
-0
lines changed

1 file changed

+216
-0
lines changed

shacl12-core/index.html

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2520,6 +2520,7 @@ <h2>Node Expressions</h2>
25202520
<ul>
25212521
<li>At <a href="#property-shapes"><code>sh:values</code> and <code>sh:defaultValue</code></a> to derive the value nodes of a property shape.</li>
25222522
<li>At <a href="#targetNode"><code>sh:targetNode</code></a> to dynamically compute the targets of a shape.</li>
2523+
<li>At <a href="#NodeByExpressionConstraintComponent"><code>sh:nodeByExpression</code></a> to validate nodes against a dynamically computed set of node shapes.</li>
25232524
<li>At <a href="#ExpressionConstraintComponent"><code>sh:expression</code></a> to validate nodes against a condition.</li>
25242525
<li>At <a href="#deactivated"><code>sh:deactivated</code></a> to deactivate certain shapes under specific conditions.</li>
25252526
</ul>
@@ -6005,6 +6006,220 @@ <h4>sh:reifierShape, sh:reificationRequired</h4>
60056006
</div>
60066007
</aside>
60076008
</section>
6009+
6010+
<section id="NodeByExpressionConstraintComponent">
6011+
<h4>sh:nodeByExpression</h4>
6012+
<p>
6013+
<code>sh:nodeByExpression</code> specifies the condition that each <a>value node</a> conforms to the
6014+
<a>node shapes</a> produced by a <a>node expression</a>.
6015+
The evaluation of these node expressions is repeated for all <a>value nodes</a> of the <a>shape</a>
6016+
as the <a>focus node</a>.
6017+
</p>
6018+
<p>
6019+
<span class="component-class">Constraint Component IRI</span>: <code>sh:NodeByExpressionConstraintComponent</code>
6020+
</p>
6021+
6022+
<div class="parameters">Parameters:</div>
6023+
<table class="term-table">
6024+
<tr>
6025+
<th>Property</th>
6026+
<th>Summary and Syntax Rules</th>
6027+
</tr>
6028+
<tr>
6029+
<td><code>sh:nodeByExpression</code></td>
6030+
<td>
6031+
The <a>node shapes</a> that all value nodes need to conform to.
6032+
<span data-syntax-rule="nodeByExpression-scope">The <a>values</a> of <code>sh:nodeByExpression</code> in a shape must be <a>well-formed</a> <a>node expressions</a>.</span>
6033+
</td>
6034+
</tr>
6035+
</table>
6036+
<div class="def def-text">
6037+
<div class="def-header">TEXTUAL DEFINITION</div>
6038+
<div class="def-text-body" data-validator="NodeByExpression">
6039+
Let <code>$expr</code> be a <a>value</a> of <code>sh:nodeByExpression</code>.
6040+
For each <a>value node</a> <code>v</code>: perform <a>conformance checking</a> of <code>v</code> against each <a>output node</a>
6041+
of <code>evalExpr(expr, <a>data graph</a>, v, {})</code> <code>s</code> that is a <a>node shape</a> in the <a>shapes graph</a>.
6042+
For each conformance check, a <a>failure</a> MUST be produced if the <a>conformance checking</a> of <code>v</code> against <code>s</code> produces a <a>failure</a>.
6043+
Otherwise, if <code>v</code> does not <a>conform</a> to <code>s</code>,
6044+
there is a <a>validation result</a> with <code>v</code> as <code>sh:value</code> and a <a>deep copy</a> of <code>s</code> as <code>sh:sourceConstraint</code>.
6045+
</div>
6046+
</div>
6047+
<p><em>The remainder of this section is informative.</em></p>
6048+
<p>
6049+
<code>sh:nodeByExpression</code> functions similarly to <code>sh:node</code>, but instead of referencing a fixed <a>node shape</a>,
6050+
a referenced <a>node expression</a> is used to dynamically compute the set of <a>node shapes</a> to which each <a>value node</a> must conform.
6051+
</p>
6052+
<p>
6053+
Note that `sh:node` and `sh:nodeByExpression` exhibit the same behavior when given a <a>value</a> that is an <a>IRI</a> of a <a>node shape</a>.
6054+
In this case, `sh:node` directly validates against the specified <a>node shape</a>, whereas `sh:nodeByExpression` interprets the <a>IRI</a>
6055+
as an <a>IRI expression</a> that evaluates to a set containing the same <a>node shape</a>.
6056+
</p>
6057+
<p>
6058+
In the following example, all values of the property <code>ex:address</code> must fulfill the
6059+
constraints expressed by the <a>shape</a> <code>ex:AddressShape</code>.
6060+
</p>
6061+
<aside class="example">
6062+
<div class="shapes-graph">
6063+
<div class="turtle">
6064+
ex:AddressShape
6065+
a sh:NodeShape ;
6066+
sh:property [
6067+
sh:path ex:postalCode ;
6068+
sh:datatype xsd:string ;
6069+
sh:maxCount 1 ;
6070+
] .
6071+
6072+
ex:PersonShape
6073+
a sh:NodeShape ;
6074+
<span class="target-can-be-skipped">sh:targetClass ex:Person ;</span>
6075+
sh:property [ # _:b1
6076+
sh:path ex:address ;
6077+
sh:minCount 1 ;
6078+
sh:node ex:AddressShape ;
6079+
] .
6080+
</div>
6081+
<div class="jsonld">
6082+
<pre class="jsonld">{
6083+
"@graph": [
6084+
{
6085+
"@id": "ex:AddressShape",
6086+
"@type": "sh:NodeShape",
6087+
"sh:property": {
6088+
"sh:datatype": {
6089+
"@id": "xsd:string"
6090+
},
6091+
"sh:maxCount": {
6092+
"@type": "xsd:integer",
6093+
"@value": "1"
6094+
},
6095+
"sh:path": {
6096+
"@id": "ex:postalCode"
6097+
}
6098+
}
6099+
},
6100+
{
6101+
"@id": "ex:PersonShape",
6102+
"@type": "sh:NodeShape",
6103+
"sh:property": {
6104+
"sh:minCount": {
6105+
"@type": "xsd:integer",
6106+
"@value": "1"
6107+
},
6108+
"sh:node": {
6109+
"@id": "ex:AddressShape"
6110+
},
6111+
"sh:path": {
6112+
"@id": "ex:address"
6113+
}
6114+
},
6115+
"sh:targetClass": {
6116+
"@id": "ex:Person"
6117+
}
6118+
}
6119+
]
6120+
}</pre>
6121+
</div>
6122+
</div>
6123+
<div class="data-graph">
6124+
<div class="turtle">
6125+
ex:Bob a ex:Person ;
6126+
ex:address ex:BobsAddress .
6127+
6128+
ex:BobsAddress
6129+
ex:postalCode "1234" .
6130+
6131+
<span class="focus-node-error">ex:Reto</span> a ex:Person ;
6132+
ex:address ex:RetosAddress .
6133+
6134+
ex:RetosAddress
6135+
ex:postalCode 5678 .
6136+
</div>
6137+
<div class="jsonld">
6138+
<pre class="jsonld">{
6139+
"@graph": [
6140+
{
6141+
"@id": "ex:Bob",
6142+
"@type": "ex:Person",
6143+
"ex:address": {
6144+
"@id": "ex:BobsAddress"
6145+
}
6146+
},
6147+
{
6148+
"@id": "ex:BobsAddress",
6149+
"ex:postalCode": "1234"
6150+
},
6151+
{
6152+
"@id": "ex:Reto",
6153+
"@type": "ex:Person",
6154+
"ex:address": {
6155+
"@id": "ex:RetosAddress"
6156+
}
6157+
},
6158+
{
6159+
"@id": "ex:RetosAddress",
6160+
"ex:postalCode": {
6161+
"@type": "xsd:integer",
6162+
"@value": "5678"
6163+
}
6164+
}
6165+
]
6166+
}</pre>
6167+
</div>
6168+
</div>
6169+
<div class="results-graph">
6170+
<div class="turtle">
6171+
[ a sh:ValidationReport ;
6172+
sh:conforms false ;
6173+
sh:result [
6174+
a sh:ValidationResult ;
6175+
sh:resultSeverity sh:Violation ;
6176+
sh:focusNode ex:Reto ;
6177+
sh:resultPath ex:address ;
6178+
sh:value ex:RetosAddress ;
6179+
sh:resultMessage "Value does not conform to shape ex:AddressShape." ;
6180+
sh:sourceConstraint ex:AddressShape ;
6181+
sh:sourceConstraintComponent sh:NodeByExpressionConstraintComponent ;
6182+
sh:sourceShape _:b1 ;
6183+
]
6184+
] .
6185+
</div>
6186+
<div class="jsonld">
6187+
<pre class="jsonld">{
6188+
"@type": "sh:ValidationReport",
6189+
"sh:conforms": {
6190+
"@type": "xsd:boolean",
6191+
"@value": "false"
6192+
},
6193+
"sh:result": {
6194+
"@type": "sh:ValidationResult",
6195+
"sh:focusNode": {
6196+
"@id": "ex:Reto"
6197+
},
6198+
"sh:resultMessage": "Value does not conform to shape ex:AddressShape.",
6199+
"sh:resultPath": {
6200+
"@id": "ex:address"
6201+
},
6202+
"sh:resultSeverity": {
6203+
"@id": "sh:Violation"
6204+
},
6205+
"sh:sourceConstraint": {
6206+
"@id": "ex:AddressShape"
6207+
},
6208+
"sh:sourceConstraintComponent": {
6209+
"@id": "sh:NodeByExpressionConstraintComponent"
6210+
},
6211+
"sh:sourceShape": {
6212+
"@id": "_:b66_b1"
6213+
},
6214+
"sh:value": {
6215+
"@id": "ex:RetosAddress"
6216+
}
6217+
}
6218+
}</pre>
6219+
</div>
6220+
</div>
6221+
</aside>
6222+
</section>
60086223
</section>
60096224

60106225
<section id="core-components-others">
@@ -6869,6 +7084,7 @@ <h2>Changes between SHACL 1.0 Core and SHACL 1.2 Core</h2>
68697084
<li>Added the new class <a href="#ShapeClass"><code>sh:ShapeClass</code></a> for implicit class targets, see <a href="https://github.com/w3c/data-shapes/issues/212">Issue 212</a></li>
68707085
<li>Moved SPARQL-based validators from Core to an Appendix of SHACL-SPARQL, see <a href="https://github.com/w3c/data-shapes/issues/271">Issue 271</a></li>
68717086
<li>Added the new constraint component <a href="#ExpressionConstraintComponent"><code>sh:expression</code></a>, see <a href="https://github.com/w3c/data-shapes/issues/357">Issue 357</a></li>
7087+
<li>Added the new constraint component <a href="#NodeByExpressionConstraintComponent"><code>sh:nodeByExpression</code></a>, see <a href="https://github.com/w3c/data-shapes/issues/408">Issue 408</a></li>
68727088
<li>Values for <a href="#deactivated"><code>sh:deactivated</code></a>, <a href="#message"><code>sh:message</code></a> and <a href="#severity"><code>sh:severity</code></a> can now be specified using RDF 1.2 reification, see <a href="https://github.com/w3c/data-shapes/issues/173">Issue 173</a></li>
68737089
</ul>
68747090
</section>

0 commit comments

Comments
 (0)