Skip to content

#301: sh:values and sh:defaultValue #310

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Mar 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 56 additions & 61 deletions shacl12-core/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ <h2>Shapes and Constraints</h2>
<div class="diagram-class-properties-section">
<div><a href="#name">sh:name</a> : xsd:string or rdf:langString</div>
<div><a href="#description">sh:description</a> : xsd:string or rdf:langString</div>
<div><a href="#defaultValue">sh:defaultValue</a> : any</div>
<div><a href="#syntax-rule-path-defaultValue">sh:defaultValue</a> : any</div>
<div><a href="#group">sh:group</a> : sh:PropertyGroup</div>
</div>
<div class="diagram-class-properties-section">
Expand Down Expand Up @@ -1422,25 +1422,24 @@ <h3>Property Shapes</h3>
<span data-syntax-rule="PropertyShape">A <dfn data-lt="property shapes">property shape</dfn> is a <a>shape</a> in the <a>shapes graph</a>
that is the <a>subject</a> of a <a>triple</a> that has <code>sh:path</code> as its <a>predicate</a>.</span>
<span data-syntax-rule="path-maxCount">A shape has at most one <a>value</a> for <code>sh:path</code>.</span>
<br/><br/>
<span data-syntax-rule="path-node">The <a>value</a> of <code>sh:path</code> in a property shape is either a <a>well-formed</a>
<a>SHACL property path</a> or a <a>well-formed</a> <a>node expression</a>.</span>
<span data-syntax-rule="path-expr-order">The syntax rules for <a>SHACL property paths</a> take precedence over <a>node expressions</a>;
for example, this means that an <a>IRI</a> will be interpreted as a <a>predicate path</a> instead of an <a>IRI expression</a>.</span>
<span data-syntax-rule="path-not-literal">The <a>value</a> of <code>sh:path</code> cannot be a <a>literal</a>.</span>
<span data-syntax-rule="path-node">The <a>value</a> of <code>sh:path</code> in a property shape is a <a>well-formed</a>
<a>SHACL property path</a>.</span>
<br/><br/>
It is recommended, but not required, for a <a>property shape</a> to be declared as a <a>SHACL instance</a> of <code>sh:PropertyShape</code>.
<span data-syntax-rule="PropertyShape-path-minCount"><a>SHACL instances</a> of <code>sh:PropertyShape</code> have one <a>value</a> for the property <code>sh:path</code>.</span>
<br/><br/>
<span data-syntax-rule="path-values">A <a>property shape</a> has at most one <a>value</a> for the property <code>sh:values</code> and this <a>value</a> is a <a>well-formed</a> <a>node expression</a>.</span>
<span data-syntax-rule="path-defaultValue">A <a>property shape</a> has at most one <a>value</a> for the property <code>sh:defaultValue</code> and this <a>value</a> is a <a>well-formed</a> <a>node expression</a>.</span>
<span data-syntax-rule="path-values-iri">A <a>property shape</a> can only have <a>values</a> for <code>sh:values</code> and/or <code>sh:defaultValue</code> when its <a>value</a> for <code>sh:path</code> is a <a href="#property-path-predicate">Predicate Path</a>.</span>
</p>
<p>
Informally, property shapes specify constraints that need to be met with respect to <a>nodes</a> that can be reached from the
<a>focus node</a> either by directly following a given property (specified as an <a>IRI</a>) or any other <a>SHACL property path</a>,
specified using <code>sh:path</code>.
<a>focus node</a> by either (a) directly following a given property (specified as an <a>IRI</a>), (b) directly following any other <a>SHACL property path</a>
(specified using <code>sh:path</code>), (c) evaluating the node expression (specified using <code>sh:values</code>),
or, (d) if no other values exist, evaluating the node expression (specified using <code>sh:defaultValue</code>).
</p>
<p>
If the <code>sh:path</code> is not a <a>well-formed</a> property path, it must be a <a>node expression</a>
and the constraints will be validated against the <a>output nodes</a> of this node expression.
Note that support for node expressions is not required by SHACL Core,
Note that support for <code>sh:values</code> and <code>sh:defaultValue</code> is not required by SHACL Core,
Copy link
Contributor

@afs afs Mar 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just say:

