###### tags: `data` `ontology` `HN`
SHACL
===
excellente présentatino de T. Francart sur le sujet:
https://rbdd.cnrs.fr/local/cache-zotspip/23D7N9G8/Francart%20SHApe%20Constraints%20Language.pdf
shacl définit des contraintes sur les triplet.
Concrètement il définit des _sh:PropertyShape_ (les contraintes) sur des _sh:NodeShape_ (les classes)
## Node shapes
d'abord on définit des "nodeshapes".
Ce sont des shapes qui contiennent les objets controlés.
__Valeurs__:
`rdf:type`: sh:NodeShape forcément!
`sh:targetClass`: ensemble des objets controlés par cette shape
`sh:nodeKind`: sh:IRI signifie que l'on souhaite que les instances des classes de cette shape soit des IRI, pas des noeuds anonymes.
`sh:property`: ce sont les contraintes (_propertyshape_) voir plus bas attaché à la shape.
`sh:ignoredPropertie` : ce sont les propriétés owl qui ne seront pas vérifié en mode "closed shapes". On y met toujours au moins `rdf:type`mais aussi toutes les propriétés d'annotation (`rdfs:label`, `skos:prefLabel`, `skos:note`, etc.)
```sparql
myPrfx:shaclNode1
rdf:type sh:NodeShape ,
sh:targetClass crm:E67_Birth ;
sh:property
crm:E67_Birth-P96_by_mother ,
crm:E67_Birth-P98_brought_into_life ,
crm:E67_Birth-P97_from_father .
```
shortcut: Si seule une classe est controlée on peut garder son IRI et ne pas renseigner de _sh:targetClass_. C'est ce que fait sparna.
L'exemple précéent peut être ré-écrit comme suit:
```sparql
crm:E67_Birth
rdf:type
sh:NodeShape ,
rdfs:Class ;
sh:property
crm:E67_Birth-P96_by_mother ,
crm:E67_Birth-P98_brought_into_life ,
crm:E67_Birth-P97_from_father .
```
## Property shapes
Ensuite on définit les contraintes, ce sont les "propertyshape"
Chaque propertyshape est une nouvelle contrainte.
Dans l'exemple précédent, pour la classe`E67_BIrth` la _sh:property_ `<crm:E67_Birth-P96_by_mother>` est une contrainte que l'on va définir ici.
__Valeurs__:
`rdf:type`: sh:PropertyShape forcément!
`sh:path` : la propriété owl concernée
`sh:class`: classe attendue comme valeur de la propriété owl (si une seule)
`sh:or`: classes attendues comme valeurs de la propriété (si plusieurs)
ex:
```sparql
crm:E67_Birth-P96_by_mother
rdf:type sh:PropertyShape ;
sh:path crm:P96_by_mother .
sh:class crm:E21_Person ;
```
## Conclusion pour domain range
on définit des contraintes pour chaque shape.
Si je reprends mon exemple et que je met tout dans la même shape (je décloisonne) ça donne
```sparql
crm:E67_Birth
rdf:type
sh:NodeShape ,
rdfs:Class ;
sh:property [
sh:path crm:P96_by_mother ;
sh:class crm:E21_Person ;
] .
```
## autre écriture
Il est possible de cible avec d'autres outils que `targetClass`par exemple avec `sh:targeSubjectOf`ou `sh:targObjectOf ` pour récupérer les sujets/objets des triplet associée à une propriété owl.
On peut alors écrire par exemple:
```sparql
ex:p98shape
rdf:type sh:NodeShape;
sh:targeSubjectOf crm:P98_brought_into_life;
sh:property [
sh:class crm:E67_Birth
] .
```
## Pour d'autres contraintes
il est possible de définir d'autres contraintes sur les shapes.
### cardinalité
Par exemple, on veut qu'il y ait 0 ou 1 mère seulement par Birth.
on peut écrire:
```sparql
crm:E67_Birth-P96_by_mother
rdf:type sh:PropertyShape ;
sh:path crm:P96_by_mother .
sh:class crm:E21_Person ;
sh:maxCount 1
```
### type
#### IRI or not
On veut que le type de la mère soit un IRI (pas une chaine de char)
```sparql
crm:E67_Birth-P96_by_mother
rdf:type sh:PropertyShape ;
sh:path crm:P96_by_mother .
sh:class crm:E21_Person ;
sh:maxCount 1
sh:nodeKind sh:IRI
```
#### non IRI: autres types
Par exemple on veut que la mère soit une chaine de char (et pas un IRI) et corresponde à un pattern
```sparql
crm:E67_Birth-P96_by_mother
rdf:type sh:PropertyShape ;
sh:path crm:P96_by_mother .
sh:class crm:E21_Person ;
sh:maxCount 1
sh:nodeKind sh:BlankNodeOrLiteral
sh:datatype xsd:string
sh:pattern "^[mM]adame .+$" ;
```