Skip to content

Latest commit

 

History

History

shex-validator

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

NPM Version ShapeExpressions Gitter chat https://gitter.im/shapeExpressions/Lobby DOI

@shexjs/validator

Validator pattern for traversing ShExJ schemas

install

npm install --save @shexjs/validator

Invocation

Using Partition(<schema>, [<URL>s]) as an example, an illustrative way to invoke from it from the command line uses @shexjs/parser and N3.js:

const ShExParser = require('@shexjs/parser');
const { ctor: RdfJsDb } = require('@shexjs/neighborhood-rdfjs')
const {ShExValidator} = require('@shexjs/validator');
const {Parser: N3Parser, Store: N3Store} = require('n3');
const base = 'http://a.example/';

const shexc = `
<S1> {
  <p1> . ;
  <p2> . ;
}`;

const turtle = `
<n1> <p1> 1 ; <p3> 2 . # missing p2
<n2> <p4> 1 ; <p2> 2 . # missing p1
`;

const schema = ShExParser.construct(base)
      .parse(shexc);
const g = new N3Store();
new N3Parser({baseIRI: base}).parse(turtle, (error, quad, prefixes) => {
  if (quad)
    g.addQuad(quad);
  else
    console.log(JSON.stringify(
      new ShExValidator(schema, RdfJsDb(g))
        .validate([{node: base + 'n1', shape: base + 'S1'},
                   {node: base + 'n2', shape: base + 'S1'}]),
      null, 2 # stringify args
    ));
});

The result is a JSON structure which reports the expected errors

{
  "type": "FailureList",
  "errors": [
    {
      "type": "Failure",
      "node": "http://a.example/n1",
      "shape": "http://a.example/S1",
      "errors": [
        {
          "type": "MissingProperty",
          "property": "http://a.example/p2"
        }
      ]
    },
    {
      "type": "Failure",
      "node": "http://a.example/n2",
      "shape": "http://a.example/S1",
      "errors": [
        {
          "type": "MissingProperty",
          "property": "http://a.example/p1"
        }
      ]
    }
  ]
}

Validation Proof

If we correct the two errors in the above Turtle:

<n1> <p1> 1 ; <p2> 2 . # fixed missing p2
<n2> <p1> 3 ; <p2> 4 . # fixed missing p1

, the validator gives us a proof of conformance:

{
  "type": "SolutionList",
  "solutions": [
    {
      "type": "ShapeTest",
      "node": "http://a.example/n1",
      "shape": "http://a.example/S1",
      "solution": {
        "type": "EachOfSolutions",
        "solutions": [
          {
            "type": "EachOfSolution",
            "expressions": [
              {
                "type": "TripleConstraintSolutions",
                "predicate": "http://a.example/p1",
                "solutions": [
                  {
                    "type": "TestedTriple",
                    "subject": "http://a.example/n1",
                    "predicate": "http://a.example/p1",
                    "object": {
                      "value": "1",
                      "type": "http://www.w3.org/2001/XMLSchema#integer"
                    }
                  }
                ]
              },
              {
                "type": "TripleConstraintSolutions",
                "predicate": "http://a.example/p2",
                "solutions": [
                  {
                    "type": "TestedTriple",
                    "subject": "http://a.example/n1",
                    "predicate": "http://a.example/p2",
                    "object": {
                      "value": "2",
                      "type": "http://www.w3.org/2001/XMLSchema#integer"
                    }
                  }
                ]
              }
            ]
          }
        ]
      }
    },
    {
      "type": "ShapeTest",
      "node": "http://a.example/n2",
      "shape": "http://a.example/S1",
      "solution": {
        "type": "EachOfSolutions",
        "solutions": [
          {
            "type": "EachOfSolution",
            "expressions": [
              {
                "type": "TripleConstraintSolutions",
                "predicate": "http://a.example/p1",
                "solutions": [
                  {
                    "type": "TestedTriple",
                    "subject": "http://a.example/n2",
                    "predicate": "http://a.example/p1",
                    "object": {
                      "value": "3",
                      "type": "http://www.w3.org/2001/XMLSchema#integer"
                    }
                  }
                ]
              },
              {
                "type": "TripleConstraintSolutions",
                "predicate": "http://a.example/p2",
                "solutions": [
                  {
                    "type": "TestedTriple",
                    "subject": "http://a.example/n2",
                    "predicate": "http://a.example/p2",
                    "object": {
                      "value": "4",
                      "type": "http://www.w3.org/2001/XMLSchema#integer"
                    }
                  }
                ]
              }
            ]
          }
        ]
      }
    }
  ]
}

Specifying Shape Evaluator

The triple expression in a Shape is essentially a fancy regular expression. shex.js ships with two evaluators:

  • eval-threaded-nerr (default) - Exhaustively enumerate combinations of ways the data fails to satisfy a shape's expression.
  • eval-simple-1err - Report only one error.

You can specify which module to use with the schema options parameter to the validator constructor:

      new ShExValidator(schema, RdfJsDb(g), {
        regexModule: require('@shexjs/eval-simple-1err')
      })

External Shapes

One form of ShEx extensibility is the declaration of external shapes:

<S1> {
  <p1> @<S2>
}
<S2> EXTERNAL

These must be supplied to your validator but the ShEx specification does not specify how. In ShExJS, these must be supplied as a constructor argument:

      new ShExValidator(schema, RdfJsDb(g), {
        regexModule: require('@shexjs/eval-simple-1err'),
        validateExtern: myValidator
      })

function myValidator (point, shapeLabel, ctx) { // (RdfJs.Term, string, ShapeExprValidationContext) -> ShExV.shapeExprTest
  if (shapeLabel === "http://a.example/S2") {
    const p2z = g.getQuads(point, 'http://a.example/p2', null);
    if (p2z.length === 1) {
      return {
        "type": "ShapeTest",
        "node": "_:b0",
        "shape": "http://a.example/S2",
        "solution": {
          "type": "TripleConstraintSolutions",
          "predicate": "http://a.example/p2",
          "solutions": [
            {
              "type": "TestedTriple",
              "subject": point,
              "predicate": "http://a.example/p2",
              "object": p2z[0].object.value
            }
          ]
        }
      };
    }
  }
}

Failure to supply an external validator function when validating a schema with external shapes will result in an exception:

TypeError: this.options.validateExtern is not a function

Lerna Monorepo

This repo uses lerna to manage multiple NPM packages. These packages are located in packages/*: