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 5 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
83 changes: 39 additions & 44 deletions shacl12-core/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1539,25 +1539,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 <a>value</a> for <code>sh:values</code> or <code>sh:defaultValue</code> when its <a>value</a> for <code>sh:path</code> is an <a>IRI</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>.
specified using <code>sh:path</code>, or evaluating the node expression specified using <code>sh:values</code>, or (if no other values exist)
by 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 @@ -1606,8 +1605,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 @@ -1771,20 +1771,21 @@ <h3>Node Expressions</h3>
One of these parameters can be the <dfn>key parameter</dfn> that uniquely identifies the <a>function name</a>.
</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 href="shacl12-sparql">SHACL-SPARQL</a>, computing
the values of a property shape for the property "full name" as the concatenation of <code>ex:firstName</code>,
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 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 Down Expand Up @@ -1819,7 +1820,7 @@ <h3>Node Expressions</h3>
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 defines exactly 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 @@ -2181,10 +2182,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 @@ -2259,22 +2263,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 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 value of the variable <code>focusNode</code>.
</li>
</ol>
</section>
</section>
</section>
Expand Down Expand Up @@ -4378,16 +4383,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 @@ -4560,7 +4555,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>
</ul>
</section>
Expand Down
126 changes: 126 additions & 0 deletions shacl12-sparql/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ <h3>Terminology</h3>
<dfn data-cite="rdf12-concepts#dfn-literal" data-lt="literal|literals">literal</dfn>,
<dfn data-cite="rdf12-concepts#dfn-blank-node" data-lt="blank node|blank nodes">blank node</dfn>,
<dfn data-cite="rdf12-concepts#dfn-node" data-lt="node|nodes">node</dfn> of an RDF graph,
<dfn data-cite="rdf12-concepts#dfn-datatype" data-lt="datatype|datatypes">datatype</dfn>,
<dfn data-cite="rdf12-concepts#dfn-rdf-term" data-lt="term|terms">RDF term</dfn>, and
<dfn data-cite="rdf12-concepts#dfn-subject" data-lt="subject|subjects">subject</dfn>,
<dfn data-cite="rdf12-concepts#dfn-predicate" data-lt="predicate|predicates">predicate</dfn>, and
Expand All @@ -409,6 +410,11 @@ <h3>Terminology</h3>
<dfn data-cite="shacl12-core#dfn-sparql-property-path" data-lt="sparql property path|sparql property paths">SPARQL property path</dfn>,
<dfn data-cite="shacl12-core#dfn-shapes-graph" data-lt="shapes graph">shapes graph</dfn>,
<dfn data-cite="shacl12-core#dfn-validators" data-lt="validator|validators">validator</dfn>,
<dfn data-cite="shacl12-core#dfn-node-expression" data-lt="node expression|node expresssions">node expression</dfn>,
<dfn data-cite="shacl12-core#dfn-node-expression-function" data-lt="node expression function|node expresssion functions">node expression function</dfn>,
<dfn data-cite="shacl12-core#dfn-function-name" data-lt="node expression function name">function name</dfn>,
<dfn data-cite="shacl12-core#dfn-key-parameter" data-lt="key parameter">key parameter</dfn>,
<dfn data-cite="shacl12-core#dfn-output-nodes" data-lt="output nodes">output nodes</dfn>,
<dfn data-cite="shacl12-core#dfn-conform" data-lt="conform|conforms">conform</dfn>,
<dfn data-cite="shacl12-core#dfn-failure" data-lt="failure|failures">failure</dfn>,
<dfn data-cite="shacl12-core#dfn-shacl-instance" data-lt="shacl instance">SHACL instance</dfn>,
Expand Down Expand Up @@ -1205,6 +1211,119 @@ <h3>Validation with SPARQL-based Constraint Components</h3>
</section>
</section>

<section id="sparql-node-expressions">
<h2>SPARQL-based Node Expressions</h2>
<p>
This section introduces <a>node expression functions</a> based on SPARQL.
</p>

