diff --git a/index.html b/index.html index fd9fd86..4c662cc 100644 --- a/index.html +++ b/index.html @@ -1365,8 +1365,240 @@
+ RDF and RDFS specify some RDF structures. + This section describes how ShEx can be used to validate instances of those structures. +
+ ++ RDF Collections are a way of creating an ordered list composed of a chain of rdf:first and rdf:rest properties. + In the Issue example below, fail0 example violates the constraint that the schema indicates that the list may not be empty. The failU1P1 example fails because the first element is out of range. + The failP1U1 example fails because the last item is out of range. +
+BASE <http://a.example/schema> +PREFIX : <#> +PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> +PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> + +<#Issue> { :affects @<#List_Product> } + +<#List_Product> CLOSED { + rdf:first @<#Product> ; + rdf:rest [rdf:nil] OR @<#List_Product> +} + +<#Product> { + :number xsd:integer ; + :name LITERAL +} + +<#User> { + :name LITERAL +}+ + +
{
+ "type": "Schema",
+ "shapes": [
+ {
+ "type": "Shape",
+ "id": "http://a.example/schema#Issue",
+ "expression": {
+ "type": "TripleConstraint",
+ "predicate": "http://a.example/schema#affects",
+ "valueExpr": "http://a.example/schema#List_Product"
+ }
+ },
+ {
+ "type": "Shape",
+ "id": "http://a.example/schema#List_Product",
+ "closed": true,
+ "expression": {
+ "type": "EachOf",
+ "expressions": [
+ {
+ "type": "TripleConstraint",
+ "predicate": "http://www.w3.org/1999/02/22-rdf-syntax-ns#first",
+ "valueExpr": "http://a.example/schema#Product"
+ },
+ {
+ "type": "TripleConstraint",
+ "predicate": "http://www.w3.org/1999/02/22-rdf-syntax-ns#rest",
+ "valueExpr": {
+ "type": "ShapeOr",
+ "shapeExprs": [
+ {
+ "type": "NodeConstraint",
+ "values": [
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"
+ ]
+ },
+ "http://a.example/schema#List_Product"
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "type": "Shape",
+ "id": "http://a.example/schema#Product",
+ "expression": {
+ "type": "EachOf",
+ "expressions": [
+ {
+ "type": "TripleConstraint",
+ "predicate": "http://a.example/schema#number",
+ "valueExpr": {
+ "type": "NodeConstraint",
+ "datatype": "http://www.w3.org/2001/XMLSchema#integer"
+ }
+ },
+ {
+ "type": "TripleConstraint",
+ "predicate": "http://a.example/schema#name",
+ "valueExpr": {
+ "type": "NodeConstraint",
+ "nodeKind": "literal"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "type": "Shape",
+ "id": "http://a.example/schema#User",
+ "expression": {
+ "type": "TripleConstraint",
+ "predicate": "http://a.example/schema#name",
+ "valueExpr": {
+ "type": "NodeConstraint",
+ "nodeKind": "literal"
+ }
+ }
+ }
+ ]
+}
+ BASE <http://a.example/data#> +PREFIX : <http://a.example/schema#> + +<#passP1> :affects (<#Product1>) . +<#passP1P2> :affects (<#Product1> <#Product2>) . + +<#fail0> :affects () . +<#failU1P1> :affects (<#User1> <#Product1>) . +<#failP1U1> :affects (<#Product1> <#User1>) . + +<#Product1> :number 1 ; :name "toaster" . +<#Product2> :number 2 ; :name "blender" . + +<#User1> :name "Alice" . +try it+ +
| Node | Shape | Result | Reason |
|---|---|---|---|
| passP1 | Issue | pass | |
| passP1P2 | Issue | pass | |
| fail0 | Issue | fail | schema prohibits empty lists. |
| failU1P1 | Issue | fail | bad first element. |
| failP1U1 | Issue | fail | bad last element. |
+ In the previous example, Products are distinct from Users in that they have a :productNumber. + Products can, however, masquerade as Users, so long as the User shape is not CLOSED. + Specifically, the Product instance (<#Product1>) meets the criteria for a User, i.e. it has a :name. + When validated as a User, the extra :productNumber is irrelevant (so long as the User shape is not CLOSED). +
+BASE <http://a.example/schema> +PREFIX : <#> +PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> +PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> + +<#Issue> { :reporter @<#List_User> } + +<#List_User> CLOSED { + rdf:first @<#User> ; + rdf:rest [rdf:nil] OR @<#List_User> +} + +<#User> /*not CLOSED*/ { + :name LITERAL +} + +<#Product> { + :number xsd:integer ; + :name LITERAL +}+ + + +
BASE <http://a.example/data#> +PREFIX : <http://a.example/schema#> + +<#passU1> :reporter (<#User1>) . +<#passU1U2> :reporter (<#User1> <#User2>) . + +# Nodes that would fail if User were CLOSED +<#failP1U1> :reporter (<#Product1> <#User1>) . +<#failU1P1> :reporter (<#User1> <#Product1>) . + +<#User1> :name "Alice" . +<#User2> :name "Alicia" . + +<#Product1> :number 1 ; :name "toaster" .try it+ +
| Node | Shape | Result | Reason |
|---|---|---|---|
| passU1 | Issue | pass | |
| passU1U2 | Issue | pass | |
| failP1U1 | Issue | pass | first element "looks" like a User. |
| failU1P1 | Issue | pass | last element "looks" like a User. |
+ If URLs in the data are expected to conform to some naming pattern, this can be enforced with regular expressions on the shape, e.g. +
++<#User> /User/ { + :name LITERAL +} ++