Suggested change
Note that support for <code>sh:values</code> and <code>sh:defaultValue</code> is not required by SHACL Core,
Note that `sh:values` and `sh:defaultValue` are not used by SHACL Core,

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the pre-edit wording. Presence in SHACL-Core notes the terms should be recognized as in the SHACL vocabulary, but knowing their functionality is explicitly "not required" is a clearer statement to me.

Copy link
Contributor

@afs afs Mar 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recognizing SHACL vocabulary would imply some basic "support"?

I wanted to capture that they can be syntactically correct and not processed in the "SHACL Core profile" (to come...).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose I'm fine with it. Though, the next line would need its grammar aligned.

but is necessary for extensions such as [[shacl12-sparql]].
</p>
<p>
Expand Down Expand Up @@ -1489,8 +1488,9 @@ <h2>SHACL Expressions</h2>
SHACL Core supports such expressions in the following features:
</p>
<ul>
<li>Property paths can be used at <a href="#property-shapes"><code>sh:path</code></a> to derive the value nodes of a property shape.</li>
<li>Node expressions can be used 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>
<li>Node expressions can be used at <a href="#targetNode"><code>sh:targetNode</code></a> to dynamically compute the targets of a shape.</li>
<li>Property paths and node expressions can be used at <a href="#property-shapes"><code>sh:path</code></a> to derive the value nodes of a property shape.</li>
<li>Node expressions can be used as parameter values of most <a href="#core-components">constraint components</a> to represent constraints that may be different depending on each focus node. <span class="todo">TODO: This change needs to be made still.</span></li>
</ul>