<section id="SelectExpression">
<h3>Select Expressions</h3>
<p>
A <a>node expression</a> that has a <a>value</a> for <code>sh:select</code> is called a <dfn>select expression</dfn> with the <a>function name</a>
<code>sh:SelectExpression</code>.
</p>
<p class="syntax">
<span data-syntax-rule="SelectExpression-syntax">A node in an RDF graph is a <a>well-formed</a> <a>select expression</a> if it is a <a>blank node</a>
that is the <a>subject</a> of exactly one <a>triple</a> with <code>sh:select</code> as <a>predicate</a> and a <a>literal</a> as <a>object</a>
with <a>datatype</a> <code>xsd:string</code>.</span>
<span data-syntax-rule="SelectExpression-query-valid">Using the <a href="#sparql-prefixes">prefix handling rules</a>, the value of <code>sh:select</code> is a valid SPARQL 1.2 SELECT query.</span>
<span data-syntax-rule="SelectExpression-query-output-nodes">The SPARQL query derived from the value of <code>sh:select</code> <a data-cite="sparql12-query/#selectproject">projects</a> exactly one variable in the SELECT clause.</span>
</p>
<div class="def" id="LiteralExpression-evaluation">
<div class="def-header">EVALUATION OF SELECT EXPRESSIONS</div>
<p>
The <a>output nodes</a> of a <a>select expression</a> are the list <code>resultNodes</code> consisting of exactly the bindings of the (only)
variable that is projected from the SELECT clause.
If present in the <a>scope</a>, the value of the scope variable <code>focusNode</code> MUST be <a>pre-bound</a> as the value of the SPARQL variable <code>this</code>.
<br/>
<br/>
<code>eval(expr, activeGraph, scope) -> resultNodes</code>
</p>
</div>
<p><em>The remainder of this section is informative.</em></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 <a>select expression</a>, computing 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 ex:fullName ;
sh:values <b>[
sh:prefixes &lt;http://example.org/ns&gt; ;
sh:select """
SELECT ?fullName
WHERE {
$this ex:firstName ?firstName .
$this ex:lastName ?lastName .
BIND (CONCAT(?firstName, " ", ?lastName) AS ?fullName) .
}
"""
]</b> ;
sh:datatype xsd:string .

&lt;http://example.org/ns&gt;
a owl:Ontology ;
sh:declare [
sh:prefix "ex" ;
sh:namespace "http://example.org/ns#"^^xsd:anyURI ;
] .
</div>
</div>
<p>
This example also illustrates the use of <code>sh:prefixes</code> to insert PREFIX declarations into the beginning of the query before parsing.
Note that the query is executed with the current <a>focus node</a> <a>pre-bound</a> to the variable <code>this</code>.
</p>
</aside>
<aside class="example" title="Dynamically computed target nodes using a node expression based on a SPARQL query">
<p>
Here is an example use of a <a>select expression</a>, computing the target nodes of a shape to consist of all instances of
<code>ex:Person</code> where the <code>ex:age</code> is less than <code>18</code>.
</p>
<div class="shapes-graph">
<div class="turtle">
ex:ChildShape
a sh:NodeShape ;
rdfs:label "Child shape" ;
rdfs:comment "This shape applies to all persons under 18 years of age." ;
sh:targetNode <b>[
sh:select """
PREFIX ex: &lt;http://example.org/ns#&gt;
SELECT ?person
WHERE {
?person a/rdfs:subClassOf* ex:Person .
?person ex:age ?age .
FILTER (?age &lt; 18) .
}
"""
]</b> .
</div>
</div>
<p>
From the following data graph, only <code>ex:Benjamin</code> is a target node.
</p>
<div class="data-graph">
<div class="turtle">
<span class="focus-node-selected">ex:Benjamin</span>
a ex:Person ;
ex:age 17 .

ex:Klaus
a ex:Person ;
ex:age 48 .

ex:Bernd
a ex:Person .
</div>
</div>
</aside>
</section>
</section>

<div style="padding-top: 30px">
<h1 id="appendix" style="font-size: 160%; font-weight: bold">Appendix</h1>
</div>
Expand Down Expand Up @@ -1317,6 +1436,13 @@ <h2>Revision History</h2>
<li><b>2024-02-14</b>: New work started by cloning the main SHACL spec and splitting it into SHACL Core and SHACL-SPARQL</li>
</ul>
</section>

<section class="appendix informative" id="changes-12">
<h2>Changes between SHACL 1.0 SPARQL and SHACL 1.2 SPARQL Extensions</h2>
<ul>
<li>Added the <a>node expression function</a> <a href="#SelectExpression"><code>sh:SelectExpression</code></a>, see <a href="https://github.com/w3c/data-shapes/issues/288">Issue 288</a></li>
</ul>
</section>

</body>

Expand Down
1 change: 1 addition & 0 deletions shacl12-test-suite/tests/sparql/manifest.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
mf:include <node/manifest.ttl> ;
mf:include <property/manifest.ttl> ;
mf:include <pre-binding/manifest.ttl> ;
mf:include <targets/manifest.ttl> ;
.
1 change: 1 addition & 0 deletions shacl12-test-suite/tests/sparql/property/manifest.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
<>
a mf:Manifest ;
rdfs:label "Tests converted from http://datashapes.org/sh/tests/tests/sparql/property" ;
mf:include <property-select-001.ttl> ;
mf:include <sparql-001.ttl> ;
.
Loading