diff --git a/src/validators.js b/src/validators.js index 918206d..5e35ac5 100644 --- a/src/validators.js +++ b/src/validators.js @@ -406,12 +406,22 @@ function validateXone(context, focusNode, valueNode, constraint) { const { sh } = context.ns const xoneNode = constraint.getParameterValue(sh.xone) const shapes = rdfListToArray(context.$shapes.node(xoneNode)) - const conformsCount = shapes - .map(shape => context.nodeConformsToShape(valueNode, shape)) - .filter(Boolean) - .length - return conformsCount === 1 + const conformsPositions = [] + for (let i = 0; i < shapes.length; i++) { + const shape = shapes[i] + if (context.nodeConformsToShape(valueNode, shape)) { + conformsPositions.push(i + 1) + } + } + + if (conformsPositions.length === 0) { + return ['no shapes matched'] + } + if (conformsPositions.length > 1) { + return ['multiple matches, at positions ' + conformsPositions.join(', ')] + } + return [] } // Private helper functions diff --git a/test/data/validation-message/message-for-xone.ttl b/test/data/validation-message/message-for-xone.ttl new file mode 100644 index 0000000..64131b4 --- /dev/null +++ b/test/data/validation-message/message-for-xone.ttl @@ -0,0 +1,12 @@ +@prefix sh: . + + a , , . + + a sh:NodeShape ; + sh:targetClass ; + sh:xone ( + [ sh:class ] + [ sh:class ] + [ sh:class ] + ) ; + . diff --git a/test/validation_message_test.js b/test/validation_message_test.js index d8f75e2..f2021da 100644 --- a/test/validation_message_test.js +++ b/test/validation_message_test.js @@ -102,4 +102,17 @@ describe('validation messages', () => { assert.strictEqual(report.results[0].message.length, 1) assert.strictEqual(report.results[0].message[0].value, 'Value is not one of the allowed values: a, b, c ... (and 2 more)') }) + + it('Lists conforming shapes in message for xone', async () => { + const dataPath = path.join(rootPath, 'message-for-xone.ttl') + const data = await loadDataset(dataPath) + const shapes = data + + const validator = new SHACLValidator(shapes) + const report = validator.validate(data) + + assert.strictEqual(report.results.length, 1) + assert.strictEqual(report.results[0].message.length, 1) + assert.strictEqual(report.results[0].message[0].value, 'multiple matches, at positions 1, 3') + }) })