Expand Down Expand Up @@ -1653,21 +1653,37 @@ <h3>Node Expressions</h3>
Each of these parameters has an <a>IRI</a>.
One of these parameters can be the <dfn>key parameter</dfn> that uniquely identifies the <a>function name</a>.
</div>
<div class="def" id="node-expression-evaluation">
<div class="def-header">EVALUATION OF NODE EXPRESSIONS</div>
The <dfn>evaluation</dfn> of a node expression is defined as a function <code>eval(expr, activeGraph, scope) -> outputNodes</code>
where
<ul>
<li><code>expr</code> is a <a>node expression</a> that is the <a>subject</a> of <a>triples</a> where the <a>predicates</a> are the <a>node expression parameters</a>,
optional for any but the <a>key parameter</a> unless stated otherwise in the definition of the node expression function.</li>
<li><code>activeGraph</code> is a <a>graph</a>, called the <dfn>active graph</dfn>.</li>
<li><code>scope</code> is a map from <a href="https://www.w3.org/TR/sparql12-query/#defn_QueryVariable">variable names</a> to individual <a>nodes</a>.
The value of the variable <code>focusNode</code> (if it exists) is called the <dfn>input focus node</dfn>.
</li>
</ul>
The result of the evaluation of a node expression is a list of <a>nodes</a> (possibly empty and with duplicates) called the <dfn>output nodes</dfn>.
The evaluation may also result in an <dfn>evaluation failure</dfn>.
</div>
<p>
The following example illustrates the syntax of a node expression, used as a blank node value of <code>sh:path</code>:
The following example illustrates the syntax of a node expression, used as a blank node value of <code>sh:values</code>:
</p>
<aside class="example" title="A dynamically computed property using a node expression based on a SPARQL query">
<p>
Here is an example use of a node expression based on <a data-cite="shacl12-sparql#SelectExpression">SHACL-SPARQL</a>, computing
the values of a property shape for the property "full name" as the concatenation of <code>ex:firstName</code>,
a space and the <code>ex:lastName</code>.
the values of a property shape for the property "full name" as the concatenation of the <code>ex:firstName</code>,
a space, and the <code>ex:lastName</code>.
</p>
<div class="shapes-graph">
<div class="turtle">
ex:Person-fullName
a sh:PropertyShape ;
sh:name "full name" ;
sh:path <b>[
sh:path ex:fullName ;
sh:values <b>[
sh:select """
PREFIX ex: &lt;http://example.org/ns#&gt;
SELECT ?fullName
Expand All @@ -1686,23 +1702,8 @@ <h3>Node Expressions</h3>
and the <a>function name</a> is (as defined by SHACL-SPARQL) is <code>sh:SelectExpression</code>.
</p>
</aside>
<div class="def" id="node-expression-evaluation">
<div class="def-header">EVALUATION OF NODE EXPRESSIONS</div>
The <dfn>evaluation</dfn> of a node expression is defined as a function <code>eval(expr, activeGraph, scope) -> outputNodes</code>
where
<ul>
<li><code>expr</code> is a <a>node expression</a> that is the <a>subject</a> of <a>triples</a> where the <a>predicates</a> are the <a>node expression parameters</a>,
optional for any but the <a>key parameter</a> unless stated otherwise in the definition of the node expression function.</li>
<li><code>activeGraph</code> is a <a>graph</a>, called the <dfn>active graph</dfn>.</li>
<li><code>scope</code> is a map from <a href="https://www.w3.org/TR/sparql12-query/#defn_QueryVariable">variable names</a> to individual <a>nodes</a>.
The value of the variable <code>focusNode</code> (if it exists) is called the <dfn>input focus node</dfn>.
</li>
</ul>
The result of the evaluation of a node expression is a list of <a>nodes</a> (possibly empty and with duplicates) called the <dfn>output nodes</dfn>.
The evaluation may also result in an <dfn>evaluation failure</dfn>.
</div>
<p>
This SHACL Core specification only defines exactly the <a>node expression functions</a> from the following two sections.
This SHACL Core specification only exactly defines the <a>node expression functions</a> from the following two subsections.
Other specifications such as [[shacl12-sparql]] introduce additional functions.
Therefore <a>node expressions</a> serve as an extension point of SHACL.
<span class="todo">TODO: Add link to shacl12-node-expr once that is stable.</span>
Expand Down Expand Up @@ -2064,10 +2065,13 @@ <h5>Focus node (sh:focusNode)</h5>
<section id="results-path">
<h4>Path (sh:resultPath)</h4>
<p>
Validation results may have a value for the property <code>sh:resultPath</code> pointing at a <a>well-formed</a> <a>SHACL property path</a>
or <a>node expression</a>.
Validation results may have a value for the property <code>sh:resultPath</code> pointing at a <a>well-formed</a> <a>SHACL property path</a>.
For results produced by a <a>property shape</a>, this <a>SHACL property path</a> is equivalent to the <a>value</a> of <code>sh:path</code> of the shape,
unless stated otherwise. <!-- sh:closed is an exception -->
If the <code>sh:path</code> <code>p</code> is a <a>blank node</a>, then the <code>sh:resultPath</code> is a "deep copy"
of <code>p</code> and any <a>triples</a> that can be reached by transitively traversing the <a>blank nodes</a>
that appear in the <a>object</a> position of these triples.
See the <a href="https://www.w3.org/submissions/CBD/">Concise Bounded Description</a>.
</p>
</section>
<section id="results-value">
Expand Down Expand Up @@ -2142,22 +2146,23 @@ <h4>Value Nodes of Node Shapes</h4>
<h4>Value Nodes of Property Shapes</h4>
<p>
For <a>property shapes</a> with a <a>value</a> for <code>sh:path</code> <code>p</code> the
<a>value nodes</a> are defined as follows.
</p>
<p>
If <code>p</code> is a <a>SHACL property path</a>, then its value nodes are the set of <a>nodes</a> in the <a>data graph</a>
that can be reached from the <a>focus node</a> with the <a>path mapping</a> of <code>p</code>.
</p>
<p>
If <code>p</code> is a <a>node expression</a>, then its value nodes are the set of <a>output nodes</a> of
<code>eval(p, <a>data graph</a>, scope)</code> where <code>scope</code> contains the <a>focus node</a> as value of the variable <code>focusNode</code>.
</p>
<p>
Unless stated otherwise, the value of <code>sh:resultPath</code> of each validation result is a "deep copy"
of <code>p</code> and any <a>triples</a> that can be reached by transitively traversing the <a>blank nodes</a>
that appear in the <a>object</a> position of these triples.
See the <a href="https://www.w3.org/submissions/CBD/">Concise Bounded Description</a>.
set of <a>value nodes</a> is produced by the following steps:
</p>
<ol>
<li>
Add all <a>nodes</a> in the <a>data graph</a> that can be reached from the <a>focus node</a> with the <a>path mapping</a> of <code>p</code>.
</li>
<li>
If <code>e</code> is the <a>value</a> of <code>sh:values</code> at the <a>property shape</a>,
then add the <a>output nodes</a> of <code>eval(e, <a>data graph</a>, scope)</code> where <code>scope</code>
contains the <a>focus node</a> as the value of the variable <code>focusNode</code>.
</li>
<li>
If the set is still empty and <code>d</code> is the <a>value</a> of <code>sh:defaultValue</code> at the <a>property shape</a>,
then add the <a>output nodes</a> of <code>eval(d, <a>data graph</a>, scope)</code> where <code>scope</code>
contains the <a>focus node</a> as the value of the variable <code>focusNode</code>.
</li>
</ol>
</section>
</section>
</section>
Expand Down Expand Up @@ -4133,16 +4138,6 @@ <h3>sh:group</h3>
Groups may also have an <code>sh:order</code> property to indicate
the relative ordering of groups within the same form.
</p>
</section>
<section id="defaultValue">
<h3>sh:defaultValue</h3>
<p>
Property shapes may have a single value for <code>sh:defaultValue</code>.
The default value does not have fixed semantics in SHACL,
but MAY be used by user interface tools to pre-populate input widgets.
The value type of the <code>sh:defaultValue</code> SHOULD align with
the specified <code>sh:datatype</code> or <code>sh:class</code> of the same shape.
</p>
<p>
The following example illustrates the use of these various features together.
</p>
Expand Down Expand Up @@ -4315,7 +4310,7 @@ <h2>Revision History</h2>
<section class="appendix informative" id="changes-12">
<h2>Changes between SHACL 1.0 Core and SHACL 1.2 Core</h2>
<ul>
<li>Introduced <a>node expressions</a> as an extension point to dynamically compute lists of nodes. Generalized <code>sh:targetNode</code> and <code>sh:path</code> to support node expressions.</li>
<li>Introduced <a>node expressions</a> as an extension point to dynamically compute lists of nodes. Generalized <code>sh:targetNode</code> and <code>sh:defaultValue</code>, and introduced <code>sh:values</code> to support node expressions.</li>
<li>Added the new constraint component <a href="#SingleLineConstraintComponent"><code>sh:singleLine</code></a>, see <a href="https://github.com/w3c/data-shapes/issues/177">Issue 177</a></li>
<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>
</ul>
Expand Down
5 changes: 3 additions & 2 deletions shacl12-sparql/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1246,14 +1246,15 @@ <h3>Select Expressions</h3>
<aside class="example" title="A dynamically computed property using a node expression based on a SPARQL query">
<p>
Here is an example use of a <a>select expression</a>, computing the values of a property shape for the property
"full name" as the concatenation of <code>ex:firstName</code>, a space and the <code>ex:lastName</code>.
"full name" as the concatenation of the <code>ex:firstName</code>, a space, and the <code>ex:lastName</code>.
</p>
<div class="shapes-graph">
<div class="turtle">
ex:Person-fullName
a sh:PropertyShape ;
sh:name "full name" ;
sh:path <b>[
sh:path ex:fullName ;
sh:values <b>[
sh:prefixes &lt;http://example.org/ns&gt; ;
sh:select """
SELECT ?fullName
Expand Down
15 changes: 3 additions & 12 deletions shacl12-test-suite/tests/sparql/property/property-select-001.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ ex:Person-fullName
a sh:PropertyShape ;
sh:targetClass ex:Person ;
sh:name "full name" ;
sh:path [
sh:path ex:fullName ;
sh:values [
sh:prefixes <http://example.org/ns> ;
sh:select """
SELECT ?fullName
Expand Down Expand Up @@ -62,17 +63,7 @@ ex:JohnWayne
sh:result [
rdf:type sh:ValidationResult ;
sh:focusNode ex:JohnWayne ;
sh:resultPath [
sh:prefixes <http://example.org/ns> ;
sh:select """
SELECT ?fullName
WHERE {
$this ex:firstName ?firstName .
$this ex:lastName ?lastName .
BIND (CONCAT(?firstName, " ", ?lastName) AS ?fullName) .
}
"""
] ;
sh:resultPath ex:fullName ;
sh:resultSeverity sh:Violation ;
sh:sourceConstraintComponent sh:HasValueConstraintComponent ;
sh:sourceShape ex:Person-fullName ;
Expand Down