├── README.md ├── charter-1.2 ├── README.md ├── shacl-wg-old.html └── shacl-wg.html ├── css ├── README.md ├── bootstrap.css ├── bootstrap.css.map ├── bootstrap.min.css ├── bootstrap.min.css.map └── shacl.css ├── index.html ├── shacl-af └── index.html ├── shacl-compact-syntax ├── SHACLC.g4 ├── index.html ├── scope.md └── tests │ └── valid │ ├── array-in.shaclc │ ├── array-in.ttl │ ├── basic-shape-iri.shaclc │ ├── basic-shape-iri.ttl │ ├── basic-shape-with-target.shaclc │ ├── basic-shape-with-target.ttl │ ├── basic-shape-with-targets.shaclc │ ├── basic-shape-with-targets.ttl │ ├── basic-shape.shaclc │ ├── basic-shape.ttl │ ├── class.shaclc │ ├── class.ttl │ ├── comment.shaclc │ ├── comment.ttl │ ├── complex1.shaclc │ ├── complex1.ttl │ ├── complex2.shaclc │ ├── complex2.ttl │ ├── count-0-1.shaclc │ ├── count-0-1.ttl │ ├── count-0-unlimited.shaclc │ ├── count-0-unlimited.ttl │ ├── count-1-2.shaclc │ ├── count-1-2.ttl │ ├── count-1-unlimited.shaclc │ ├── count-1-unlimited.ttl │ ├── datatype.shaclc │ ├── datatype.ttl │ ├── directives.shaclc │ ├── directives.ttl │ ├── empty.shaclc │ ├── empty.ttl │ ├── nestedShape.shaclc │ ├── nestedShape.ttl │ ├── node-or-2.shaclc │ ├── node-or-2.ttl │ ├── node-or-3-not.shaclc │ ├── node-or-3-not.ttl │ ├── nodeKind.shaclc │ ├── nodeKind.ttl │ ├── path-alternative.shaclc │ ├── path-alternative.ttl │ ├── path-complex.shaclc │ ├── path-complex.ttl │ ├── path-inverse.shaclc │ ├── path-inverse.ttl │ ├── path-oneOrMore.shaclc │ ├── path-oneOrMore.ttl │ ├── path-sequence.shaclc │ ├── path-sequence.ttl │ ├── path-zeroOrMore.shaclc │ ├── path-zeroOrMore.ttl │ ├── path-zeroOrOne.shaclc │ ├── path-zeroOrOne.ttl │ ├── property-empty.shaclc │ ├── property-empty.ttl │ ├── property-not.shaclc │ ├── property-not.ttl │ ├── property-or-2.shaclc │ ├── property-or-2.ttl │ ├── property-or-3.shaclc │ ├── property-or-3.ttl │ ├── shapeRef.shaclc │ └── shapeRef.ttl ├── shacl-core ├── images │ ├── Class-Diagram-Arrows.png │ └── SHACL-Validation-Process.png ├── index.html ├── shacl-shacl.ttl └── shacl.ttl ├── shacl-js └── index.html ├── shacl-jsonld-context ├── discussion.md ├── examples │ ├── jsonld-examples.ld.json │ └── jsonld-examples.ttl └── shacl.context.ld.json ├── shacl-sparql └── index.html ├── shapes └── datacube.shapes.ttl └── w3c.json /README.md: -------------------------------------------------------------------------------- 1 | # SHACL 2 | SHACL Community Group (Closed as of January 2025) 3 | 4 | This Community Group and its GitHub repo are now closed and should no longer be used. 5 | 6 | Ongoing SHACL work towards version 1.2 happens in https://github.com/w3c/data-shapes 7 | 8 | SHACL Document Drafts from the Community Group: 9 | 10 | * [SHACL Core](https://w3c.github.io/shacl/shacl-core) 11 | * [SHACL SPARQL](https://w3c.github.io/shacl/shacl-sparql) 12 | * [SHACL Advanced features](https://w3c.github.io/shacl/shacl-af) 13 | * [SHACL Compact Syntax](https://w3c.github.io/shacl/shacl-compact-syntax) 14 | * [SHACL JS](https://w3c.github.io/shacl/shacl-js) 15 | -------------------------------------------------------------------------------- /charter-1.2/README.md: -------------------------------------------------------------------------------- 1 | # SHACL 1.2 WG Charter 2 | 3 | This folder in the SHACL respository contains the Draft Charter for a new SHACL Working Group. 4 | 5 | The Charter file, `shacl-wg.html`, is rendered online at and will be co-listed within the W3C's Draft Charters repository soon, too. 6 | 7 | Please see the rendered Draft Charter for mor information, including contacts. 8 | -------------------------------------------------------------------------------- /charter-1.2/shacl-wg-old.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SHACL WG Group Charter 6 | 7 | 8 | 9 | 66 | 67 | 68 | 91 |
92 |

93 | [DRAFT] SHACL 1.2 Working Group Charter 94 |

95 |

This proposed charter is available 96 | on GitHub. 97 | 98 | Feel free to raise issues. 99 |

100 |
101 | 102 | 103 | 106 | 109 | 110 | 111 | 114 | 117 | 118 | 119 | 122 | 125 | 126 | 127 | 130 | 134 | 135 | 136 | 139 | 143 | 144 | 145 | 148 | 156 | 157 |
104 | Charter Status 105 | 107 | See the group status page and detailed change history. 108 |
112 | Start date 113 | 115 | Approx September 2024 116 |
120 | End date 121 | 123 | Start + 2 years 124 |
128 | Chairs 129 | 131 | Nicholas Car (KurrawongAI)
132 | Eliana Papoutsoglou (Taxonic) 133 |
137 | Team Contacts 138 | 140 | Xxx xxxxx (0.50 FTE) 142 |
146 | Meeting Schedule 147 | 149 | Teleconferences: The Working Group and its Task Forces generally each hold 150 | weekly teleconferences, but this may vary over time according to agenda and preferences. 151 |
152 | Face-to-face: The Working Group generally meets during the W3C's annual Technical Plenary 153 | week; additional face-to-face meetings may be scheduled by consent of the participants, usually no more than 154 | 2 per year. 155 |
158 |
159 |

160 | Goals 161 |

162 |

163 | This Working Group is formed to: 164 |

165 | 177 |

178 | Scope of Work 179 |

180 |

181 | The scope of work for this WG is the delivery of the Specifications listed below in Deliverables section only. This includes test suite extensions and implementations necessary for specification ratification. 182 |

183 |

Phases

184 |

185 | This Working Group will take a phased approach to producing the individual deliverables as follows: 186 |

187 | 200 |

The reason for this phasing is to ensure that the core SHACL specification updates are in place before extension work takes place.

201 |

Timing

202 |

203 | Timing of Phase 1 is dependent on the work of the RDF-star Working Group (see Dependencies, below). The time that this WG needs for the substantive work of Phase 1 is not expected to be great - single figure months - given work to date (see the Deliverables). 204 |

205 |

Phase 2 timing is unknown but is expected to take more than one year, even if the individual Deliverables are worked on in parallel, given the new material needed for some of them, in particular Inferencing Rules and Profiling

206 |

207 | Out of Scope 208 |

209 | 218 |

219 | Deliverables 220 |

221 |

222 | Specifications 223 |

224 |
225 |
SHACL 1.2 Core
226 |
227 |

228 | This specification will basically be an updated and slightly extended version of the first part the SHACL 1.0 spec. 229 | It should fix some unfinished issues in SHACL 1.0, such as recursion. 230 | A goal is maximum backwards compatibility. 231 |

232 |

233 | For specific suggested issues see SHACL Core GitHub issues. 234 |

235 |

236 | There is an evolving SHACL 1.2 Core draft. 237 |

238 |
239 |
SHACL 1.2 SPARQL Extensions
240 |
241 |

242 | This specification will be an incremental update of the second part the SHACL 1.0 spec. 243 | It would include selected SPARQL-related features from the SHACL Advanced Features Report. 244 |

245 |

246 | For specific suggested issues see SHACL-SPARQL GitHub issues. 247 |

248 |

249 | There is an evolving SHACL 1.2 SPARQL Extensions draft. 250 |

251 |
252 |
SHACL 1.2 User Interfaces
253 |
254 |

255 | This specification will define a richer vocabulary that can be queried by user interface tools to produce renderings of RDF graphs, 256 | in particular for viewing and editing RDF resources on forms. 257 | An example starting point is the DASH vocabulary. 258 |

259 |
260 |
SHACL 1.2 Inferencing Rules
261 |
262 |

263 | This specification will define a SHACL vocabulary to represent inferencing rules that can be used to infer new RDF statements from existing statements. 264 | A starting point may be the Node Expressions and SHACL Rules 265 | from the Advanced Features document. 266 |

267 |
268 |
SHACL 1.2 Profiling
269 |
270 |

271 | This specification will define methods for using SHACL to create formal profiles of (RDF) standards. 272 |

273 |

274 | This work will likely build on the profile definitions of the W3C's Profiles Vocabulary which has been used extensively with SHACL constraints and the proposed SHACL 1.2 Inferencing Rules. 275 |

276 |

277 | For specific suggested issues see Profiling GitHub issues. 278 |

279 |
280 |
SHACL 1.2 Compact Syntax
281 |
282 |

283 | This specification will define an alternative "compact" syntax that is custom-tailored for SHACL shapes. 284 | A starting point is the SHACL Compact Syntax draft. 285 |

286 |

287 | For specific suggested issues see SHACL Compact Syntax GitHub issues. 288 |

289 |

290 | There is an evolving SHACL 1.2 Compact Syntax draft. 291 |

292 |
293 |
294 |

295 | Non-Normative Reports 296 |

297 |

298 | The group may produce other Community Group Reports within the scope of 299 | this charter but that are not Specifications, for instance use cases, 300 | requirements, or white papers. 301 |

302 |

303 | Test Suites and Other Software 304 |

305 |

306 | The previous SHACL WG created the Test Suite as described in the SHACL Test Suite and Implementation Report. 307 |

308 |

309 | This new WG will extend that Test Suite to cover new SHACL work and will work with as many implementers as possible to see new SHACL elements supported by tools. Members of the proposed new WG include contributors to the following implementations: 310 |

311 | 316 |

Possibly too:

317 | 324 |

325 | All previously known implementers will be contacted and invited to extend their implementations. 326 |

327 |

328 | Dependencies or Liaisons 329 |

330 |

331 | The initial work proposed for the WG is dependent on outputs from the RDF-star Working Group for the proposed SHACL 1.2 Core and SHACL 1.2 SPARQL Extensions specifications since they intend to cater for RDF-Star. Liaison persons between this WG and the RDF-star WG have not yet been formalised. 332 |

333 |

334 | No other dependencies are known. 335 |

336 |

337 | Community and Business Group Process 338 |

339 |

340 | The group operates under the Community and Business 342 | Group Process. Terms in this Charter that conflict with those of the 343 | Community and Business Group Process are void. 344 |

345 |

346 | As with other Community Groups, W3C seeks organizational licensing 347 | commitments under the W3C Community 349 | Contributor License Agreement (CLA). When people request to 350 | participate without representing their organization's legal interests, 351 | W3C will in general approve those requests for this group with the 352 | following understanding: W3C will seek and expect an organizational 353 | commitment under the CLA starting with the individual's first request to 354 | make a contribution to a group Deliverable. 355 | The section on Contribution Mechanics describes 356 | how W3C expects to monitor these contribution requests. 357 |

358 | 359 |

360 | The W3C Code of 361 | Ethics and Professional Conduct applies to participation in 362 | this group. 363 |

364 | 365 |

366 | Contribution Mechanics 367 |

368 |

369 | Substantive Contributions to Specifications can only be made by Working 370 | Group Participants who abide by the W3C Process and follow the W3C Code of Ethics and Professional Conduct. 371 |

372 |

373 | Contributions from non-WG members will need to be sponsored by a WG member. 374 |

375 |

376 | WG contributors will use the existing SHACL GitHub Repository for all work. All contributions will need to be reviewed by WG members other than the contributor before being accepted. 377 |

378 |

379 | Specifications created in the Community Group must use the 381 | W3C Software and Document License. All other documents produced by 382 | the group should use that License where possible. 383 |

384 |

385 | All GitHub repositories attached to the Community Group must contain a 386 | copy of the CONTRIBUTING 388 | and LICENSE 390 | files. 391 |

392 |

393 | Transparency 394 |

395 |

396 | The group will conduct all of its technical work in public. If the group 397 | uses GitHub, all technical work will occur in its GitHub repositories 398 | (and not in mailing list discussions). This is to ensure contributions 399 | can be tracked through a software tool. 400 |

401 |

402 | Meetings may be restricted to Community Group participants, but a public 403 | summary or minutes must be posted to the group's public mailing list, or 404 | to a GitHub issue if the group uses GitHub. 405 |

406 |

407 | Decision Process 408 |

409 |

410 | All scope and contributions decisions within this WG will be communicated within the SHACL GitHub Repository. 411 |

412 |

413 | This group will seek to make decisions where there is consensus. Groups 414 | are free to decide how to make decisions (e.g. Participants who have 415 | earned Committer status for a history of useful contributions assess 416 | consensus, or the Chair assesses consensus, or where consensus isn't 417 | clear there is a Call for Consensus [CfC] to allow multi-day online 418 | feedback for a proposed course of action). It is expected that 419 | participants can earn Committer status through a history of valuable 420 | contributions as is common in open source projects. After discussion and 421 | due consideration of different opinions, a decision should be publicly 422 | recorded (where GitHub is used as the resolution of an Issue). 423 |

424 |

425 | If substantial disagreement remains (e.g. the group is divided) and the 426 | group needs to decide an Issue in order to continue to make progress, the 427 | Committers will choose an alternative that had substantial support (with 428 | a vote of Committers if necessary). Individuals who disagree with the 429 | choice are strongly encouraged to take ownership of their objection by 430 | taking ownership of an alternative fork. This is explicitly allowed (and 431 | preferred to blocking progress) with a goal of letting implementation 432 | experience inform which spec is ultimately chosen by the group to move 433 | ahead with. 434 |

435 |

436 | Any decisions reached at any meeting are tentative and should be recorded 437 | in a GitHub Issue for groups that use GitHub and otherwise on the group's 438 | public mail list. Any group participant may object to a decision reached 439 | at an online or in-person meeting within 7 days of publication of the 440 | decision provided that they include clear technical reasons for their 441 | objection. The Chairs will facilitate discussion to try to resolve the 442 | objection according to this decision process. 443 |

444 |

445 | It is the Chairs' responsibility to ensure that the decision process is 446 | fair, respects the consensus of the CG, and does not unreasonably favour 447 | or discriminate against any group participant or their employer. 448 |

449 |

450 | Chair Selection 451 |

452 |

453 | Participants in this group choose their Chair(s) and can replace their 454 | Chair(s) at any time using whatever means they prefer. However, if 5 455 | participants, no two from the same organisation, call for an election, 456 | the group must use the following process to replace any current Chair(s) 457 | with a new Chair, consulting the Community Development Lead on election 458 | operations (e.g., voting infrastructure and using RFC 2777). 460 |

461 |
    462 |
  1. Participants announce their candidacies. Participants have 14 days to 463 | announce their candidacies, but this period ends as soon as all 464 | participants have announced their intentions. If there is only one 465 | candidate, that person becomes the Chair. If there are two or more 466 | candidates, there is a vote. Otherwise, nothing changes. 467 |
  2. 468 |
  3. Participants vote. Participants have 21 days to vote for a single 469 | candidate, but this period ends as soon as all participants have voted. 470 | The individual who receives the most votes, no two from the same 471 | organisation, is elected chair. In case of a tie, RFC2777 is used to 472 | break the tie. An elected Chair may appoint co-Chairs. 473 |
  4. 474 |
475 |

476 | Participants dissatisfied with the outcome of an election may ask the 477 | Community Development Lead to intervene. The Community Development Lead, 478 | after evaluating the election, may take any action including no action. 479 |

480 |

481 | Amendments to this Charter 482 |

483 |

484 | The group can decide to work on a proposed amended charter, editing the 485 | text using the Decision Process described above. 486 | The decision on whether to adopt the amended charter is made by 487 | conducting a 30-day vote on the proposed new charter. The new charter, if 488 | approved, takes effect on either the proposed date in the charter itself, 489 | or 7 days after the result of the election is announced, whichever is 490 | later. A new charter must receive 2/3 of the votes cast in the approval 491 | vote to pass. The group may make simple corrections to the charter such 492 | as deliverable dates by the simpler group decision process rather than 493 | this charter amendment process. The group will use the amendment process 494 | for any substantive changes to the goals, scope, deliverables, decision 495 | process or rules for amending the charter. 496 |

497 |
498 |
499 | 515 | 516 | 517 | -------------------------------------------------------------------------------- /charter-1.2/shacl-wg.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Data Shapes WG Group Charter 7 | 8 | 9 | 10 | 11 | 50 | 51 | 52 | 72 | 73 | 74 |
75 |

PROPOSED Data Shapes Working Group Charter

76 | 77 | 78 |

The mission of the Data Shapes Working Group is to update data shapes standards in line with the versions of core Semantic Web standards that cater for RDF-star and to extend the applications of data shapes with new packaging and use specifications.

79 | 80 | 81 | 84 | 85 | 86 |

87 | This proposed charter is available on GitHub.

88 | Feel free to raise issues. 89 |

90 | 91 |
92 | 93 | 94 | 97 | 100 | 101 | 102 | 105 | 108 | 109 | 110 | 113 | 116 | 117 | 118 | 121 | 125 | 126 | 127 | 130 | 134 | 135 | 136 | 139 | 147 | 148 |
95 | Charter Status 96 | 98 | See the group status page and detailed change history. 99 |
103 | Start date 104 | 106 | Approx September 2024 107 |
111 | End date 112 | 114 | Start + 2 years 115 |
119 | Chairs 120 | 122 | Nicholas Car (KurrawongAI)
123 | Eliana Papoutsoglou (Taxonic) 124 |
128 | Team Contacts 129 | 131 | Carine Bournez (0.1 FTE) 133 |
137 | Meeting Schedule 138 | 140 | Teleconferences: The Working Group and its Task Forces hope to hold 141 | weekly teleconferences, but this may vary over time according to agenda and preferences. 142 |

143 | Face-to-face: The Working Group generally meets during the W3C's annual Technical Plenary 144 | week; additional face-to-face meetings may be scheduled by consent of the participants, usually no more than 145 | 2 per year. 146 |
149 | 150 | 151 |
152 | 153 |
154 |

Motivation and Background

155 |

The primary motivations for forming this working group are to:

156 |
    157 |
  1. provide SHACL handling of for RDF-star and SPARQL-star
  2. 158 |
  3. make minor updates to the SHACL core and extended specifications from 5+ years experience of their use
  4. 159 |
160 |

The secondary motivation is to:

161 |
    162 |
  1. develop new specifications that assist with extended SHACL use
  2. 163 |
164 |

For this secondary motivation, the areas of UI generation, reasoning rule definition and profiling descriptions are expected to be addressed. Others may be too, pending resourcing.

165 |
166 | 167 |
168 |

Scope

169 |

170 | This Working Group is formed to: 171 |

172 |
    173 |
  • update SHACL in line with 1.2 version updates to RDF & SPARQL, the core Semantic Web standards that SHACL is built on
  • 174 |
  • extend the specification of advanced use of SHACL in line with use observed since 2017 & SHACL 1.0
  • 175 |
  • develop new SHACL-based specifications in the areas of: 176 |
      177 |
    • auto-generation of user interfaces to RDF graphs
    • 178 |
    • reasoning rules - their dependencies, ordering and packaging
    • 179 |
    • profiling mechanisms - how to specify constraints on specifications & models
    • 180 |
    • a "compact" syntax
    • 181 |
    182 |
  • 183 |
184 | 185 |
186 |

Out of Scope

187 |

The following features are out of scope, and will not be addressed by this Working group.

188 | 189 |
    190 |
  • specifications not based on SHACL
  • 191 |
192 |
193 | 194 |
195 | 196 |
197 |

198 | Deliverables 199 |

200 | 201 |

202 | Updated document status is available on the group publication status page. 203 |

204 | 205 |

206 | Status indicates the state of the deliverable at the time of the charter approval. Expected completion indicates when the deliverable is projected to become a Recommendation, or otherwise reach a stable state. See Timeline for notes of Phase timing. 207 |

208 | 209 |
210 |

211 | Normative Specifications 212 |

213 |

214 | The Working Group will deliver the following W3C normative specifications: 215 |

216 |
217 |
SHACL 1.2 Core
218 |
219 |

220 | This specification will basically be an updated and slightly extended version of the first part the SHACL 1.0 spec. 221 | It should fix some unfinished issues in SHACL 1.0, such as recursion. 222 | A goal is maximum backwards compatibility. 223 |

224 |

225 | For specific suggested issues see SHACL Core GitHub issues. 226 |

227 |

228 | There is an evolving SHACL 1.2 Core draft. 229 |

230 |

Status: Draft

231 |

Expected Completion: Phase 1

232 |
233 |
SHACL 1.2 SPARQL Extensions
234 |
235 |

236 | This specification will be an incremental update of the second part the SHACL 1.0 spec. 237 | It would include selected SPARQL-related features from the SHACL Advanced Features Report. 238 |

239 |

240 | For specific suggested issues see SHACL-SPARQL GitHub issues. 241 |

242 |

243 | There is an evolving SHACL 1.2 SPARQL Extensions draft. 244 |

245 |

Status: Draft

246 |

Expected Completion: Phase 1

247 |
248 |
SHACL 1.2 User Interfaces
249 |
250 |

251 | This specification will define a richer vocabulary that can be queried by user interface tools to produce renderings of RDF graphs, 252 | in particular for viewing and editing RDF resources on forms. 253 | An example starting point is the DASH vocabulary. 254 |

255 |

Status: Not started

256 |
257 |
SHACL 1.2 Inferencing Rules
258 |

Expected Completion: Phase 2

259 |
260 |

261 | This specification will define a SHACL vocabulary to represent inferencing rules that can be used to infer new RDF statements from existing statements. 262 | A starting point may be the Node Expressions and SHACL Rules 263 | from the Advanced Features document. 264 |

265 |

Status: Not started

266 |

Expected Completion: Phase 2

267 |
268 |
SHACL 1.2 Profiling
269 |
270 |

271 | This specification will define methods for using SHACL to create formal profiles of (RDF) standards. 272 |

273 |

274 | This work will likely build on the profile definitions of the W3C's Profiles Vocabulary which has been used extensively with SHACL constraints and the proposed SHACL 1.2 Inferencing Rules. 275 |

276 |

277 | For specific suggested issues see Profiling GitHub issues. 278 |

279 |

Status: Not started

280 |

Expected Completion: Phase 2

281 |
282 |
SHACL 1.2 Compact Syntax
283 |
284 |

285 | This specification will define an alternative "compact" syntax that is custom-tailored for SHACL shapes. 286 | A starting point is the SHACL Compact Syntax draft. 287 |

288 |

289 | For specific suggested issues see SHACL Compact Syntax GitHub issues. 290 |

291 |

292 | There is an evolving SHACL 1.2 Compact Syntax draft. 293 |

294 |

Status: Draft (from previous WG work)

295 |

Expected Completion: Phase 2

296 |
297 |
298 | 299 |
300 | 301 |
302 |

303 | Non-normative Documents 304 |

305 |

306 | The group may produce other Community Group Reports within the scope of 307 | this charter but that are not Specifications, for instance use cases, 308 | requirements, or white papers. 309 |

310 |
311 | 312 |
313 |

Timeline

314 |

315 | This Working Group will take a phased approach to producing the individual deliverables as follows: 316 |

317 |
    318 |
  • Phase 1 319 |
      320 |
    • SHACL 1.2 Core
    • 321 |
    • SHACL 1.2 SPARQL Extensions
    • 322 |
    323 |
  • 324 |
  • Phase 2 325 |
      326 |
    • all other proposed deliverables
    • 327 |
    328 |
  • 329 |
330 |

331 | Timing of Phase 1 is dependent on the work of the RDF-star Working Group (see Dependencies, below). The time that this WG needs for the substantive work of Phase 1 is not expected to be great - single figure months - given work to date (see the Deliverables). 332 |

333 |

Phase 2 timing is unknown but is expected to take more than one year, even if the individual Deliverables are worked on in parallel, given the new material needed for some of them, in particular Inferencing Rules and Profiling

334 |
335 |
336 | 337 |
338 |

Success Criteria

339 | 340 | 341 |

In order to advance to Proposed Recommendation, each normative specification is expected to have 342 | at least two independent interoperable implementations of every feature defined in the specification, where 343 | interoperability can be verified by passing open test suites.

344 |

Already the current version of SHACL has test suites and implementations (see the current SHACL Test Suite and Implementation Report). We expect to extend this work to cover all the new elements added in the Core and SPARQL Extensions specifications and to create similar Test Suites and Implementation Reports for the other normative specifications. 345 |

346 |

347 | Members of the proposed WG include contributors to the following existing SHACL implementations: 348 |

349 | 354 |

Other implementations that will be approached are:

355 | 362 |

363 | All previously known implementers will be contacted and invited to extend their implementations. 364 |

365 |
366 | 367 |
368 |

Coordination

369 |

For all specifications, this Working Group will seek horizontal review for 370 | accessibility, internationalization, privacy, and security with the relevant Working and 371 | Interest Groups, and with the TAG. 372 | Invitation for review must be issued during each major standards-track document transition, including 373 | FPWD. The 374 | Working Group is encouraged to engage collaboratively with the horizontal review groups throughout development of 375 | each specification. The Working Group is advised to seek a review at least 3 months before first entering 376 | CR and is encouraged 377 | to proactively notify the horizontal review groups when major changes occur in a specification following a review.

378 | 379 |

Additional technical coordination with the following Groups will be made, per the W3C Process Document:

380 | 381 |
382 |

W3C Groups

383 |
    384 |
  • RDF-star Working Group
  • 385 |
386 |
387 | 388 |
389 |

External Organizations

390 |

None yet identified.

391 |
392 |
393 | 394 |
395 |

396 | Participation 397 |

398 |

399 | To be successful, this Working Group is expected to have 6 or more active participants for its duration, including representatives from the key implementors of this specification, and active Editors and Test Leads for each specification. The Chairs, specification Editors, and Test Leads are expected to contribute half of a working day per week towards the Working Group. There is no minimum requirement for other Participants. 400 |

401 |

402 | The group encourages questions, comments and issues on its public mailing lists and document repositories, as described in Communication. 403 |

404 |

405 | The group also welcomes non-Members to contribute technical submissions for consideration upon their agreement to the terms of the W3C Patent Policy. 406 |

407 |

Participants in the group are required (by the W3C Process) to follow the 408 | W3C Code of Conduct.

409 |
410 | 411 |
412 |

413 | Communication 414 |

415 |

416 | Technical discussions for this Working Group are conducted in public: the meeting minutes from teleconference and face-to-face meetings will be archived for public review, and technical discussions and issue tracking will be conducted in a manner that can be both read and written to by the general public. Working Drafts and Editor's Drafts of specifications will be developed in public repositories and may permit direct public contribution requests. 417 | The meetings themselves are not open to public participation, however. 418 |

419 |

420 | Information about the group (including details about deliverables, issues, actions, status, participants, and meetings) will be available from the Data Shapes Working Group home page. 421 |

422 |

423 | Most Data Shapes Working Group teleconferences will focus on discussion of particular specifications, and will be conducted on an as-needed basis. 424 |

425 |

426 | This group primarily conducts its technical work on the public mailing list public-shacl@w3.org (archive) 427 | and via GitHub issues. 428 | The public is invited to review, discuss and contribute to this work. 429 |

430 |

431 | The group may use a Member-confidential mailing list for administrative purposes and, at the discretion of the Chairs and members of the group, for member-only discussions in special cases when a participant requests such a discussion. 432 |

433 |
434 | 435 |
436 |

437 | Decision Policy 438 |

439 |

440 | This group will seek to make decisions through consensus and due process, per the W3C Process Document (section 5.2.1, Consensus). Typically, an editor or other participant makes an initial proposal, which is then refined in discussion with members of the group and other reviewers, and consensus emerges with little formal voting being required.

441 |

442 | However, if a decision is necessary for timely progress and consensus is not achieved after careful consideration of the range of views presented, the Chairs may call for a group vote and record a decision along with any objections. 443 |

444 |

445 | To afford asynchronous decisions and organizational deliberation, any resolution (including publication decisions) taken in a face-to-face meeting or teleconference will be considered provisional. 446 | 447 | A call for consensus (CfC) will be issued for all resolutions (for example, via email, GitHub issue or web-based survey), with a response period from one week to 10 working days, depending on the chair's evaluation of the group consensus on the issue. 448 | 449 | If no objections are raised by the end of the response period, the resolution will be considered to have consensus as a resolution of the Working Group. 450 |

451 |

452 | All decisions made by the group should be considered resolved unless and until new information becomes available or unless reopened at the discretion of the Chairs. 453 |

454 |

455 | This charter is written in accordance with the W3C Process Document (Section 5.2.3, Deciding by Vote) and includes no voting procedures beyond what the Process Document requires. 456 |

457 |
458 | 459 |
460 | 461 |

462 | Patent Policy 463 |

464 |

465 | This Working Group operates under the W3C Patent Policy (Version of 15 September 2020). To promote the widest adoption of Web standards, W3C seeks to issue Web specifications that can be implemented, according to this policy, on a Royalty-Free basis. 466 | 467 | For more information about disclosure obligations for this group, please see the licensing information. 468 |

469 |
470 | 471 |
472 |

Licensing

473 |

This Working Group will use the W3C Software and Document license for all its deliverables.

474 |
475 | 476 |
477 |

478 | About this Charter 479 |

480 |

481 | This charter has been created according to section 3.4 of the Process Document. In the event of a conflict between this document or the provisions of any charter and the W3C Process, the W3C Process shall take precedence. 482 |

483 | 484 |
485 |

486 | Charter History 487 |

488 | 489 |

The following table lists details of all changes from the initial charter, per the W3C Process Document (section 4.3, Advisory Committee Review of a Charter):

490 | 491 | 492 | 493 | 494 | 497 | 500 | 503 | 506 | 507 | 508 | 511 | 514 | 517 | 520 | 521 | 522 | 525 | 528 | 531 | 534 | 535 | 536 | 539 | 542 | 545 | 548 | 549 | 550 |
495 | Charter Period 496 | 498 | Start Date 499 | 501 | End Date 502 | 504 | Changes 505 |
509 | Initial Charter 510 | 512 | [dd monthname yyyy] 513 | 515 | [dd monthname yyyy] 516 | 518 | none 519 |
523 | Charter Extension 524 | 526 | [dd monthname yyyy] 527 | 529 | [dd monthname yyyy] 530 | 532 | none 533 |
537 | Rechartered 538 | 540 | [dd monthname yyyy] 541 | 543 | [dd monthname yyyy] 544 | 546 |

[description of change to charter, with link to new deliverable item in charter] Note: use the class new for all new deliverables, for ease of recognition.

547 |
551 |
552 | 553 |
554 |

Change log

555 | 556 | 557 |

Changes to this document are documented in this section.

558 | 564 |
565 |
566 |
567 | 568 |
569 | 570 | 584 | 585 | 586 | 587 | -------------------------------------------------------------------------------- /css/README.md: -------------------------------------------------------------------------------- 1 | CSS from bootstrap-4.5.3-dist.zip 2 | -------------------------------------------------------------------------------- /css/shacl.css: -------------------------------------------------------------------------------- 1 | body { font-family: "Open Sans", sans-serif ; 2 | font-size: 15px ; 3 | font-weight: 400 ; 4 | line-height: 25px; 5 | color: #404040 ; 6 | } 7 | 8 | a { color : #0000C0 ; } 9 | a:hover { text-decoration: underline ; } 10 | a:visited { color : #000080 ; } 11 | 12 | h1 { font-size: 32px ; font-weight: bold ; } 13 | h2 { font-size: 24px ; font-weight: bold ; } 14 | h3 { font-size: 18px ; font-weight: bold ; } 15 | 16 | code { font-family: "Inconsolata" ; color: black ; background-color: #F0F0F0 ; } 17 | pre { font-family: "Inconsolata" ; } 18 | 19 | pre code { white-space: pre; overflow: auto;} 20 | 21 | blockquote { font-size: 14px ; color: #888 ; font-style: italic ; } 22 | 23 | table tr td,th { 24 | vertical-align: top; 25 | border-right: 1px dotted #A0A0A0; 26 | border-top: 1px dotted #A0A0A0; 27 | padding-left: 2em ; 28 | padding-right: 2em ; 29 | padding: 0.3em; 30 | } 31 | 32 | table { 33 | border: 1px solid #A0A0A0 ; 34 | border-spacing: 0; 35 | } 36 | 37 | table th { 38 | padding-left: 0.5em ; 39 | padding-right: 0.5em ; 40 | background-color: #ededee; 41 | } 42 | 43 | img { 44 | border: 0; 45 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | W3C SHACL Community Group 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 |
 
24 |
25 | 26 |
27 | 28 |
29 |

30 | 31 | W3C 34 | 35 |

36 | 40 | 41 |

Data Shapes Working Group:

42 | 54 |
55 | 56 |

Community:

57 | 76 |
77 | 78 |

SHACL Community Group Documents:

79 | 80 | 87 | 88 |
89 | 90 |
91 | 92 |
93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /shacl-compact-syntax/SHACLC.g4: -------------------------------------------------------------------------------- 1 | grammar SHACLC; 2 | 3 | shaclDoc : directive* (nodeShape|shapeClass)* EOF; 4 | 5 | directive : baseDecl | importsDecl | prefixDecl ; 6 | baseDecl : KW_BASE IRIREF ; 7 | importsDecl : KW_IMPORTS IRIREF ; 8 | prefixDecl : KW_PREFIX PNAME_NS IRIREF ; 9 | 10 | shapeClass : KW_SHAPE_CLASS iri nodeShapeBody ; 11 | nodeShape : KW_SHAPE iri targetClass? nodeShapeBody ; 12 | nodeShapeBody : '{' constraint* '}'; 13 | targetClass : '->' iri+ ; 14 | 15 | constraint : ( nodeOr+ | propertyShape ) '.' ; 16 | nodeOr : nodeNot ( '|' nodeNot) * ; 17 | nodeNot : negation? nodeValue ; 18 | nodeValue : nodeParam '=' iriOrLiteralOrArray ; 19 | 20 | propertyShape : path ( propertyCount | propertyOr )* ; 21 | propertyOr : propertyNot ( '|' propertyNot) * ; 22 | propertyNot : negation? propertyAtom ; 23 | propertyAtom : propertyType | nodeKind | shapeRef | propertyValue | nodeShapeBody ; 24 | propertyCount : '[' propertyMinCount '..' propertyMaxCount ']' ; 25 | propertyMinCount : INTEGER ; 26 | propertyMaxCount : (INTEGER | '*') ; 27 | propertyType : iri ; 28 | nodeKind : 'BlankNode' | 'IRI' | 'Literal' | 'BlankNodeOrIRI' | 'BlankNodeOrLiteral' | 'IRIOrLiteral' ; 29 | shapeRef : ATPNAME_LN | ATPNAME_NS | '@' IRIREF ; 30 | propertyValue : propertyParam '=' iriOrLiteralOrArray ; 31 | negation : '!' ; 32 | 33 | path : pathAlternative ; 34 | pathAlternative : pathSequence ( '|' pathSequence )* ; 35 | pathSequence : pathEltOrInverse ( '/' pathEltOrInverse )* ; 36 | pathElt : pathPrimary pathMod? ; 37 | pathEltOrInverse : pathElt | pathInverse pathElt ; 38 | pathInverse : '^' ; 39 | pathMod : '?' | '*' | '+' ; 40 | pathPrimary : iri | '(' path ')' ; 41 | 42 | iriOrLiteralOrArray : iriOrLiteral | array ; 43 | iriOrLiteral : iri | literal ; 44 | 45 | iri : IRIREF | prefixedName ; 46 | prefixedName : PNAME_LN | PNAME_NS ; 47 | 48 | literal : rdfLiteral | numericLiteral | booleanLiteral ; 49 | booleanLiteral : KW_TRUE | KW_FALSE ; 50 | numericLiteral : INTEGER | DECIMAL | DOUBLE ; 51 | rdfLiteral : string (LANGTAG | '^^' datatype)? ; 52 | datatype : iri ; 53 | string : STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2 | STRING_LITERAL1 | STRING_LITERAL2 ; 54 | 55 | array : '[' iriOrLiteral* ']' ; 56 | 57 | nodeParam : 'targetNode' | 'targetObjectsOf' | 'targetSubjectsOf' | 58 | 'deactivated' | 'severity' | 'message' | 59 | 'class' | 'datatype' | 'nodeKind' | 60 | 'minExclusive' | 'minInclusive' | 'maxExclusive' | 'maxInclusive' | 61 | 'minLength' | 'maxLength' | 'pattern' | 'flags' | 'languageIn' | 62 | 'equals' | 'disjoint' | 63 | 'closed' | 'ignoredProperties' | 'hasValue' | 'in' ; 64 | 65 | propertyParam : 'deactivated' | 'severity' | 'message' | 66 | 'class' | 'datatype' | 'nodeKind' | 67 | 'minExclusive' | 'minInclusive' | 'maxExclusive' | 'maxInclusive' | 68 | 'minLength' | 'maxLength' | 'pattern' | 'flags' | 'languageIn' | 'uniqueLang' | 69 | 'equals' | 'disjoint' | 'lessThan' | 'lessThanOrEquals' | 70 | 'qualifiedValueShape' | 'qualifiedMinCount' | 'qualifiedMaxCount' | 'qualifiedValueShapesDisjoint' | 71 | 'closed' | 'ignoredProperties' | 'hasValue' | 'in' ; 72 | 73 | // Keywords 74 | KW_BASE : 'BASE' ; 75 | KW_IMPORTS : 'IMPORTS' ; 76 | KW_PREFIX : 'PREFIX' ; 77 | 78 | KW_SHAPE_CLASS : 'shapeClass' ; 79 | KW_SHAPE : 'shape' ; 80 | 81 | KW_TRUE : 'true' ; 82 | KW_FALSE : 'false' ; 83 | 84 | // Terminals 85 | PASS : [ \t\r\n]+ -> skip; 86 | COMMENT : '#' ~[\r\n]* -> skip; 87 | 88 | IRIREF : '<' (~[\u0000-\u0020=<>\"{}|^`\\] | UCHAR)* '>' ; 89 | PNAME_NS : PN_PREFIX? ':' ; 90 | PNAME_LN : PNAME_NS PN_LOCAL ; 91 | ATPNAME_NS : '@' PN_PREFIX? ':' ; 92 | ATPNAME_LN : '@' PNAME_NS PN_LOCAL ; 93 | LANGTAG : '@' [a-zA-Z]+ ('-' [a-zA-Z0-9]+)* ; 94 | INTEGER : [+-]? [0-9]+ ; 95 | DECIMAL : [+-]? [0-9]* '.' [0-9]+ ; 96 | DOUBLE : [+-]? ([0-9]+ '.' [0-9]* EXPONENT | '.'? [0-9]+ EXPONENT) ; 97 | fragment EXPONENT : [eE] [+-]? [0-9]+ ; 98 | STRING_LITERAL1 : '\'' (~[\u0027\u005C\u000A\u000D] | ECHAR | UCHAR)* '\'' ; 99 | STRING_LITERAL2 : '"' (~[\u0022\u005C\u000A\u000D] | ECHAR | UCHAR)* '"' ; 100 | STRING_LITERAL_LONG1: '\'\'\'' (('\'' | '\'\'')? (~[\'\\] | ECHAR | UCHAR))* '\'\'\'' ; 101 | STRING_LITERAL_LONG2: '"""' (('"' | '""')? (~[\"\\] | ECHAR | UCHAR))* '"""' ; 102 | fragment UCHAR : '\\u' HEX HEX HEX HEX | '\\U' HEX HEX HEX HEX HEX HEX HEX HEX ; 103 | fragment ECHAR : '\\' [tbnrf\\\"\'] ; 104 | fragment WS : [\u0020\u0009\u000D\u000A] ; 105 | fragment PN_CHARS_BASE: [A-Z] | [a-z] | [\u00C0-\u00D6] | [\u00D8-\u00F6] | [\u00F8-\u02FF] | [\u0370-\u037D] 106 | | [\u037F-\u1FFF] | [\u200C-\u200D] | [\u2070-\u218F] | [\u2C00-\u2FEF] | [\u3001-\uD7FF] 107 | | [\uF900-\uFDCF] | [\uFDF0-\uFFFD] 108 | ; 109 | fragment PN_CHARS_U : PN_CHARS_BASE | '_' ; 110 | fragment PN_CHARS : PN_CHARS_U | '-' | [0-9] | [\u00B7] | [\u0300-\u036F] | [\u203F-\u2040] ; 111 | fragment PN_PREFIX : PN_CHARS_BASE ((PN_CHARS | '.')* PN_CHARS)? ; 112 | fragment PN_LOCAL : (PN_CHARS_U | ':' | [0-9] | PLX) ((PN_CHARS | '.' | ':' | PLX)* (PN_CHARS | ':' | PLX))? ; 113 | fragment PLX : PERCENT | PN_LOCAL_ESC ; 114 | fragment PERCENT : '%' HEX HEX ; 115 | fragment HEX : [0-9] | [A-F] | [a-f] ; 116 | fragment PN_LOCAL_ESC: '\\' ('_' | '~' | '.' | '-' | '!' | '$' | '&' | '\'' | '(' | ')' | '*' | '+' | ',' 117 | | ';' | '=' | '/' | '?' | '#' | '@' | '%') ; 118 | -------------------------------------------------------------------------------- /shacl-compact-syntax/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHACL Compact Syntax 5 | 6 | 7 | 38 | 246 | 247 | 248 | 249 |
250 |

251 | The Shapes Constraint Language (SHACL) [[!shacl]] is a language for validating RDF graphs against a set of conditions. 252 | SHACL consists of SHACL Core and SHACL-SPARQL which covers advanced features that use SPARQL-based constraints. 253 | The syntax of SHACL is RDF. 254 |

255 |

256 | This document defines the Compact Syntax for a subset of SHACL Core. 257 | The Compact Syntax offers an alternative notation to the general RDF-based notations for SHACL, 258 | aimed at human editors and readers. 259 |

260 |
261 | 262 |
263 | This specification was started by the RDF Data Shapes WG but is now continued within the 264 | SHACL Community Group. 265 |
266 | 267 |
268 |

Document Outline

269 |

270 | Some examples in this document use Turtle [[!turtle]]. 271 | The reader is expected to be familiar with SHACL [[!shacl]]. 272 |

273 |
274 | 275 |
276 |

Introduction

277 | 278 |
279 |

Document Conventions

280 |

281 | Within this document, the following namespace prefix bindings are used: 282 |

283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 |
PrefixNamespace
rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#
rdfs:http://www.w3.org/2000/01/rdf-schema#
sh:http://www.w3.org/ns/shacl#
xsd:http://www.w3.org/2001/XMLSchema#
ex:http://example.com/ns#
309 |
310 | 311 |
312 |

An Example of the SHACL Compact Syntax

313 |

314 | The following example illustrates key features of the SHACL Compact Syntax. 315 | It is an extended version of the Person Example from [[!shacl]]. 316 |

317 |
318 | BASE <http://example.com/ns>
319 | 
320 | IMPORTS <http://example.com/person-ontology>
321 | 
322 | PREFIX ex: <http://example.com/ns#>
323 | 
324 | shape ex:PersonShape -> ex:Person {
325 | 	closed=true ignoredProperties=[rdf:type] . 
326 | 
327 | 	ex:ssn       xsd:string [0..1] pattern="^\\d{3}-\\d{2}-\\d{4}$" .
328 | 	ex:worksFor  IRI ex:Company [0..*] .
329 | 	ex:address   BlankNode [0..1] {
330 | 		ex:city xsd:string [1..1] .
331 | 		ex:postalCode xsd:integer|xsd:string [1..1] maxLength=5 .
332 | 	} .
333 | }
334 |

335 | Using the this example is mapped to the following Turtle RDF graph: 336 |

337 |
338 | @base <http://example.com/ns> .
339 | @prefix ex: <http://example.com/ns#> .
340 | @prefix owl: <http://www.w3.org/2002/07/owl#> .
341 | @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
342 | @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
343 | @prefix sh: <http://www.w3.org/ns/shacl#> .
344 | @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
345 | 
346 | <http://example.com/ns>
347 | 	rdf:type owl:Ontology ;
348 | 	owl:imports <http://example.com/person-ontology> .
349 | 
350 | ex:PersonShape
351 | 	a sh:NodeShape ;
352 | 	sh:targetClass ex:Person ;
353 | 	sh:closed true ;
354 | 	sh:ignoredProperties ( rdf:type ) ;
355 | 	sh:property [
356 | 		sh:path ex:ssn ;
357 | 		sh:maxCount 1 ;
358 | 		sh:datatype xsd:string ;
359 | 		sh:pattern "^\\d{3}-\\d{2}-\\d{4}$" ;
360 | 	] ;
361 | 	sh:property [
362 | 		sh:path ex:worksFor ;
363 | 		sh:class ex:Company ;
364 | 		sh:nodeKind sh:IRI ;
365 | 	] ;
366 | 	sh:property [
367 | 		sh:path ex:address ;
368 | 		sh:maxCount 1 ;
369 | 		sh:nodeKind sh:BlankNode ;
370 | 		sh:node [
371 | 			sh:property [
372 | 				sh:path ex:city ;
373 | 				sh:datatype xsd:string ;
374 | 				sh:minCount 1 ;
375 | 				sh:maxCount 1 ;
376 | 			] ;
377 | 			sh:property [
378 | 				sh:path ex:postalCode ;
379 | 				sh:or ( [ sh:datatype xsd:integer ] [ sh:datatype xsd:string ] ) ;
380 | 				sh:minCount 1 ;
381 | 				sh:maxCount 1 ;
382 | 				sh:maxLength 5 ;
383 | 			] ;
384 | 		] ;
385 | 	] .
386 |

387 | SHACL also supports a design pattern where shapes that are also declared to be classes apply to 388 | all instances of the class. The Compact Syntax includes the keyword shapeClass 389 | for this case, as shown in the snippet below: 390 |

391 |
392 | shapeClass ex:Person {
393 | 	...
394 | }
395 |

396 | Compared to the example further above using shape, this would produce the following 397 | RDF triples (with no sh:targetClass triple): 398 |

399 |
400 | ex:Person
401 | 	a sh:NodeShape, rdfs:Class ;
402 | 	...
403 |

404 | The SHACL Compact Syntax can be used both as an exchange format but also as temporary editing input format. 405 | If SHACL Compact Syntax files are saved, the recommended file ending is .shaclc. 406 |

407 |
408 |
409 | 410 |
411 |

Grammar and Production Rules

412 |

413 | The following grammar (in ANTLR format) defines the parsing rules 414 | for the SHACL Compact Syntax. 415 | Valid SHACL Compact Syntax documents must be parseable against this grammar, 416 | must not cause any errors during the application of the production rules 417 | and furthermore produce no ill-formed nodes. 418 |

419 |
420 | grammar SHACLC;
421 | 
422 | shaclDoc            : directive* (nodeShape|shapeClass)* EOF;
423 | 
424 | directive           : baseDecl | importsDecl | prefixDecl ;
425 | baseDecl            : KW_BASE  IRIREF ;
426 | importsDecl         : KW_IMPORTS IRIREF ;
427 | prefixDecl          : KW_PREFIX PNAME_NS IRIREF ;
428 | 
429 | nodeShape           : KW_SHAPE iri targetClass? nodeShapeBody ;
430 | shapeClass          : KW_SHAPE_CLASS iri nodeShapeBody ;
431 | nodeShapeBody       : '{' constraint* '}';
432 | targetClass         : '->' iri+ ;
433 | 
434 | constraint          : ( nodeOr+ | propertyShape ) '.' ;
435 | nodeOr              : nodeNot ( '|' nodeNot) * ;
436 | nodeNot             : negation? nodeValue ;
437 | nodeValue           : nodeParam '=' iriOrLiteralOrArray ;
438 | 
439 | propertyShape       : path ( propertyCount | propertyOr )* ;
440 | propertyOr          : propertyNot ( '|' propertyNot) * ;
441 | propertyNot         : negation? propertyAtom ;
442 | propertyAtom        : propertyType | nodeKind | shapeRef | propertyValue | nodeShapeBody ;
443 | propertyCount       : '[' propertyMinCount '..' propertyMaxCount ']' ;
444 | propertyMinCount    : INTEGER ;
445 | propertyMaxCount    : (INTEGER | '*') ;
446 | propertyType        : iri ;
447 | nodeKind            : 'BlankNode' | 'IRI' | 'Literal' | 'BlankNodeOrIRI' | 'BlankNodeOrLiteral' | 'IRIOrLiteral' ;
448 | shapeRef            : ATPNAME_LN | ATPNAME_NS | '@' IRIREF ;
449 | propertyValue       : propertyParam '=' iriOrLiteralOrArray ;
450 | negation            : '!' ;
451 | 
452 | path                : pathAlternative ;
453 | pathAlternative     : pathSequence ( '|' pathSequence )* ;
454 | pathSequence        : pathEltOrInverse ( '/' pathEltOrInverse )* ;
455 | pathElt             : pathPrimary pathMod? ;
456 | pathEltOrInverse    : pathElt | pathInverse pathElt ;
457 | pathInverse         : '^' ;
458 | pathMod             : '?' | '*' | '+' ;
459 | pathPrimary         : iri | '(' path ')' ;
460 | 
461 | iriOrLiteralOrArray : iriOrLiteral | array ;
462 | iriOrLiteral        : iri | literal ;
463 | 
464 | iri                 : IRIREF | prefixedName ;
465 | prefixedName        : PNAME_LN | PNAME_NS ;
466 | 
467 | literal             : rdfLiteral | numericLiteral | booleanLiteral ;
468 | booleanLiteral      : KW_TRUE | KW_FALSE ;
469 | numericLiteral      : INTEGER | DECIMAL | DOUBLE ;
470 | rdfLiteral          : string (LANGTAG | '^^' datatype)? ;
471 | datatype            : iri ;
472 | string              : STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2 | STRING_LITERAL1 | STRING_LITERAL2 ;
473 | 
474 | array               : '[' iriOrLiteral* ']' ;
475 | 
476 | nodeParam           : 'targetNode' | 'targetObjectsOf' | 'targetSubjectsOf' |
477 |                       'deactivated' | 'severity' | 'message' |
478 |                       'class' | 'datatype' | 'nodeKind' |
479 |                       'minExclusive' | 'minInclusive' | 'maxExclusive' | 'maxInclusive' |
480 |                       'minLength' | 'maxLength' | 'pattern' | 'flags' | 'languageIn' |
481 |                       'equals' | 'disjoint' |
482 |                       'closed' | 'ignoredProperties' | 'hasValue' | 'in' ;
483 | 
484 | propertyParam       : 'deactivated' | 'severity' | 'message' |
485 |                       'class' | 'datatype' | 'nodeKind' |
486 |                       'minExclusive' | 'minInclusive' | 'maxExclusive' | 'maxInclusive' |
487 |                       'minLength' | 'maxLength' | 'pattern' | 'flags' | 'languageIn' | 'uniqueLang' |
488 |                       'equals' | 'disjoint' | 'lessThan' | 'lessThanOrEquals' |
489 |                       'qualifiedValueShape' | 'qualifiedMinCount' | 'qualifiedMaxCount' | 'qualifiedValueShapesDisjoint' |
490 |                       'closed' | 'ignoredProperties' | 'hasValue' | 'in' ;
491 | 
492 | // Keywords
493 | KW_BASE             : 'BASE' ;
494 | KW_IMPORTS          : 'IMPORTS' ;
495 | KW_PREFIX           : 'PREFIX' ;
496 | 
497 | KW_SHAPE_CLASS      : 'shapeClass' ;
498 | KW_SHAPE            : 'shape' ;
499 | 
500 | KW_TRUE             : 'true' ;
501 | KW_FALSE            : 'false' ;
502 | 
503 | // Terminals
504 | PASS                : [ \t\r\n]+ -> skip;
505 | COMMENT             : '#' ~[\r\n]* -> skip;
506 | 
507 | IRIREF              : '<' (~[\u0000-\u0020=<>\"{}|^`\\] | UCHAR)* '>' ;
508 | PNAME_NS            : PN_PREFIX? ':' ;
509 | PNAME_LN            : PNAME_NS PN_LOCAL ;
510 | ATPNAME_NS          : '@' PN_PREFIX? ':' ;
511 | ATPNAME_LN          : '@' PNAME_NS PN_LOCAL ;
512 | LANGTAG             : '@' [a-zA-Z]+ ('-' [a-zA-Z0-9]+)* ;
513 | INTEGER             : [+-]? [0-9]+ ;
514 | DECIMAL             : [+-]? [0-9]* '.' [0-9]+ ;
515 | DOUBLE              : [+-]? ([0-9]+ '.' [0-9]* EXPONENT | '.'? [0-9]+ EXPONENT) ;
516 | fragment EXPONENT   : [eE] [+-]? [0-9]+ ;
517 | STRING_LITERAL1     : '\'' (~[\u0027\u005C\u000A\u000D] | ECHAR | UCHAR)* '\'' ;
518 | STRING_LITERAL2     : '"' (~[\u0022\u005C\u000A\u000D] | ECHAR | UCHAR)* '"' ;
519 | STRING_LITERAL_LONG1: '\'\'\'' (('\'' | '\'\'')? (~[\'\\] | ECHAR | UCHAR))* '\'\'\'' ;
520 | STRING_LITERAL_LONG2: '"""' (('"' | '""')? (~[\"\\] | ECHAR | UCHAR))* '"""' ;
521 | fragment UCHAR      : '\\u' HEX HEX HEX HEX | '\\U' HEX HEX HEX HEX HEX HEX HEX HEX ;
522 | fragment ECHAR      : '\\' [tbnrf\\\"\'] ;
523 | fragment WS         : [\u0020\u0009\u000D\u000A] ;
524 | fragment PN_CHARS_BASE: [A-Z] | [a-z] | [\u00C0-\u00D6] | [\u00D8-\u00F6] | [\u00F8-\u02FF] | [\u0370-\u037D]
525 |                        | [\u037F-\u1FFF] | [\u200C-\u200D] | [\u2070-\u218F] | [\u2C00-\u2FEF] | [\u3001-\uD7FF]
526 |                        | [\uF900-\uFDCF] | [\uFDF0-\uFFFD]
527 | 					   		   ;
528 | fragment PN_CHARS_U : PN_CHARS_BASE | '_' ;
529 | fragment PN_CHARS   : PN_CHARS_U | '-' | [0-9] | [\u00B7] | [\u0300-\u036F] | [\u203F-\u2040] ;
530 | fragment PN_PREFIX  : PN_CHARS_BASE ((PN_CHARS | '.')* PN_CHARS)? ;
531 | fragment PN_LOCAL   : (PN_CHARS_U | ':' | [0-9] | PLX) ((PN_CHARS | '.' | ':' | PLX)* (PN_CHARS | ':' | PLX))? ;
532 | fragment PLX        : PERCENT | PN_LOCAL_ESC ;
533 | fragment PERCENT    : '%' HEX HEX ;
534 | fragment HEX        : [0-9] | [A-F] | [a-f] ;
535 | fragment PN_LOCAL_ESC: '\\' ('_' | '~' | '.' | '-' | '!' | '$' | '&' | '\'' | '(' | ')' | '*' | '+' | ','
536 |                        | ';' | '=' | '/' | '?' | '#' | '@' | '%') ;
537 | 			
538 |

539 | A parser for the SHACL Compact Syntax receives as input a (text) document plus an optional base URI 540 | which is used as initial value for the variable ?baseURI. 541 | The parser uses a prefix mapping which has initial mappings for the following namespaces: 542 |

543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 |
PrefixNamespace
rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#
rdfs:http://www.w3.org/2000/01/rdf-schema#
sh:http://www.w3.org/ns/shacl#
xsd:http://www.w3.org/2001/XMLSchema#
565 |

566 | It then produces a new RDF graph with the triples produced by the following rules. 567 |

568 |

569 | baseDecl: set ?baseURI to the IRI specified by IRIREF. 570 |

571 |

572 | importsDecl: add the IRI specified by IRIREF into a set ?imports. 573 |

574 |

575 | prefixDecl: add to the prefix mapping a mapping from the prefix PNAME_NS (without the ':') to 576 | the namespace specified by IRIREF. 577 |

578 |

579 | Once the whole document has been completed, produce a triple ?baseURI rdf:type owl:Ontology 580 | using the final value of baseURI. 581 | Report an error if baseURI has no value but imports is not empty. 582 | For each iri in imports, produce a triple ?baseURI owl:imports ?iri. 583 |

584 |

585 | nodeShape: Produce a triple ?shape rdf:type sh:NodeShape where ?shape is 586 | derived from the iri using iri. 587 | Use ?shape as context shape for the targetClass 588 | and nodeShapeBody. 589 |

590 |

591 | shapeClass: Produce the triples ?shape rdf:type sh:NodeShape and 592 | ?shape rdf:type rdfs:Class where ?shape is 593 | derived from the iri using iri. 594 | Use ?shape as context shape for the nodeShapeBody. 595 |

596 |

597 | targetClass: For each iri, produce a triple ?shape sh:targetClass ?iri 598 | where ?iri is derived from iri. 599 |

600 |

601 | nodeShapeBody: Handle each constraint using the context shape ?shape. 602 |

603 |

604 | constraint: Handle each nodeOr or 605 | propertyShape using the context shape ?shape. 606 |

607 |

608 | nodeOr: If there is more than one nodeNot, then produce an RDF list ?or where for each nodeNot, 609 | there is a new blank node, and that blank node is used as context shape for the nodeNot. 610 | Then produce a triple ?shape sh:or ?or. 611 | If there is only one nodeNot, handle the nodeNot using the context shape ?shape. 612 |

613 |

614 | nodeNot: If there is a negation, produce a new blank node ?not and produce a triple 615 | ?shape sh:not ?not. Then handle the nodeValue using ?not as context shape. 616 | If there is no negation, handle the nodeValue using the context shape ?shape. 617 |

618 |

619 | nodeValue: Produce a triple ?shape ?predicate ?object where ?predicate 620 | is the IRI produced by concatenating the sh namespace with string value of nodeParam 621 | (for example "minLength" becomes sh:minLength), 622 | and ?object is derived from the iriOrLiteralOrArray. 623 |

624 |

625 | propertyShape: Using a new blank node ?property, produce a triple 626 | ?shape sh:property ?property. 627 | Produce a triple ?property sh:path ?path where ?path is the result of path. 628 | Use ?property as context shape for propertyCount and propertyOr. 629 |

630 |

631 | propertyCount: 632 | If propertyMinCount is not "0", produce a triple ?property sh:minCount ?minCount 633 | using the xsd:integer derived from propertyMinCount as ?minCount. 634 | If propertyMaxCount is not "*", produce a triple ?property sh:maxCount ?maxCount 635 | using the xsd:integer derived from propertyMaxCount as ?maxCount. 636 |

637 |

638 | propertyOr: If there is more than one propertyNot, then produce an RDF list ?or where for each propertyNot, 639 | there is a new blank node, and that blank node is used as context shape for the propertyNot. 640 | Then produce a triple ?property sh:or ?or. 641 | If there is only one propertyNot, handle the propertyNot using the context shape ?property. 642 |

643 |

644 | propertyNot: If there is a negation, produce a new blank node ?not and produce a triple 645 | ?property sh:not ?not. Then handle the propertyAtom using ?not as context shape. 646 | If there is no negation, handle the propertyAtom using the context shape ?property. 647 |

648 |

649 | propertyAtom: Use ?property as context shape for any of the child elements. 650 | For a nested nodeShapeBody, produce a new blank node ?node and use that as the context shape ?shape. 651 | Then produce a triple ?property sh:node ?node. 652 |

653 |

654 | propertyType: Let ?iri be the IRI derived from the propertyType using iri. 655 | If ?iri is one of the RDF datatypes supported by SPARQL 1.1 (such as xsd:string) then produce a triple 656 | ?property sh:datatype ?iri, otherwise ?property sh:class ?iri. 657 |

658 |

659 | nodeKind: Produce a triple ?property sh:nodeKind ?nodeKind where 660 | ?nodeKind is the IRI produced by concatenating the sh namespace 661 | with the text value of nodeKind (e.g., sh:Literal). 662 |

663 |

664 | shapeRef: Produce a triple ?property sh:node ?node where 665 | ?node is the IRI derived from the substring of shapeRef after the '@' character using iri. 666 |

667 |

668 | propertyValue: Produce a triple ?property ?predicate ?object where ?predicate 669 | is the IRI produced by concatenating the sh namespace with the string value of propertyParam, 670 | and ?object is derived from the iriOrLiteralOrArray. 671 |

672 |

673 | path: If there is more than one pathSequence, produce a new RDF list ?list where there is 674 | one list member for the paths derived from each pathSequence. 675 | Then produce a triple ?alt sh:alternativePath ?list where ?alt is a new blank node, and return ?alt. 676 | If there is only one pathSequence, return the path derived from pathSequence. 677 |

678 |

679 | pathSequence: If there is more than one pathEltOrInverse, produce a new blank node RDF list ?list 680 | where there is one list member for the path derived from each pathEltOrInverse. Return ?list. 681 | If there is only one pathEltOrInverse, return the path derived from pathEltOrInverse. 682 |

683 |

684 | pathEltOrInverse: If there is a pathInverse, produce a triple 685 | ?path sh:inversePath ?inverse where ?path is a new blank node and ?inverse 686 | is the path derived from pathElt. Return ?path. 687 | If there is only one pathElt, return the path derived from pathElt. 688 |

689 |

690 | pathElt: Let ?primary be the path derived from pathPrimary. 691 | If pathMod does not exist, return ?primary. 692 | Otherwise, produce and return a new blank node ?path with one of the following triples: 693 | If pathMod equals "?" produce a triple ?path sh:zeroOrOnePath ?primary. 694 | If pathMod equals "+" produce a triple ?path sh:oneOrMorePath ?primary. 695 | If pathMod equals "*" produce a triple ?path sh:zeroOrMorePath ?primary. 696 |

697 |

698 | pathPrimary: If iri exists, return the predicate derived from that IRI. 699 | Otherwise, return the path derived from path. 700 |

701 |

702 | iriOrLiteralOrArray: If there is an array, produce and return an RDF list 703 | where each iriOrLiteral is a member. 704 | Otherwise, return iriOrLiteral for iriOrLiteral. 705 |

706 |

707 | iriOrLiteral: If there is an iri, return the node derived from iri. 708 | Otherwise, apply Turtle's parsing rules to turn the string literal into an RDF literal. 709 |

710 |

711 | iri: If there is a IRIREF, return the result of IRIREF. 712 | Otherwise, return an IRI applying the current prefix mapping on prefixedName. 713 | Report an error if there is no matching prefix. 714 |

715 |

716 | IRIREF: Return the IRI consisting of the substring of IRIREF between the leading < 717 | and the trailing >, turning relative IRIs into absolute IRIs using the current ?baseURI. 718 |

719 |

720 | Developers may find the Test Cases useful. 721 | Each test consists of a .shaclc file and an associated .ttl file. 722 | Parsing the .shaclc file must produce a graph that is isomorphic to the .ttl file. 723 | The test cases are not normative. 724 |

725 |
726 | 727 |
728 |

IANA Considerations

729 | 730 |

This section reviewed, approved, and registered with IANA by the Internet Engineering Steering Group (IESG), 731 | see https://www.iana.org/assignments/media-types/text/shaclc. 732 |

733 | 734 |

text/shaclc

735 |
736 |
Type name:
737 |
text
738 |
Subtype name:
739 |
shaclc
740 |
Required parameters:
741 |
None
742 |
Encoding considerations:
743 |
SHACL Compact Syntax (SHACLC) is a text language encoded in UTF-8.
744 |
Security considerations:
745 |
746 |

747 | Revealing the structure of an RDF graph can reveal information about the content of conformant data. 748 | For instance, a schema with a predicate to describe cancer stage indicates that conforming graphs describe patients with cancer. 749 |

750 |

751 | The process of testing a graph's conformance to a schema could draw significant system resources and be a vector for Denial of Service attacks. 752 |

753 |

754 | RDF Turtle security considerations about IRI spoofing may also apply here. 755 |

756 |
757 |
Interoperability considerations:
758 |
Not Applicable
759 |
Published specification:
760 |
This document
761 |
Applications that use this media type:
762 |
An implementations of SHACLC is part of the TopQuadrant SHACL API 763 |
764 |
Additional information:
765 |
766 |
767 |
Magic number(s):
768 | SHACLC documents will likely have the words PREFIX or BASE (case sensitive) near the beginning of the document. 769 | However, the same words may appear in Turtle and SPARQL documents. 770 |
771 |
File extension(s):
772 |
.shc, .shaclc
773 |
Macintosh file type code(s):
774 |
TEXT
775 |
776 |
777 |
Person & email address to contact for further information:
778 |
Vladimir Alexiev <vladimir.alexiev@ontotext.com>
779 |
Intended usage:
780 |
Common
781 |
Restrictions on usage:
782 |
None
783 |
Author(s):
784 |
Holger Knublauch, TopQuadrant
785 |
Change controller:
786 |
W3C SHACL Community Group 787 |
788 |
789 |
790 | 791 |
792 |

Acknowledgements

793 |

794 | This document is heavily inspired by the ShEx Compact Syntax, 795 | a version of which was provided as input to the RDF Data Shapes Working Group. 796 | The IANA Considerations section has been adapted from the same document. 797 |

798 |

799 | The ShEx Compact Syntax was primarily developed by the following people: 800 |

801 |

802 | Eric Prud'hommeaux, 803 | Iovka Boneva, 804 | Jose Labra, 805 | Harold Solbrig 806 |

807 |
808 | 809 | 810 | 811 | 812 | -------------------------------------------------------------------------------- /shacl-compact-syntax/scope.md: -------------------------------------------------------------------------------- 1 | # SHACL Compact (SHACL-C) Syntax 1.2 Scope Document 2 | 3 | As SHACL needs to be updated to support RDF 1.2, there is an opportunity to promote SHACL-C from a CG to WG specification, whilst: 4 | - Upgrading the SHACL-C spec to support RDF 1.2 features in alignment with upgrades to the other SHACL specs, and 5 | - Adding support for additional SHACL-C features 6 | 7 | This document outlines the scope of new features to be supported. 8 | 9 | ## Aligning with RDF 1.2 10 | 11 | Syntactic additions will be required for SHACL-C to support the following: 12 | 13 | - [RDF datasets](https://github.com/w3c/shacl/issues/22) 14 | - [RDF 1.2 triple terms and occurrences](https://github.com/w3c/shacl/issues/23) 15 | - [RDF 1.2 text direction](https://github.com/w3c/shacl/issues/24) 16 | 17 | Note that this should be done *after* these features have been supported by the core SHACL spec. 18 | 19 | ## New Features 20 | 21 | ### Support for additional SHACL-C shorthands 22 | - Support Rules 23 | - Support (SPARQL) Functions 24 | - Support shorthand (`<`, `=`, `<=`, etc.) for property pair constraints 25 | - [Support `xone` and more `or` cases](https://github.com/w3c/shacl/issues/12) 26 | - Opting out of the production of the triple `?baseUri rdf:type owl:Ontology` 27 | - Support for non-validating characteristics (e.g., generating `sh:order` triples by declaring `@order` at the top of a file/shape, allow grouping by `@group` at the top of a set of properties, and allowing a `@description` above properties). 28 | 29 | The first 2 of these have been supported in [this xtext file](https://gitlab.com/allotrope-open-source/shape-editor/-/blob/master/src/com.osthus.shapes.shaclc.parent/com.osthus.shapes.shaclc/src/com/osthus/shapes/shaclc/SHACLC.xtext) by [allotrope](https://www.allotrope.org/). Some or all of these additions may be ignored in favour of keeping SHACL-C a simple syntax to implement and use. 30 | 31 | ### [Making SHACL-C Lossless](https://github.com/w3c/shacl/issues/36) 32 | 33 | There are attempts to implement lossless SHACL-C by allowing the use of a more Turtle-like syntax in places. We should align on a way of doing this and write it up in spec form. Existing attempts include: 34 | - [Extended Compact Syntax in `shaclcjs`](https://github.com/jeswr/shaclcjs?tab=readme-ov-file#extended-shacl-compact-syntax) 35 | - [make SHACL-C→SHACL nearly lossless TopQuadrant/shacl#98](https://github.com/TopQuadrant/shacl/issues/98) (escape into Turtle, and some extra links and ideas) 36 | 37 | ### Extending the test suite 38 | 39 | There is also work that can be done to make the test suite more robust such as: 40 | - [SHACL-C: missing property shape TopQuadrant/shacl#142](https://github.com/TopQuadrant/shacl/issues/142) (test case) 41 | - [SHACL-C→SHACL outputs `;` instead of `.` TopQuadrant/shacl#91](https://github.com/TopQuadrant/shacl/issues/91) (test case) 42 | - [SHACL conversion: malformed lists TopQuadrant/shacl#92](https://github.com/TopQuadrant/shacl/issues/92) (test case) 43 | 44 | ## Implementations 45 | The current SHACL-C implementations include 46 | - https://jena.apache.org/documentation/shacl/#shacl-compact-syntax 47 | - https://github.com/jeswr/shaclcjs and https://github.com/jeswr/shaclc-writer 48 | - https://gitlab.com/allotrope-open-source/shape-editor 49 | 50 | ## Related Issues 51 | - [SHACL-compact-syntax #7](https://github.com/w3c/shacl/issues/7) 52 | - [SHACL-C grammar: nodeOr vs propertyOr #12](https://github.com/w3c/shacl/issues/12) 53 | - [Extending SHACL-C to enable the expression of any RDF statements #36](https://github.com/w3c/shacl/issues/36) 54 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/array-in.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property in=[ex:Instance1 true "string" 42] . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/array-in.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ex:property ; 17 | sh:in ( ex:Instance1 true "string" 42 ) ; 18 | ] ; 19 | . 20 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/basic-shape-iri.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | shape { 4 | } 5 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/basic-shape-iri.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix owl: . 3 | @prefix rdf: . 4 | @prefix rdfs: . 5 | @prefix sh: . 6 | @prefix xsd: . 7 | 8 | 9 | a owl:Ontology ; 10 | . 11 | 12 | 13 | a sh:NodeShape ; 14 | . 15 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/basic-shape-with-target.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape -> ex:TestClass { 6 | } 7 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/basic-shape-with-target.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:targetClass ex:TestClass ; 16 | . 17 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/basic-shape-with-targets.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape -> ex:TestClass1 ex:TestClass2 { 6 | targetNode=ex:TestNode targetSubjectsOf=ex:subjectProperty targetObjectsOf=ex:objectProperty . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/basic-shape-with-targets.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:targetClass ex:TestClass1, ex:TestClass2 ; 16 | sh:targetNode ex:TestNode ; 17 | sh:targetObjectsOf ex:objectProperty ; 18 | sh:targetSubjectsOf ex:subjectProperty ; 19 | . 20 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/basic-shape.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | } 7 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/basic-shape.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | . 16 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/class.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property ex:TestClass . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/class.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ex:property ; 17 | sh:class ex:TestClass ; 18 | ] ; 19 | . 20 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/comment.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { # Rest is a comment 6 | } 7 | 8 | # Another comment -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/comment.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | . 16 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/complex1.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | IMPORTS 4 | 5 | PREFIX ex: 6 | 7 | shape ex:PersonShape -> ex:Person { 8 | closed=true ignoredProperties=[rdf:type] . 9 | ex:ssn xsd:string [0..1] pattern="^\\d{3}-\\d{2}-\\d{4}$" . 10 | ex:worksFor IRI ex:Company [0..*] . 11 | ex:address BlankNode [0..1] { 12 | ex:city xsd:string [1..1] . 13 | ex:postalCode xsd:integer|xsd:string [1..1] maxLength=5 . 14 | } . 15 | } -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/complex1.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | 10 | rdf:type owl:Ontology ; 11 | owl:imports . 12 | 13 | ex:PersonShape 14 | a sh:NodeShape ; 15 | sh:targetClass ex:Person ; 16 | sh:closed true ; 17 | sh:ignoredProperties ( rdf:type ) ; 18 | sh:property [ 19 | sh:path ex:ssn ; 20 | sh:maxCount 1 ; 21 | sh:datatype xsd:string ; 22 | sh:pattern "^\\d{3}-\\d{2}-\\d{4}$" ; 23 | ] ; 24 | sh:property [ 25 | sh:path ex:worksFor ; 26 | sh:class ex:Company ; 27 | sh:nodeKind sh:IRI ; 28 | ] ; 29 | sh:property [ 30 | sh:path ex:address ; 31 | sh:maxCount 1 ; 32 | sh:nodeKind sh:BlankNode ; 33 | sh:node [ 34 | sh:property [ 35 | sh:path ex:city ; 36 | sh:datatype xsd:string ; 37 | sh:minCount 1 ; 38 | sh:maxCount 1 ; 39 | ] ; 40 | sh:property [ 41 | sh:path ex:postalCode ; 42 | sh:or ( [ sh:datatype xsd:integer ] [ sh:datatype xsd:string ] ) ; 43 | sh:minCount 1 ; 44 | sh:maxCount 1 ; 45 | sh:maxLength 5 ; 46 | ] ; 47 | ] ; 48 | ] . -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/complex2.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | IMPORTS 4 | 5 | PREFIX ex: 6 | 7 | shapeClass ex:Person { 8 | closed=true ignoredProperties=[rdf:type] . 9 | ex:ssn xsd:string [0..1] pattern="^\\d{3}-\\d{2}-\\d{4}$" . 10 | ex:worksFor IRI ex:Company [0..*] . 11 | ex:address BlankNode [0..1] { 12 | ex:city xsd:string [1..1] . 13 | ex:postalCode xsd:integer|xsd:string [1..1] maxLength=5 . 14 | } . 15 | } 16 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/complex2.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | 10 | rdf:type owl:Ontology ; 11 | owl:imports . 12 | 13 | ex:Person 14 | a sh:NodeShape, rdfs:Class ; 15 | sh:closed true ; 16 | sh:ignoredProperties ( rdf:type ) ; 17 | sh:property [ 18 | sh:path ex:ssn ; 19 | sh:maxCount 1 ; 20 | sh:datatype xsd:string ; 21 | sh:pattern "^\\d{3}-\\d{2}-\\d{4}$" ; 22 | ] ; 23 | sh:property [ 24 | sh:path ex:worksFor ; 25 | sh:class ex:Company ; 26 | sh:nodeKind sh:IRI ; 27 | ] ; 28 | sh:property [ 29 | sh:path ex:address ; 30 | sh:maxCount 1 ; 31 | sh:nodeKind sh:BlankNode ; 32 | sh:node [ 33 | sh:property [ 34 | sh:path ex:city ; 35 | sh:datatype xsd:string ; 36 | sh:minCount 1 ; 37 | sh:maxCount 1 ; 38 | ] ; 39 | sh:property [ 40 | sh:path ex:postalCode ; 41 | sh:or ( [ sh:datatype xsd:integer ] [ sh:datatype xsd:string ] ) ; 42 | sh:minCount 1 ; 43 | sh:maxCount 1 ; 44 | sh:maxLength 5 ; 45 | ] ; 46 | ] ; 47 | ] . -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/count-0-1.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property [0..1] . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/count-0-1.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ex:property ; 17 | sh:maxCount 1 ; 18 | ] ; 19 | . 20 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/count-0-unlimited.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property [0..*] . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/count-0-unlimited.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ex:property ; 17 | ] ; 18 | . 19 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/count-1-2.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property [1..2] . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/count-1-2.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ex:property ; 17 | sh:minCount 1 ; 18 | sh:maxCount 2 ; 19 | ] ; 20 | . 21 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/count-1-unlimited.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property [1..*] . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/count-1-unlimited.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ex:property ; 17 | sh:minCount 1 ; 18 | ] ; 19 | . 20 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/datatype.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:stringProperty xsd:string . 7 | ex:langProperty rdf:langString . 8 | } 9 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/datatype.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ex:stringProperty ; 17 | sh:datatype xsd:string ; 18 | ] ; 19 | sh:property [ 20 | sh:path ex:langProperty ; 21 | sh:datatype rdf:langString ; 22 | ] ; 23 | . 24 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/directives.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | IMPORTS 4 | IMPORTS 5 | 6 | PREFIX ex: 7 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/directives.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | 10 | a owl:Ontology ; 11 | owl:imports ; 12 | owl:imports ; 13 | . 14 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/empty.shaclc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/shacl/e28389980cab29f0bb63f83a4037a6cbef52e3ba/shacl-compact-syntax/tests/valid/empty.shaclc -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/empty.ttl: -------------------------------------------------------------------------------- 1 | @prefix owl: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | 7 | 8 | a owl:Ontology ; 9 | . -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/nestedShape.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property IRI { 7 | ex:nestedProperty [1..1] . 8 | } . 9 | } 10 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/nestedShape.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ex:property ; 17 | sh:nodeKind sh:IRI ; 18 | sh:node [ 19 | sh:property [ 20 | sh:path ex:nestedProperty ; 21 | sh:minCount 1 ; 22 | sh:maxCount 1 ; 23 | ] ; 24 | ] ; 25 | ] ; 26 | . 27 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/node-or-2.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | datatype=xsd:string|datatype=rdf:langString . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/node-or-2.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:or ( [ sh:datatype xsd:string ] [ sh:datatype rdf:langString ] ) ; 16 | . 17 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/node-or-3-not.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | datatype=xsd:string|!datatype=rdf:langString | class = ex:TestClass . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/node-or-3-not.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:or ( 16 | [ sh:datatype xsd:string ] 17 | [ sh:not [ sh:datatype rdf:langString ] ] 18 | [ sh:class ex:TestClass ] 19 | ) ; 20 | . 21 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/nodeKind.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:iriProperty IRI . 7 | ex:literalProperty Literal . 8 | } 9 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/nodeKind.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ex:iriProperty ; 17 | sh:nodeKind sh:IRI ; 18 | ] ; 19 | sh:property [ 20 | sh:path ex:literalProperty ; 21 | sh:nodeKind sh:Literal ; 22 | ] ; 23 | . 24 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/path-alternative.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property1|ex:property2 . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/path-alternative.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path [ sh:alternativePath ( ex:property1 ex:property2 ) ] ; 17 | ] ; 18 | . 19 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/path-complex.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | (rdf:type/rdfs:subClassOf*)|ex:property . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/path-complex.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path [ sh:alternativePath ( ( rdf:type [ sh:zeroOrMorePath rdfs:subClassOf ] ) ex:property ) ] ; 17 | ] ; 18 | . 19 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/path-inverse.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ^ex:property . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/path-inverse.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path [ sh:inversePath ex:property ] ; 17 | ] ; 18 | . 19 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/path-oneOrMore.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property+ . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/path-oneOrMore.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path [ sh:oneOrMorePath ex:property ] ; 17 | ] ; 18 | . 19 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/path-sequence.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property1/ex:property2 . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/path-sequence.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ( ex:property1 ex:property2 ) ; 17 | ] ; 18 | . 19 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/path-zeroOrMore.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property* . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/path-zeroOrMore.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path [ sh:zeroOrMorePath ex:property ] ; 17 | ] ; 18 | . 19 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/path-zeroOrOne.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property? . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/path-zeroOrOne.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path [ sh:zeroOrOnePath ex:property ] ; 17 | ] ; 18 | . 19 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/property-empty.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/property-empty.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ex:property ; 17 | ] ; 18 | . 19 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/property-not.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property !ex:Person . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/property-not.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ex:property ; 17 | sh:not [ sh:class ex:Person ] ; 18 | ] ; 19 | . 20 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/property-or-2.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property1 xsd:string|rdf:langString . 7 | ex:property2 xsd:string|ex:TestClass . 8 | } 9 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/property-or-2.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ex:property1 ; 17 | sh:or ( [ sh:datatype xsd:string ] [ sh:datatype rdf:langString ] ) ; 18 | ] ; 19 | sh:property [ 20 | sh:path ex:property2 ; 21 | sh:or ( [ sh:datatype xsd:string ] [ sh:class ex:TestClass ] ) ; 22 | ] ; 23 | . 24 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/property-or-3.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property xsd:string|rdf:langString|@ex:OtherShape . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/property-or-3.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ex:property ; 17 | sh:or ( [ sh:datatype xsd:string ] [ sh:datatype rdf:langString ] [ sh:node ex:OtherShape ] ) ; 18 | ] ; 19 | . 20 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/shapeRef.shaclc: -------------------------------------------------------------------------------- 1 | BASE 2 | 3 | PREFIX ex: 4 | 5 | shape ex:TestShape { 6 | ex:property @ @ex:OtherShape2 . 7 | } 8 | -------------------------------------------------------------------------------- /shacl-compact-syntax/tests/valid/shapeRef.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | @prefix ex: . 3 | @prefix owl: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | 9 | <> 10 | a owl:Ontology ; 11 | . 12 | 13 | ex:TestShape 14 | a sh:NodeShape ; 15 | sh:property [ 16 | sh:path ex:property ; 17 | sh:node ex:OtherShape1, ex:OtherShape2 ; 18 | ] ; 19 | . 20 | -------------------------------------------------------------------------------- /shacl-core/images/Class-Diagram-Arrows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/shacl/e28389980cab29f0bb63f83a4037a6cbef52e3ba/shacl-core/images/Class-Diagram-Arrows.png -------------------------------------------------------------------------------- /shacl-core/images/SHACL-Validation-Process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/shacl/e28389980cab29f0bb63f83a4037a6cbef52e3ba/shacl-core/images/SHACL-Validation-Process.png -------------------------------------------------------------------------------- /shacl-core/shacl-shacl.ttl: -------------------------------------------------------------------------------- 1 | # baseURI: http://www.w3.org/ns/shacl-shacl# 2 | 3 | # A SHACL shapes graph to validate SHACL shapes graphs 4 | # Draft last edited 2017-04-04 5 | 6 | @prefix rdf: . 7 | @prefix rdfs: . 8 | @prefix sh: . 9 | @prefix xsd: . 10 | 11 | @prefix shsh: . 12 | 13 | shsh: 14 | rdfs:label "SHACL for SHACL"@en ; 15 | rdfs:comment "This shapes graph can be used to validate SHACL shapes graphs against a subset of the syntax rules."@en ; 16 | sh:declare [ 17 | sh:prefix "shsh" ; 18 | sh:namespace "http://www.w3.org/ns/shacl-shacl#" ; 19 | ] . 20 | 21 | 22 | shsh:ListShape 23 | a sh:NodeShape ; 24 | rdfs:label "List shape"@en ; 25 | rdfs:comment "A shape describing well-formed RDF lists. Currently does not check for non-recursion. This could be expressed using SHACL-SPARQL."@en ; 26 | rdfs:seeAlso ; 27 | sh:property [ 28 | sh:path [ sh:zeroOrMorePath rdf:rest ] ; 29 | rdfs:comment "Each list member (including this node) must be have the shape shsh:ListNodeShape."@en ; 30 | sh:hasValue rdf:nil ; 31 | sh:node shsh:ListNodeShape ; 32 | ] . 33 | 34 | shsh:ListNodeShape 35 | a sh:NodeShape ; 36 | rdfs:label "List node shape"@en ; 37 | rdfs:comment "Defines constraints on what it means for a node to be a node within a well-formed RDF list. Note that this does not check whether the rdf:rest items are also well-formed lists as this would lead to unsupported recursion."@en ; 38 | sh:or ( [ 39 | sh:hasValue rdf:nil ; 40 | sh:property [ 41 | sh:path rdf:first ; 42 | sh:maxCount 0 ; 43 | ] ; 44 | sh:property [ 45 | sh:path rdf:rest ; 46 | sh:maxCount 0 ; 47 | ] ; 48 | ] 49 | [ 50 | sh:not [ sh:hasValue rdf:nil ] ; 51 | sh:property [ 52 | sh:path rdf:first ; 53 | sh:maxCount 1 ; 54 | sh:minCount 1 ; 55 | ] ; 56 | sh:property [ 57 | sh:path rdf:rest ; 58 | sh:maxCount 1 ; 59 | sh:minCount 1 ; 60 | ] ; 61 | ] ) . 62 | 63 | shsh:ShapeShape 64 | a sh:NodeShape ; 65 | rdfs:label "Shape shape"@en ; 66 | rdfs:comment "A shape that can be used to validate syntax rules for other shapes."@en ; 67 | 68 | # See https://www.w3.org/TR/shacl/#shapes for what counts as a shape 69 | sh:targetClass sh:NodeShape ; 70 | sh:targetClass sh:PropertyShape ; 71 | sh:targetSubjectsOf sh:targetClass, sh:targetNode, sh:targetObjectsOf, sh:targetSubjectsOf ; 72 | sh:targetSubjectsOf sh:and, sh:class, sh:closed, sh:datatype, sh:disjoint, sh:equals, sh:flags, sh:hasValue, 73 | sh:ignoredProperties, sh:in, sh:languageIn, sh:lessThan, sh:lessThanOrEquals, sh:maxCount, sh:maxExclusive, 74 | sh:maxInclusive, sh:maxLength, sh:minCount, sh:minExclusive, sh:minInclusive, sh:minLength, sh:node, sh:nodeKind, 75 | sh:not, sh:or, sh:pattern, sh:property, sh:qualifiedMaxCount, sh:qualifiedMinCount, sh:qualifiedValueShape, 76 | sh:qualifiedValueShape, sh:qualifiedValueShapesDisjoint, sh:qualifiedValueShapesDisjoint, sh:uniqueLang, sh:xone ; 77 | 78 | sh:targetObjectsOf sh:node ; # node-node 79 | sh:targetObjectsOf sh:not ; # not-node 80 | sh:targetObjectsOf sh:property ; # property-node 81 | sh:targetObjectsOf sh:qualifiedValueShape ; # qualifiedValueShape-node 82 | 83 | # Shapes are either node shapes or property shapes 84 | sh:xone ( shsh:NodeShapeShape shsh:PropertyShapeShape ) ; 85 | 86 | sh:property [ 87 | sh:path sh:targetNode ; 88 | sh:nodeKind sh:IRIOrLiteral ; # targetNode-nodeKind 89 | ] ; 90 | sh:property [ 91 | sh:path sh:targetClass ; 92 | sh:nodeKind sh:IRI ; # targetClass-nodeKind 93 | ] ; 94 | sh:property [ 95 | sh:path sh:targetSubjectsOf ; 96 | sh:nodeKind sh:IRI ; # targetSubjectsOf-nodeKind 97 | ] ; 98 | sh:property [ 99 | sh:path sh:targetObjectsOf ; 100 | sh:nodeKind sh:IRI ; # targetObjectsOf-nodeKind 101 | ] ; 102 | sh:or ( [ sh:not [ 103 | sh:class rdfs:Class ; 104 | sh:or ( [ sh:class sh:NodeShape ] [ sh:class sh:PropertyShape ] ) 105 | ] ] 106 | [ sh:nodeKind sh:IRI ] 107 | ) ; # implicit-targetClass-nodeKind 108 | 109 | sh:property [ 110 | sh:path sh:severity ; 111 | sh:maxCount 1 ; # severity-maxCount 112 | sh:nodeKind sh:IRI ; # severity-nodeKind 113 | ] ; 114 | sh:property [ 115 | sh:path sh:message ; 116 | sh:or ( [ sh:datatype xsd:string ] [ sh:datatype rdf:langString ] ) ; # message-datatype 117 | ] ; 118 | sh:property [ 119 | sh:path sh:deactivated ; 120 | sh:maxCount 1 ; # deactivated-maxCount 121 | sh:in ( true false ) ; # deactivated-datatype 122 | ] ; 123 | 124 | sh:property [ 125 | sh:path sh:and ; 126 | sh:node shsh:ListShape ; # and-node 127 | ] ; 128 | sh:property [ 129 | sh:path sh:class ; 130 | sh:nodeKind sh:IRI ; # class-nodeKind 131 | ] ; 132 | sh:property [ 133 | sh:path sh:closed ; 134 | sh:datatype xsd:boolean ; # closed-datatype 135 | sh:maxCount 1 ; # multiple-parameters 136 | ] ; 137 | sh:property [ 138 | sh:path sh:ignoredProperties ; 139 | sh:node shsh:ListShape ; # ignoredProperties-node 140 | sh:maxCount 1 ; # multiple-parameters 141 | ] ; 142 | sh:property [ 143 | sh:path ( sh:ignoredProperties [ sh:zeroOrMorePath rdf:rest ] rdf:first ) ; 144 | sh:nodeKind sh:IRI ; # ignoredProperties-members-nodeKind 145 | ] ; 146 | sh:property [ 147 | sh:path sh:datatype ; 148 | sh:nodeKind sh:IRI ; # datatype-nodeKind 149 | sh:maxCount 1 ; # datatype-maxCount 150 | ] ; 151 | sh:property [ 152 | sh:path sh:disjoint ; 153 | sh:nodeKind sh:IRI ; # disjoint-nodeKind 154 | ] ; 155 | sh:property [ 156 | sh:path sh:equals ; 157 | sh:nodeKind sh:IRI ; # equals-nodeKind 158 | ] ; 159 | sh:property [ 160 | sh:path sh:in ; 161 | sh:maxCount 1 ; # in-maxCount 162 | sh:node shsh:ListShape ; # in-node 163 | ] ; 164 | sh:property [ 165 | sh:path sh:languageIn ; 166 | sh:maxCount 1 ; # languageIn-maxCount 167 | sh:node shsh:ListShape ; # languageIn-node 168 | ] ; 169 | sh:property [ 170 | sh:path ( sh:languageIn [ sh:zeroOrMorePath rdf:rest ] rdf:first ) ; 171 | sh:datatype xsd:string ; # languageIn-members-datatype 172 | ] ; 173 | sh:property [ 174 | sh:path sh:lessThan ; 175 | sh:nodeKind sh:IRI ; # lessThan-nodeKind 176 | ] ; 177 | sh:property [ 178 | sh:path sh:lessThanOrEquals ; 179 | sh:nodeKind sh:IRI ; # lessThanOrEquals-nodeKind 180 | ] ; 181 | sh:property [ 182 | sh:path sh:maxCount ; 183 | sh:datatype xsd:integer ; # maxCount-datatype 184 | sh:maxCount 1 ; # maxCount-maxCount 185 | ] ; 186 | sh:property [ 187 | sh:path sh:maxExclusive ; 188 | sh:maxCount 1 ; # maxExclusive-maxCount 189 | sh:nodeKind sh:Literal ; # maxExclusive-nodeKind 190 | ] ; 191 | sh:property [ 192 | sh:path sh:maxInclusive ; 193 | sh:maxCount 1 ; # maxInclusive-maxCount 194 | sh:nodeKind sh:Literal ; # maxInclusive-nodeKind 195 | ] ; 196 | sh:property [ 197 | sh:path sh:maxLength ; 198 | sh:datatype xsd:integer ; # maxLength-datatype 199 | sh:maxCount 1 ; # maxLength-maxCount 200 | ] ; 201 | sh:property [ 202 | sh:path sh:minCount ; 203 | sh:datatype xsd:integer ; # minCount-datatype 204 | sh:maxCount 1 ; # minCount-maxCount 205 | ] ; 206 | sh:property [ 207 | sh:path sh:minExclusive ; 208 | sh:maxCount 1 ; # minExclusive-maxCount 209 | sh:nodeKind sh:Literal ; # minExclusive-nodeKind 210 | ] ; 211 | sh:property [ 212 | sh:path sh:minInclusive ; 213 | sh:maxCount 1 ; # minInclusive-maxCount 214 | sh:nodeKind sh:Literal ; # minInclusive-nodeKind 215 | ] ; 216 | sh:property [ 217 | sh:path sh:minLength ; 218 | sh:datatype xsd:integer ; # minLength-datatype 219 | sh:maxCount 1 ; # minLength-maxCount 220 | ] ; 221 | sh:property [ 222 | sh:path sh:nodeKind ; 223 | sh:in ( sh:BlankNode sh:IRI sh:Literal sh:BlankNodeOrIRI sh:BlankNodeOrLiteral sh:IRIOrLiteral ) ; # nodeKind-in 224 | sh:maxCount 1 ; # nodeKind-maxCount 225 | ] ; 226 | sh:property [ 227 | sh:path sh:or ; 228 | sh:node shsh:ListShape ; # or-node 229 | ] ; 230 | sh:property [ 231 | sh:path sh:pattern ; 232 | sh:datatype xsd:string ; # pattern-datatype 233 | sh:maxCount 1 ; # multiple-parameters 234 | # Not implemented: syntax rule pattern-regex 235 | ] ; 236 | sh:property [ 237 | sh:path sh:flags ; 238 | sh:datatype xsd:string ; # flags-datatype 239 | sh:maxCount 1 ; # multiple-parameters 240 | ] ; 241 | sh:property [ 242 | sh:path sh:qualifiedMaxCount ; 243 | sh:datatype xsd:integer ; # qualifiedMaxCount-datatype 244 | sh:maxCount 1 ; # multiple-parameters 245 | ] ; 246 | sh:property [ 247 | sh:path sh:qualifiedMinCount ; 248 | sh:datatype xsd:integer ; # qualifiedMinCount-datatype 249 | sh:maxCount 1 ; # multiple-parameters 250 | ] ; 251 | sh:property [ 252 | sh:path sh:qualifiedValueShape ; 253 | sh:maxCount 1 ; # multiple-parameters 254 | ] ; 255 | sh:property [ 256 | sh:path sh:qualifiedValueShapesDisjoint ; 257 | sh:datatype xsd:boolean ; # qualifiedValueShapesDisjoint-datatype 258 | sh:maxCount 1 ; # multiple-parameters 259 | ] ; 260 | sh:property [ 261 | sh:path sh:uniqueLang ; 262 | sh:datatype xsd:boolean ; # uniqueLang-datatype 263 | sh:maxCount 1 ; # uniqueLang-maxCount 264 | ] ; 265 | sh:property [ 266 | sh:path sh:xone ; 267 | sh:node shsh:ListShape ; # xone-node 268 | ] . 269 | 270 | shsh:NodeShapeShape 271 | a sh:NodeShape ; 272 | sh:targetObjectsOf sh:node ; # node-node 273 | sh:property [ 274 | sh:path sh:path ; 275 | sh:maxCount 0 ; # NodeShape-path-maxCount 276 | ] ; 277 | sh:property [ 278 | sh:path sh:lessThan ; 279 | sh:maxCount 0 ; # lessThan-scope 280 | ] ; 281 | sh:property [ 282 | sh:path sh:lessThanOrEquals ; 283 | sh:maxCount 0 ; # lessThanOrEquals-scope 284 | ] ; 285 | sh:property [ 286 | sh:path sh:maxCount ; 287 | sh:maxCount 0 ; # maxCount-scope 288 | ] ; 289 | sh:property [ 290 | sh:path sh:minCount ; 291 | sh:maxCount 0 ; # minCount-scope 292 | ] ; 293 | sh:property [ 294 | sh:path sh:qualifiedValueShape ; 295 | sh:maxCount 0 ; # qualifiedValueShape-scope 296 | ] ; 297 | sh:property [ 298 | sh:path sh:uniqueLang ; 299 | sh:maxCount 0 ; # uniqueLang-scope 300 | ] . 301 | 302 | shsh:PropertyShapeShape 303 | a sh:NodeShape ; 304 | sh:targetObjectsOf sh:property ; # property-node 305 | sh:property [ 306 | sh:path sh:path ; 307 | sh:maxCount 1 ; # path-maxCount 308 | sh:minCount 1 ; # PropertyShape-path-minCount 309 | sh:node shsh:PathShape ; # path-node 310 | ] . 311 | 312 | # Values of sh:and, sh:or and sh:xone must be lists of shapes 313 | shsh:ShapesListShape 314 | a sh:NodeShape ; 315 | sh:targetObjectsOf sh:and ; # and-members-node 316 | sh:targetObjectsOf sh:or ; # or-members-node 317 | sh:targetObjectsOf sh:xone ; # xone-members-node 318 | sh:property [ 319 | sh:path ( [ sh:zeroOrMorePath rdf:rest ] rdf:first ) ; 320 | sh:node shsh:ShapeShape ; 321 | ] . 322 | 323 | 324 | # A path of blank node path syntax, used to simulate recursion 325 | _:PathPath 326 | sh:alternativePath ( 327 | ( [ sh:zeroOrMorePath rdf:rest ] rdf:first ) 328 | ( sh:alternativePath [ sh:zeroOrMorePath rdf:rest ] rdf:first ) 329 | sh:inversePath 330 | sh:zeroOrMorePath 331 | sh:oneOrMorePath 332 | sh:zeroOrOnePath 333 | ) . 334 | 335 | shsh:PathShape 336 | a sh:NodeShape ; 337 | rdfs:label "Path shape"@en ; 338 | rdfs:comment "A shape that can be used to validate the syntax rules of well-formed SHACL paths."@en ; 339 | rdfs:seeAlso ; 340 | sh:property [ 341 | sh:path [ sh:zeroOrMorePath _:PathPath ] ; 342 | sh:node shsh:PathNodeShape ; 343 | ] . 344 | 345 | shsh:PathNodeShape 346 | sh:xone ( # path-metarule 347 | [ sh:nodeKind sh:IRI ] # 2.3.1.1: Predicate path 348 | [ sh:nodeKind sh:BlankNode ; # 2.3.1.2: Sequence path 349 | sh:node shsh:PathListWithAtLeast2Members ; 350 | ] 351 | [ sh:nodeKind sh:BlankNode ; # 2.3.1.3: Alternative path 352 | sh:closed true ; 353 | sh:property [ 354 | sh:path sh:alternativePath ; 355 | sh:node shsh:PathListWithAtLeast2Members ; 356 | sh:minCount 1 ; 357 | sh:maxCount 1 ; 358 | ] 359 | ] 360 | [ sh:nodeKind sh:BlankNode ; # 2.3.1.4: Inverse path 361 | sh:closed true ; 362 | sh:property [ 363 | sh:path sh:inversePath ; 364 | sh:minCount 1 ; 365 | sh:maxCount 1 ; 366 | ] 367 | ] 368 | [ sh:nodeKind sh:BlankNode ; # 2.3.1.5: Zero-or-more path 369 | sh:closed true ; 370 | sh:property [ 371 | sh:path sh:zeroOrMorePath ; 372 | sh:minCount 1 ; 373 | sh:maxCount 1 ; 374 | ] 375 | ] 376 | [ sh:nodeKind sh:BlankNode ; # 2.3.1.6: One-or-more path 377 | sh:closed true ; 378 | sh:property [ 379 | sh:path sh:oneOrMorePath ; 380 | sh:minCount 1 ; 381 | sh:maxCount 1 ; 382 | ] 383 | ] 384 | [ sh:nodeKind sh:BlankNode ; # 2.3.1.7: Zero-or-one path 385 | sh:closed true ; 386 | sh:property [ 387 | sh:path sh:zeroOrOnePath ; 388 | sh:minCount 1 ; 389 | sh:maxCount 1 ; 390 | ] 391 | ] 392 | ) . 393 | 394 | shsh:PathListWithAtLeast2Members 395 | a sh:NodeShape ; 396 | sh:node shsh:ListShape ; 397 | sh:property [ 398 | sh:path [ sh:oneOrMorePath rdf:rest ] ; 399 | sh:minCount 2 ; # 1 other list node plus rdf:nil 400 | ] . 401 | 402 | shsh:ShapesGraphShape 403 | a sh:NodeShape ; 404 | sh:targetObjectsOf sh:shapesGraph ; 405 | sh:nodeKind sh:IRI . # shapesGraph-nodeKind 406 | 407 | shsh:EntailmentShape 408 | a sh:NodeShape ; 409 | sh:targetObjectsOf sh:entailment ; 410 | sh:nodeKind sh:IRI . # entailment-nodeKind 411 | -------------------------------------------------------------------------------- /shacl-jsonld-context/discussion.md: -------------------------------------------------------------------------------- 1 | To discuss: 2 | - `sh:focusNode` has no `rdfs:range` defined in shacl.ttl, but I have treated it as an "object property" in the JSON-LD @context, since I don't think literals can be targets. 3 | - `sh:sourceConstraint` has no `rdfs:range` defined in shacl.ttl, but I have treated it as an "object property" in the JSON-LD @context. 4 | 5 | To consider: 6 | 7 | Do we want to use language maps where appropriate, e.g. for `sh:message` (or `sh:name`). 8 | ``` 9 | { 10 | "@context": { 11 | "@vocab": "http://www.w3.org/ns/shacl#", 12 | "sh" : "http://www.w3.org/ns/shacl#", 13 | "message" : { 14 | "@container" : "@language" 15 | } 16 | } 17 | } 18 | ``` 19 | 20 | This leads to (ttl) 21 | ``` 22 | ... 23 | sh:message "Too many characters"@en ; 24 | sh:message "Zu viele Zeichen"@de 25 | ... 26 | ``` 27 | 28 | being represented as (JSON-LD) 29 | ``` 30 | ... 31 | "message" : { 32 | "en" : "Too many characters", 33 | "de" : "Zu viele Zeichen" 34 | } 35 | ... 36 | ``` 37 | 38 | The only problem is, that when there is no language specified, the key gets split off from the map. 39 | Like so: 40 | ``` 41 | ... 42 | sh:name "postal code" ; 43 | sh:name "zip code"@en-US ; 44 | ... 45 | ``` 46 | 47 | becomes: 48 | ``` 49 | ... 50 | "sh:name" : "postal code", 51 | "name" : { 52 | "en-us" : "zip code" 53 | } 54 | ... 55 | ``` 56 | 57 | 58 | 59 | `sh:path` is can point to a resource or a list for property paths. One could distinguish this in JSON-LD by mapping @list property paths to a designated key in JSON-LD, e.g. pathList. 60 | ``` 61 | { 62 | "@context": { 63 | "@vocab": "http://www.w3.org/ns/shacl#", 64 | "path" : { 65 | "@type" : "@id" 66 | }, 67 | "pathList" : { 68 | "@id" : "path", 69 | "@type" : "@id", 70 | "@container" : "@list" 71 | } 72 | } 73 | } 74 | ``` 75 | 76 | which would lead to (ttl) 77 | ``` 78 | ... 79 | [ 80 | sh:path ex:single 81 | ], 82 | [ 83 | sh:path (ex:knows ex:email) ; 84 | ] 85 | ... 86 | ``` 87 | 88 | being represented as (JSON-LD) 89 | ``` 90 | ... 91 | { 92 | "path" : "ex:single", 93 | }, 94 | { 95 | "pathList" : [ "ex:knows", "ex:email" ] 96 | }, 97 | ... 98 | ``` 99 | 100 | vs. 101 | 102 | ``` 103 | ... 104 | { 105 | "path" : "ex:single" 106 | }, 107 | { 108 | "path" : { 109 | "@list" : [ "ex:knows", "ex:email" ] 110 | } 111 | } 112 | ... 113 | ``` 114 | 115 | However, this might confuse users, since pathList is not defined in SHACL and is not mentioned in the spec. 116 | -------------------------------------------------------------------------------- /shacl-jsonld-context/examples/jsonld-examples.ld.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "@vocab": "http://www.w3.org/ns/shacl#", 4 | "sh" : "http://www.w3.org/ns/shacl#", 5 | "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", 6 | "rdfs" : "http://www.w3.org/2000/01/rdf-schema#", 7 | "xsd": "http://www.w3.org/2001/XMLSchema#", 8 | "comment": "rdfs:comment", 9 | "target" : { 10 | "@type" : "@id" 11 | }, 12 | "targetClass" : { 13 | "@type" : "@id" 14 | }, 15 | "targetObjectsOf" : { 16 | "@type" : "@id" 17 | }, 18 | "targetSubjectsOf" : { 19 | "@type" : "@id" 20 | }, 21 | "severity" : { 22 | "@type" : "@id" 23 | }, 24 | "result" : { 25 | "@type" : "@id" 26 | }, 27 | "detail" : { 28 | "@type" : "@id" 29 | }, 30 | "resultPath" : { 31 | "@type" : "@id" 32 | }, 33 | "resultSeverity" : { 34 | "@type" : "@id" 35 | }, 36 | "sourceShape" : { 37 | "@type" : "@id" 38 | }, 39 | "sourceConstraintComponent" : { 40 | "@type" : "@id" 41 | }, 42 | "prefixes" : { 43 | "@type" : "@id" 44 | }, 45 | "declare" : { 46 | "@type" : "@id" 47 | }, 48 | "namespace" : { 49 | "@type" : "xsd:anyURI" 50 | }, 51 | "shapesGraph" : { 52 | "@type" : "@id" 53 | }, 54 | "path" : { 55 | "@type" : "@id" 56 | }, 57 | "inversePath" : { 58 | "@type" : "@id" 59 | }, 60 | "alternativePath" : { 61 | "@type" : "@id", 62 | "@container" : "@list" 63 | }, 64 | "zeroOrMorePath" : { 65 | "@type" : "@id" 66 | }, 67 | "oneOrMorePath" : { 68 | "@type" : "@id" 69 | }, 70 | "zeroOrOnePath" : { 71 | "@type" : "@id" 72 | }, 73 | "parameter" : { 74 | "@type" : "@id" 75 | }, 76 | "validator" : { 77 | "@type" : "@id" 78 | }, 79 | "nodeValidator" : { 80 | "@type" : "@id" 81 | }, 82 | "propertyValidator" : { 83 | "@type" : "@id" 84 | }, 85 | "and" : { 86 | "@type" : "@id", 87 | "@container" : "@list" 88 | }, 89 | "class" : { 90 | "@type" : "@id" 91 | }, 92 | "ignoredProperties" : { 93 | "@type" : "@id", 94 | "@container" : "@list" 95 | }, 96 | "datatype" : { 97 | "@type" : "@id" 98 | }, 99 | "disjoint" : { 100 | "@type" : "@id" 101 | }, 102 | "equals" : { 103 | "@type" : "@id" 104 | }, 105 | "in" : { 106 | "@container" : "@list" 107 | }, 108 | "languageIn" : { 109 | "@container" : "@list" 110 | }, 111 | "lessThan" : { 112 | "@type" : "@id" 113 | }, 114 | "lessThanOrEquals" : { 115 | "@type" : "@id" 116 | }, 117 | "node" : { 118 | "@type" : "@id" 119 | }, 120 | "nodeKind" : { 121 | "@type" : "@id" 122 | }, 123 | "not" : { 124 | "@type" : "@id" 125 | }, 126 | "or" : { 127 | "@type" : "@id", 128 | "@container" : "@list" 129 | }, 130 | "property" : { 131 | "@type" : "@id" 132 | }, 133 | "qualifiedValueShape" : { 134 | "@type" : "@id" 135 | }, 136 | "xone" : { 137 | "@type" : "@id", 138 | "@container" : "@list" 139 | }, 140 | "sparql" : { 141 | "@type" : "@id" 142 | }, 143 | "derivedValues" : { 144 | "@type" : "@id" 145 | }, 146 | "group" : { 147 | "@type" : "@id" 148 | }, 149 | "returnType" : { 150 | "@type" : "@id" 151 | }, 152 | "resultAnnotation" : { 153 | "@type" : "@id" 154 | }, 155 | "annotationProperty" : { 156 | "@type" : "@id" 157 | }, 158 | "maxCount" : { 159 | "@type" : "xsd:integer" 160 | }, 161 | "maxLength" : { 162 | "@type" : "xsd:integer" 163 | }, 164 | "minCount" : { 165 | "@type" : "xsd:integer" 166 | }, 167 | "minLength" : { 168 | "@type" : "xsd:integer" 169 | }, 170 | "qualifiedMaxCount" : { 171 | "@type" : "xsd:integer" 172 | }, 173 | "qualifiedMinCount" : { 174 | "@type" : "xsd:integer" 175 | } 176 | }, 177 | "@graph" : [ 178 | { 179 | "@id" : "http://example.com/ns#PersonShape", 180 | "@type" : "NodeShape", 181 | "targetClass" : "http://example.com/ns#Person", 182 | "property" : [ 183 | { 184 | "path" : "http://example.com/ns#ssn", 185 | "datatype" : "xsd:string", 186 | "maxCount" : 1, 187 | "pattern" : "^\\d{3}-\\d{2}-\\d{4}$" 188 | }, 189 | { 190 | "path" : "http://example.com/ns#child", 191 | "class" : "http://example.com/ns#Person", 192 | "nodeKind" : "sh:IRI" 193 | }, 194 | { 195 | "comment" : "A person's parents are represented via ex:child used in the inverse direction.", 196 | "path" : { 197 | "inversePath" : "http://example.com/ns#child" 198 | }, 199 | "name" : "parent", 200 | "maxCount" : 2 201 | } 202 | ], 203 | "closed" : true, 204 | "ignoredProperties" : [ "rdf:type" ] 205 | }, 206 | { 207 | "@id" : "http://example.com/ns#InvoiceShape", 208 | "@type" : "NodeShape", 209 | "property" : { 210 | "path" : "http://example.com/ns#customer", 211 | "class" : [ "http://example.com/ns#Customer", "http://example.com/ns#Person" ] 212 | } 213 | }, 214 | { 215 | "@id" : "http://example.com/ns#MultiplePatternsShape", 216 | "@type" : "NodeShape", 217 | "property" : [ 218 | { 219 | "path" : "http://example.com/ns#name", 220 | "pattern" : "^Start", 221 | "flags" : "i" 222 | }, 223 | { 224 | "path" : "http://example.com/ns#name", 225 | "pattern" : "End$" 226 | } 227 | ] 228 | }, 229 | { 230 | "@id" : "http://example.com/ns#TargetSubjectsOfExampleShape", 231 | "@type" : "NodeShape", 232 | "targetSubjectsOf" : "http://example.com/ns#knows" 233 | }, 234 | { 235 | "@id" : "http://example.com/ns#TargetObjectsOfExampleShape", 236 | "@type" : "NodeShape", 237 | "targetObjectsOf" : "http://example.com/ns#knows" 238 | }, 239 | { 240 | "@id" : "http://example.com/ns#MyShape", 241 | "@type" : "NodeShape", 242 | "targetNode" : "http://example.com/ns#MyInstance", 243 | "property" : [ 244 | { 245 | "path" : "http://example.com/ns#myProperty", 246 | "datatype" : "xsd:string", 247 | "minCount" : 1, 248 | "severity" : "sh:Warning" 249 | }, 250 | { 251 | "path" : "http://example.com/ns#myProperty", 252 | "maxLength" : 10, 253 | "message" : [ 254 | { 255 | "@language" : "en", 256 | "@value" : "Too many characters" 257 | }, { 258 | "@language" : "de", 259 | "@value" : "Zu viele Zeichen" 260 | } 261 | ] 262 | } 263 | ] 264 | }, 265 | { 266 | "@id" : "http://example.com/ns#ExampleNodeShapeWithPropertyShapes", 267 | "@type" : "NodeShape", 268 | "property" : [ 269 | { 270 | "path" : "http://example.com/ns#email", 271 | "name" : "e-mail", 272 | "description" : "We need at least one email value", 273 | "minCount" : 1 274 | }, 275 | { 276 | "path" : { 277 | "@list" : [ "http://example.com/ns#knows", "http://example.com/ns#email" ] 278 | }, 279 | "name" : "Friend's e-mail", 280 | "description" : "We need at least one email for everyone you know", 281 | "minCount" : 1 282 | } 283 | ] 284 | }, 285 | { 286 | "@id" : "http://example.com/ns#ExamplePropertyShape", 287 | "@type" : "PropertyShape", 288 | "description" : "We need at least one email value", 289 | "minCount" : 1, 290 | "path" : "http://example.com/ns#email" 291 | }, 292 | { 293 | "@id" : "http://example.com/ns#PersonFormShape", 294 | "@type" : "NodeShape", 295 | "property" : [ 296 | { 297 | "path" : "http://example.com/ns#firstName", 298 | "description" : "The person's given name(s)", 299 | "group" : "http://example.com/ns#NameGroup", 300 | "name" : "first name", 301 | "order" : 0 302 | }, 303 | { 304 | "path" : "http://example.com/ns#lastName", 305 | "description" : "The person's last name", 306 | "group" : "http://example.com/ns#NameGroup", 307 | "name" : "last name", 308 | "order" : 1 309 | }, 310 | { 311 | "path" : "http://example.com/ns#streetAddress", 312 | "description" : "The street address including number", 313 | "group" : "http://example.com/ns#AddressGroup", 314 | "name" : "street address", 315 | "order" : 11 316 | }, 317 | { 318 | "path" : "http://example.com/ns#locality", 319 | "description" : "The suburb, city or town of the address", 320 | "group" : "http://example.com/ns#AddressGroup", 321 | "name" : "locality", 322 | "order" : 12 323 | }, 324 | { 325 | "path" : "http://example.com/ns#postalCode", 326 | "description" : "The postal code of the locality", 327 | "group" : "http://example.com/ns#AddressGroup", 328 | "name" : [ 329 | "postal code", 330 | { 331 | "@language" : "en-us", 332 | "@value" : "zip code" 333 | } 334 | ], 335 | "order" : 13 336 | } ] 337 | }, 338 | { 339 | "@id" : "http://example.com/ns#NameGroup", 340 | "@type" : "PropertyGroup", 341 | "rdfs:label" : "Name", 342 | "order" : 0 343 | }, 344 | { 345 | "@id" : "http://example.com/ns#AddressGroup", 346 | "@type" : "PropertyGroup", 347 | "rdfs:label" : "Address", 348 | "order" : 1 349 | } 350 | ] 351 | } 352 | -------------------------------------------------------------------------------- /shacl-jsonld-context/examples/jsonld-examples.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix rdfs: . 3 | @prefix sh: . 4 | @prefix xsd: . 5 | @prefix ex: . 6 | 7 | 8 | ex:PersonShape 9 | a sh:NodeShape ; 10 | sh:targetClass ex:Person ; # Applies to all persons 11 | sh:property [ 12 | sh:path ex:ssn ; # This property shape is about the values of the ex:ssn property 13 | sh:maxCount 1 ; 14 | sh:datatype xsd:string ; 15 | sh:pattern "^\\d{3}-\\d{2}-\\d{4}$" ; 16 | ] ; 17 | sh:property [ 18 | sh:path ex:child ; 19 | sh:class ex:Person ; 20 | sh:nodeKind sh:IRI ; 21 | ] ; 22 | sh:property [ 23 | rdfs:comment "A person's parents are represented via ex:child used in the inverse direction." ; 24 | sh:path [ sh:inversePath ex:child ] ; 25 | sh:name "parent" ; 26 | sh:maxCount 2 ; 27 | ] ; 28 | sh:closed true ; 29 | sh:ignoredProperties ( rdf:type ) . 30 | 31 | ex:InvoiceShape 32 | a sh:NodeShape ; 33 | sh:property [ 34 | sh:path ex:customer ; 35 | sh:class ex:Customer ; 36 | sh:class ex:Person ; 37 | ] . 38 | 39 | ex:MultiplePatternsShape 40 | a sh:NodeShape ; 41 | sh:property [ 42 | sh:path ex:name ; 43 | sh:pattern "^Start" ; 44 | sh:flags "i" ; 45 | ] ; 46 | sh:property [ 47 | sh:path ex:name ; 48 | sh:pattern "End$" ; 49 | ] . 50 | 51 | ex:TargetSubjectsOfExampleShape 52 | a sh:NodeShape ; 53 | sh:targetSubjectsOf ex:knows . 54 | 55 | ex:TargetObjectsOfExampleShape 56 | a sh:NodeShape ; 57 | sh:targetObjectsOf ex:knows . 58 | 59 | ex:MyShape 60 | a sh:NodeShape ; 61 | sh:targetNode ex:MyInstance ; 62 | sh:property [ # _:b1 63 | # Violations of sh:minCount and sh:datatype are produced as warnings 64 | sh:path ex:myProperty ; 65 | sh:minCount 1 ; 66 | sh:datatype xsd:string ; 67 | sh:severity sh:Warning ; 68 | ] ; 69 | sh:property [ # _:b2 70 | # The default severity here is sh:Violation 71 | sh:path ex:myProperty ; 72 | sh:maxLength 10 ; 73 | sh:message "Too many characters"@en ; 74 | sh:message "Zu viele Zeichen"@de ; 75 | ] . 76 | 77 | ex:ExampleNodeShapeWithPropertyShapes 78 | a sh:NodeShape ; 79 | sh:property [ 80 | sh:path ex:email ; 81 | sh:name "e-mail" ; 82 | sh:description "We need at least one email value" ; 83 | sh:minCount 1 ; 84 | ] ; 85 | sh:property [ 86 | sh:path (ex:knows ex:email) ; 87 | sh:name "Friend's e-mail" ; 88 | sh:description "We need at least one email for everyone you know" ; 89 | sh:minCount 1 ; 90 | ] . 91 | 92 | ex:ExamplePropertyShape 93 | a sh:PropertyShape ; 94 | sh:path ex:email ; 95 | sh:description "We need at least one email value" ; 96 | sh:minCount 1 . 97 | 98 | ex:PersonFormShape 99 | a sh:NodeShape ; 100 | sh:property [ 101 | sh:path ex:firstName ; 102 | sh:name "first name" ; 103 | sh:description "The person's given name(s)" ; 104 | sh:order 0 ; 105 | sh:group ex:NameGroup ; 106 | ] ; 107 | sh:property [ 108 | sh:path ex:lastName ; 109 | sh:name "last name" ; 110 | sh:description "The person's last name" ; 111 | sh:order 1 ; 112 | sh:group ex:NameGroup ; 113 | ] ; 114 | sh:property [ 115 | sh:path ex:streetAddress ; 116 | sh:name "street address" ; 117 | sh:description "The street address including number" ; 118 | sh:order 11 ; 119 | sh:group ex:AddressGroup ; 120 | ] ; 121 | sh:property [ 122 | sh:path ex:locality ; 123 | sh:name "locality" ; 124 | sh:description "The suburb, city or town of the address" ; 125 | sh:order 12 ; 126 | sh:group ex:AddressGroup ; 127 | ] ; 128 | sh:property [ 129 | sh:path ex:postalCode ; 130 | sh:name "postal code" ; 131 | sh:name "zip code"@en-US ; 132 | sh:description "The postal code of the locality" ; 133 | sh:order 13 ; 134 | sh:group ex:AddressGroup ; 135 | ] . 136 | 137 | ex:NameGroup 138 | a sh:PropertyGroup ; 139 | sh:order 0 ; 140 | rdfs:label "Name" . 141 | 142 | ex:AddressGroup 143 | a sh:PropertyGroup ; 144 | sh:order 1 ; 145 | rdfs:label "Address" . 146 | -------------------------------------------------------------------------------- /shacl-jsonld-context/shacl.context.ld.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "@vocab": "http://www.w3.org/ns/shacl#", 4 | "sh" : "http://www.w3.org/ns/shacl#", 5 | "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", 6 | "rdfs" : "http://www.w3.org/2000/01/rdf-schema#", 7 | "xsd": "http://www.w3.org/2001/XMLSchema#", 8 | "comment": "rdfs:comment", 9 | "target" : { 10 | "@type" : "@id" 11 | }, 12 | "targetClass" : { 13 | "@type" : "@id" 14 | }, 15 | "targetObjectsOf" : { 16 | "@type" : "@id" 17 | }, 18 | "targetSubjectsOf" : { 19 | "@type" : "@id" 20 | }, 21 | "severity" : { 22 | "@type" : "@id" 23 | }, 24 | "result" : { 25 | "@type" : "@id" 26 | }, 27 | "detail" : { 28 | "@type" : "@id" 29 | }, 30 | "resultPath" : { 31 | "@type" : "@id" 32 | }, 33 | "resultSeverity" : { 34 | "@type" : "@id" 35 | }, 36 | "sourceShape" : { 37 | "@type" : "@id" 38 | }, 39 | "sourceConstraintComponent" : { 40 | "@type" : "@id" 41 | }, 42 | "prefixes" : { 43 | "@type" : "@id" 44 | }, 45 | "declare" : { 46 | "@type" : "@id" 47 | }, 48 | "namespace" : { 49 | "@type" : "xsd:anyURI" 50 | }, 51 | "shapesGraph" : { 52 | "@type" : "@id" 53 | }, 54 | "path" : { 55 | "@type" : "@id" 56 | }, 57 | "inversePath" : { 58 | "@type" : "@id" 59 | }, 60 | "alternativePath" : { 61 | "@type" : "@id", 62 | "@container" : "@list" 63 | }, 64 | "zeroOrMorePath" : { 65 | "@type" : "@id" 66 | }, 67 | "oneOrMorePath" : { 68 | "@type" : "@id" 69 | }, 70 | "zeroOrOnePath" : { 71 | "@type" : "@id" 72 | }, 73 | "parameter" : { 74 | "@type" : "@id" 75 | }, 76 | "validator" : { 77 | "@type" : "@id" 78 | }, 79 | "nodeValidator" : { 80 | "@type" : "@id" 81 | }, 82 | "propertyValidator" : { 83 | "@type" : "@id" 84 | }, 85 | "and" : { 86 | "@type" : "@id", 87 | "@container" : "@list" 88 | }, 89 | "class" : { 90 | "@type" : "@id" 91 | }, 92 | "ignoredProperties" : { 93 | "@type" : "@id", 94 | "@container" : "@list" 95 | }, 96 | "datatype" : { 97 | "@type" : "@id" 98 | }, 99 | "disjoint" : { 100 | "@type" : "@id" 101 | }, 102 | "equals" : { 103 | "@type" : "@id" 104 | }, 105 | "in" : { 106 | "@container" : "@list" 107 | }, 108 | "languageIn" : { 109 | "@container" : "@list" 110 | }, 111 | "lessThan" : { 112 | "@type" : "@id" 113 | }, 114 | "lessThanOrEquals" : { 115 | "@type" : "@id" 116 | }, 117 | "node" : { 118 | "@type" : "@id" 119 | }, 120 | "nodeKind" : { 121 | "@type" : "@id" 122 | }, 123 | "not" : { 124 | "@type" : "@id" 125 | }, 126 | "or" : { 127 | "@type" : "@id", 128 | "@container" : "@list" 129 | }, 130 | "property" : { 131 | "@type" : "@id" 132 | }, 133 | "qualifiedValueShape" : { 134 | "@type" : "@id" 135 | }, 136 | "xone" : { 137 | "@type" : "@id", 138 | "@container" : "@list" 139 | }, 140 | "sparql" : { 141 | "@type" : "@id" 142 | }, 143 | "derivedValues" : { 144 | "@type" : "@id" 145 | }, 146 | "group" : { 147 | "@type" : "@id" 148 | }, 149 | "returnType" : { 150 | "@type" : "@id" 151 | }, 152 | "resultAnnotation" : { 153 | "@type" : "@id" 154 | }, 155 | "annotationProperty" : { 156 | "@type" : "@id" 157 | }, 158 | "maxCount" : { 159 | "@type" : "xsd:integer" 160 | }, 161 | "maxLength" : { 162 | "@type" : "xsd:integer" 163 | }, 164 | "minCount" : { 165 | "@type" : "xsd:integer" 166 | }, 167 | "minLength" : { 168 | "@type" : "xsd:integer" 169 | }, 170 | "qualifiedMaxCount" : { 171 | "@type" : "xsd:integer" 172 | }, 173 | "qualifiedMinCount" : { 174 | "@type" : "xsd:integer" 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /shapes/datacube.shapes.ttl: -------------------------------------------------------------------------------- 1 | # baseURI: http://topbraid.org/datacube 2 | # imports: http://datashapes.org/dash 3 | # imports: http://purl.org/linked-data/cube 4 | # imports: http://www.w3.org/2004/02/skos/core 5 | 6 | @prefix dash: . 7 | @prefix owl: . 8 | @prefix qb: . 9 | @prefix rdf: . 10 | @prefix rdfs: . 11 | @prefix sh: . 12 | @prefix skos: . 13 | @prefix xsd: . 14 | 15 | qb:ComponentPropertyRuleShape 16 | a sh:NodeShape ; 17 | rdfs:comment "A SHACL rule that can be used to infer additional triples that copies all values of the sub-properties of qb:componentProperty into qb:componentProperty itself. This is needed because many constraints here only reference qb:componentProperty." ; 18 | sh:rule [ 19 | a sh:SPARQLRule ; 20 | sh:construct """CONSTRUCT { 21 | ?subject qb:componentProperty ?object . 22 | } 23 | WHERE { 24 | ?subject qb:attribute|qb:dimension|qb:measure|qb:measureDimension ?object . 25 | }""" ; 26 | sh:order 0 ; 27 | sh:prefixes ; 28 | ] ; 29 | sh:targetNode sh:this ; 30 | . 31 | qb:DataSetShape 32 | a sh:NodeShape ; 33 | rdfs:label "Data set shape" ; 34 | sh:property [ 35 | sh:path qb:structure ; 36 | rdfs:comment "IC-2. Unique DSD" ; 37 | sh:maxCount 1 ; 38 | sh:message "Every qb:DataSet has exactly one associated qb:DataStructureDefinition." ; 39 | sh:minCount 1 ; 40 | ] ; 41 | sh:targetClass qb:DataSet ; 42 | . 43 | qb:DataStructureDefinitionShape 44 | a sh:NodeShape ; 45 | rdfs:label "Data structure definition shape" ; 46 | sh:property [ 47 | sh:path qb:component ; 48 | rdfs:comment "IC-3. DSD includes measure" ; 49 | sh:message "Every qb:DataStructureDefinition must include at least one declared measure." ; 50 | sh:qualifiedMinCount 1 ; 51 | sh:qualifiedValueShape [ 52 | sh:path qb:componentProperty ; 53 | sh:qualifiedMinCount 1 ; 54 | sh:qualifiedValueShape [ 55 | rdfs:comment "Note: we assume here that subclasses of qb:MeasureProperty are also permitted." ; 56 | sh:class qb:MeasureProperty ; 57 | ] ; 58 | ] ; 59 | ] ; 60 | sh:sparql [ 61 | rdfs:comment "IC-6. Only attributes may be optional" ; 62 | sh:message "The only components of a qb:DataStructureDefinition that may be marked as optional, using qb:componentRequired are attributes." ; 63 | sh:prefixes ; 64 | sh:select """SELECT $this 65 | WHERE { 66 | $this qb:component ?componentSpec . 67 | ?componentSpec qb:componentRequired false ; 68 | qb:componentProperty ?component . 69 | FILTER NOT EXISTS { ?component a qb:AttributeProperty } 70 | }""" ; 71 | ] ; 72 | sh:targetClass qb:DataStructureDefinition ; 73 | . 74 | qb:DimensionPropertyShape 75 | a sh:NodeShape ; 76 | rdfs:label "Dimension property shape" ; 77 | sh:node [ 78 | rdfs:comment "IC-5: Concept dimensions have code lists" ; 79 | sh:message "Every dimension with range skos:Concept must have a qb:codeList." ; 80 | sh:or ( 81 | [ 82 | sh:not [ 83 | sh:path rdfs:range ; 84 | sh:hasValue skos:Concept ; 85 | ] ; 86 | ] 87 | [ 88 | sh:path qb:codeList ; 89 | sh:minCount 1 ; 90 | ] 91 | ) ; 92 | ] ; 93 | sh:property [ 94 | sh:path rdfs:range ; 95 | rdfs:comment "IC-4. Dimensions have range" ; 96 | sh:message "Every dimension declared in a qb:DataStructureDefinition must have a declared rdfs:range." ; 97 | sh:minCount 1 ; 98 | ] ; 99 | sh:targetClass qb:DimensionProperty ; 100 | . 101 | qb:ObservationShape 102 | a sh:NodeShape ; 103 | rdfs:label "Observation shape" ; 104 | sh:property [ 105 | sh:path qb:dataSet ; 106 | rdfs:comment "IC-1. Unique DataSet" ; 107 | sh:maxCount 1 ; 108 | sh:message "Every qb:Observation has exactly one associated qb:DataSet." ; 109 | sh:minCount 1 ; 110 | ] ; 111 | sh:sparql [ 112 | rdfs:comment "IC-11. All dimensions required" ; 113 | sh:message "Every qb:Observation has a value for each dimension declared in its associated qb:DataStructureDefinition." ; 114 | sh:prefixes ; 115 | sh:select """SELECT $this 116 | WHERE { 117 | $this qb:dataSet/qb:structure/qb:component/qb:componentProperty ?dim . 118 | ?dim a qb:DimensionProperty; 119 | FILTER NOT EXISTS { $this ?dim [] } 120 | }""" ; 121 | ] ; 122 | sh:sparql [ 123 | rdfs:comment "IC-12. No duplicate observations" ; 124 | sh:message "No two qb:Observations in the same qb:DataSet may have the same value for all dimensions." ; 125 | sh:prefixes ; 126 | sh:select """SELECT $this 127 | WHERE { 128 | { 129 | # For each pair of observations test if all the dimension values are the same 130 | SELECT $this (MIN(?equal) AS ?allEqual) 131 | WHERE { 132 | $this qb:dataSet ?dataset . 133 | ?obs2 qb:dataSet ?dataset . 134 | FILTER ($this != ?obs2) 135 | ?dataset qb:structure/qb:component/qb:componentProperty ?dim . 136 | ?dim a qb:DimensionProperty . 137 | $this ?dim ?value1 . 138 | ?obs2 ?dim ?value2 . 139 | BIND( ?value1 = ?value2 AS ?equal) 140 | } 141 | GROUP BY $this ?obs2 142 | } 143 | FILTER( ?allEqual ) 144 | }""" ; 145 | ] ; 146 | sh:sparql [ 147 | rdfs:comment "IC-13. Required attributes" ; 148 | sh:message "Every qb:Observation has a value for each declared attribute that is marked as required." ; 149 | sh:prefixes ; 150 | sh:select """SELECT $this 151 | WHERE { 152 | $this qb:dataSet/qb:structure/qb:component ?component . 153 | ?component qb:componentRequired true ; 154 | qb:componentProperty ?attr . 155 | FILTER NOT EXISTS { $this ?attr [] } 156 | }""" ; 157 | ] ; 158 | sh:sparql [ 159 | rdfs:comment "IC-14. All measures present" ; 160 | sh:message "In a qb:DataSet which does not use a Measure dimension then each individual qb:Observation must have a value for every declared measure." ; 161 | sh:prefixes ; 162 | sh:select """SELECT $this 163 | WHERE { 164 | # Observation in a non-measureType cube 165 | $this qb:dataSet/qb:structure ?dsd . 166 | FILTER NOT EXISTS { ?dsd qb:component/qb:componentProperty qb:measureType } 167 | 168 | # verify every measure is present 169 | ?dsd qb:component/qb:componentProperty ?measure . 170 | ?measure a qb:MeasureProperty; 171 | FILTER NOT EXISTS { $this ?measure [] } 172 | }""" ; 173 | ] ; 174 | sh:sparql [ 175 | rdfs:comment "IC-15. Measure dimension consistent" ; 176 | sh:message "In a qb:DataSet which uses a Measure dimension then each qb:Observation must have a value for the measure corresponding to its given qb:measureType." ; 177 | sh:prefixes ; 178 | sh:select """SELECT $this 179 | WHERE { 180 | # Observation in a measureType-cube 181 | $this qb:dataSet/qb:structure ?dsd ; 182 | qb:measureType ?measure . 183 | ?dsd qb:component/qb:componentProperty qb:measureType . 184 | # Must have value for its measureType 185 | FILTER NOT EXISTS { $this ?measure [] } 186 | }""" ; 187 | ] ; 188 | sh:sparql [ 189 | rdfs:comment "IC-16. Single measure on measure dimension observation" ; 190 | sh:message """In a qb:DataSet which uses a Measure dimension then each qb:Observation must only have a value for one measure (by IC-15 this will be the measure corresponding to its qb:measureType). 191 | 192 | """ ; 193 | sh:prefixes ; 194 | sh:select """SELECT $this 195 | WHERE { 196 | # Observation with measureType 197 | $this qb:dataSet/qb:structure ?dsd ; 198 | qb:measureType ?measure ; 199 | ?omeasure [] . 200 | # Any measure on the observation 201 | ?dsd qb:component/qb:componentProperty qb:measureType ; 202 | qb:component/qb:componentProperty ?omeasure . 203 | ?omeasure a qb:MeasureProperty . 204 | # Must be the same as the measureType 205 | FILTER (?omeasure != ?measure) 206 | }""" ; 207 | ] ; 208 | sh:sparql [ 209 | rdfs:comment "IC-17. All measures present in measures dimension cube" ; 210 | sh:message "In a qb:DataSet which uses a Measure dimension then if there is a Observation for some combination of non-measure dimensions then there must be other Observations with the same non-measure dimension values for each of the declared measures." ; 211 | sh:prefixes ; 212 | sh:select """SELECT $this 213 | WHERE { 214 | { 215 | # Count number of other measures found at each point 216 | SELECT $this ?numMeasures (COUNT(?obs2) AS ?count) 217 | WHERE { 218 | { 219 | # Find the DSDs and check how many measures they have 220 | SELECT $this ?dsd (COUNT(?m) AS ?numMeasures) 221 | WHERE { 222 | ?dsd qb:component/qb:componentProperty ?m. 223 | ?m a qb:MeasureProperty . 224 | } 225 | GROUP BY ?dsd 226 | } 227 | 228 | # Observation in measureType cube 229 | $this qb:dataSet/qb:structure ?dsd; 230 | qb:dataSet ?dataset ; 231 | qb:measureType ?m1 . 232 | 233 | # Other observation at same dimension value 234 | ?obs2 qb:dataSet ?dataset ; 235 | qb:measureType ?m2 . 236 | FILTER NOT EXISTS { 237 | ?dsd qb:component/qb:componentProperty ?dim . 238 | FILTER (?dim != qb:measureType) 239 | ?dim a qb:DimensionProperty . 240 | $this ?dim ?v1 . 241 | ?obs2 ?dim ?v2. 242 | FILTER (?v1 != ?v2) 243 | } 244 | 245 | } 246 | GROUP BY $this ?numMeasures 247 | HAVING (?count != ?numMeasures) 248 | } 249 | }""" ; 250 | ] ; 251 | sh:sparql [ 252 | rdfs:comment "IC-18. Consistent data set links" ; 253 | sh:message "If a qb:DataSet D has a qb:slice S, and S has an qb:observation O, then the qb:dataSet corresponding to O must be D." ; 254 | sh:prefixes ; 255 | sh:select """SELECT $this 256 | WHERE { 257 | ?slice qb:observation $this . 258 | ?dataset qb:slice ?slice . 259 | FILTER NOT EXISTS { $this qb:dataSet ?dataset . } 260 | }""" ; 261 | ] ; 262 | sh:sparql [ 263 | rdfs:comment "IC-19. a) Codes from code list" ; 264 | owl:versionInfo "See section IC-19 in the Data Cubes spec on pre-conditions that need to be met prior to the execution of this constraints. Parts of them are covered by the rules at skos:memberListShape." ; 265 | sh:message "If a dimension property has a qb:codeList, then the value of the dimension property on every qb:Observation must be in the code list." ; 266 | sh:prefixes ; 267 | sh:select """SELECT $this 268 | WHERE { 269 | $this qb:dataSet/qb:structure/qb:component/qb:componentProperty ?dim . 270 | ?dim a qb:DimensionProperty ; 271 | qb:codeList ?list . 272 | ?list a skos:ConceptScheme . 273 | $this ?dim ?v . 274 | FILTER NOT EXISTS { ?v a skos:Concept ; skos:inScheme ?list } 275 | }""" ; 276 | ] ; 277 | sh:sparql [ 278 | rdfs:comment "IC-19. b) Codes from code list" ; 279 | owl:versionInfo "See section IC-19 in the Data Cubes spec on pre-conditions that need to be met prior to the execution of this constraints. Parts of them are covered by the rules at skos:memberListShape." ; 280 | sh:message "If a dimension property has a qb:codeList, then the value of the dimension property on every qb:Observation must be in the code list." ; 281 | sh:prefixes ; 282 | sh:select """SELECT $this 283 | WHERE { 284 | $this qb:dataSet/qb:structure/qb:component/qb:componentProperty ?dim . 285 | ?dim a qb:DimensionProperty ; 286 | qb:codeList ?list . 287 | ?list a skos:Collection . 288 | $this ?dim ?v . 289 | FILTER NOT EXISTS { ?v a skos:Concept ; skos:member+ ?v } 290 | }""" ; 291 | ] ; 292 | sh:sparql [ 293 | rdfs:comment "IC-20. Codes from hierarchy" ; 294 | sh:message "If a dimension property has a qb:HierarchicalCodeList with a non-blank qb:parentChildProperty then the value of that dimension property on every qb:Observation must be reachable from a root of the hierarchy using zero or more hops along the qb:parentChildProperty links." ; 295 | sh:prefixes ; 296 | sh:select """SELECT $this 297 | WHERE { 298 | $this qb:dataSet/qb:structure/qb:component/qb:componentProperty ?dim . 299 | ?dim a qb:DimensionProperty ; 300 | qb:codeList ?list . 301 | ?list a qb:HierarchicalCodeList . 302 | $this ?dim ?v . 303 | ?hierarchy a qb:HierarchicalCodeList ; 304 | qb:parentChildProperty ?p . 305 | FILTER ( isIRI(?p) ) . 306 | FILTER NOT EXISTS { 307 | ?list qb:hierarchyRoot ?root . 308 | FILTER qb:hasZeroOrMore(?root, ?p, ?v) . 309 | } 310 | }""" ; 311 | ] ; 312 | sh:sparql [ 313 | rdfs:comment "IC-21. Codes from hierarchy (inverse)" ; 314 | sh:message "If a dimension property has a qb:HierarchicalCodeList with an inverse qb:parentChildProperty then the value of that dimension property on every qb:Observation must be reachable from a root of the hierarchy using zero or more hops along the inverse qb:parentChildProperty links." ; 315 | sh:prefixes ; 316 | sh:select """SELECT $this 317 | WHERE { 318 | $this qb:dataSet/qb:structure/qb:component/qb:componentProperty ?dim . 319 | ?dim a qb:DimensionProperty ; 320 | qb:codeList ?list . 321 | ?list a qb:HierarchicalCodeList . 322 | $this ?dim ?v . 323 | ?hierarchy a qb:HierarchicalCodeList; 324 | qb:parentChildProperty ?pcp . 325 | FILTER( isBlank(?pcp) ) 326 | ?pcp owl:inverseOf ?p . 327 | FILTER( isIRI(?p) ) 328 | FILTER NOT EXISTS { 329 | ?list qb:hierarchyRoot ?root . 330 | FILTER qb:hasZeroOrMore(?root, ?p, ?v) . 331 | } 332 | }""" ; 333 | ] ; 334 | sh:targetClass qb:Observation ; 335 | . 336 | qb:SliceKeyShape 337 | a sh:NodeShape ; 338 | rdfs:label "Slice key shape" ; 339 | sh:sparql [ 340 | rdfs:comment "IC-7. Slice Keys must be declared" ; 341 | sh:message "Every qb:SliceKey must be associated with a qb:DataStructureDefinition." ; 342 | sh:prefixes ; 343 | sh:select """SELECT $this 344 | WHERE { 345 | FILTER NOT EXISTS { [a qb:DataStructureDefinition] qb:sliceKey $this } 346 | }""" ; 347 | ] ; 348 | sh:sparql [ 349 | rdfs:comment "IC-8. Slice Keys consistent with DSD" ; 350 | sh:message "Every qb:componentProperty on a qb:SliceKey must also be declared as a qb:component of the associated qb:DataStructureDefinition." ; 351 | sh:prefixes ; 352 | sh:select """SELECT $this 353 | WHERE { 354 | $this qb:componentProperty ?prop . 355 | ?dsd qb:sliceKey $this . 356 | FILTER NOT EXISTS { ?dsd qb:component [qb:componentProperty ?prop] } 357 | }""" ; 358 | ] ; 359 | sh:targetClass qb:SliceKey ; 360 | . 361 | qb:SliceShape 362 | a sh:NodeShape ; 363 | rdfs:label "Slice shape" ; 364 | sh:property [ 365 | sh:path qb:sliceStructure ; 366 | rdfs:comment "IC-9. Unique slice structure" ; 367 | sh:maxCount 1 ; 368 | sh:message "Each qb:Slice must have exactly one associated qb:sliceStructure." ; 369 | sh:minCount 1 ; 370 | ] ; 371 | sh:sparql [ 372 | rdfs:comment "IC-10. Slice dimensions complete" ; 373 | sh:message "Every qb:Slice must have a value for every dimension declared in its qb:sliceStructure." ; 374 | sh:prefixes ; 375 | sh:select """SELECT $this 376 | WHERE { 377 | $this qb:sliceStructure [qb:componentProperty ?dim] . 378 | FILTER NOT EXISTS { $this ?dim [] } 379 | }""" ; 380 | ] ; 381 | sh:targetClass qb:Slice ; 382 | . 383 | qb:hasZeroOrMore 384 | a sh:SPARQLFunction ; 385 | rdfs:comment "A helper function that simulates a property* path in SPARQL, where the property is a variable. This is needed as a helper for the constraints IC-20 and IC-21. The function takes a subject, predicate and object (all of which must be bound) and returns true if the SPARQL expression ?subject ?predicate* ?object has a match." ; 386 | rdfs:label "has zero or more" ; 387 | sh:ask """ASK { 388 | FILTER (?subject = ?object || EXISTS { 389 | ?subject ?predicate ?o . 390 | FILTER qb:hasZeroOrMore(?o, ?predicate, ?object) . 391 | }) 392 | }""" ; 393 | sh:parameter [ 394 | sh:path qb:object ; 395 | sh:description "The value on the \"right hand side\"." ; 396 | sh:name "object" ; 397 | sh:order 2 ; 398 | ] ; 399 | sh:parameter [ 400 | sh:path qb:predicate ; 401 | sh:description "The \"predicate\", i.e. the property to traverse." ; 402 | sh:name "predicate" ; 403 | sh:nodeKind sh:IRI ; 404 | sh:order 1 ; 405 | ] ; 406 | sh:parameter [ 407 | sh:path qb:subject ; 408 | sh:description "The value on the \"left hand side\"." ; 409 | sh:name "subject" ; 410 | sh:order 0 ; 411 | ] ; 412 | sh:prefixes ; 413 | sh:returnType xsd:boolean ; 414 | . 415 | 416 | a owl:Ontology ; 417 | rdfs:comment "Implements the integrity constraints defined by section 11.1 of the Data Cube specification. Most of the constraints work in standard SHACL-SPARQL, but two constraints require a SHACL function (from SHACL Advanced Features) to recursively walk a dynamically computed property path. An alternative implementation of these constraints could be produced without a helper function based on SHACL-JS." ; 418 | rdfs:label "SHACL shapes for RDF Data Cube Vocabulary" ; 419 | rdfs:seeAlso ; 420 | owl:imports ; 421 | owl:imports ; 422 | owl:imports ; 423 | owl:versionInfo "Created with TopBraid Composer. This is currently completely untested." ; 424 | sh:declare [ 425 | a sh:PrefixDeclaration ; 426 | sh:namespace "http://purl.org/linked-data/cube#"^^xsd:anyURI ; 427 | sh:prefix "qb" ; 428 | ] ; 429 | sh:entailment sh:Rules ; 430 | . 431 | skos:memberListShape 432 | a sh:NodeShape ; 433 | rdfs:comment "A shape that applies to all subjects of skos:memberList triples." ; 434 | rdfs:label "member list shape" ; 435 | sh:rule [ 436 | a sh:SPARQLRule ; 437 | rdfs:comment "Materializes any skos:member triples from skos:memberList values, if needed." ; 438 | sh:construct """CONSTRUCT { 439 | $this skos:member ?member . 440 | } 441 | WHERE { 442 | $this skos:memberList ?list . 443 | ?list rdf:rest*/rdf:first ?member . 444 | }""" ; 445 | sh:prefixes ; 446 | ] ; 447 | sh:targetSubjectsOf skos:memberList ; 448 | . 449 | -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "contacts": ["caribouW3"] 3 | , "policy": "open" 4 | , "repo-type": "archive" 5 | , "exposed": "false" 6 | } 7 | --------------------------------------------------------------------------------