Martynas Jusevičius
Martynas Jusevičius

Reputation: 612

Validating rdf:Seq with SPARQL

rdf:Seq is a sequence of RDF properties rdf:_1, rdf:_2, rdf:_3...

Can it be validated using a SPARQL 1.1 query? For example, if the sequence is valid, an ASK query should return true, otherwise false.

The constraints that I can think of right now:

I suspect a completely generic solution can be difficult due to the absence of recursion in SPARQL. But a pragmatic solution that validates a finite number of members (say 30 or 50) would be acceptable as well.

Upvotes: 1

Views: 242

Answers (1)

Jan Martin Keil
Jan Martin Keil

Reputation: 1519

One could just check, if there is some item with another item of the same position or if there is an item without direct predecessor. Unfortunately, this requires some ugly and expensive string operations, so this will probably take longer on large datasets. This query ignores that the duplicate might actually be the same (owl:sameAs).

Sample Data:

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
@prefix ex: <http://example.org/>

ex:a a rdf:Seq;
    rdf:_1 ex:a1 ;
    rdf:_2 ex:a2 .
ex:b a rdf:Bag;
    rdf:_1 ex:b1 ;
    rdf:_1 ex:b2 .
ex:c a rdf:Alt;
    rdf:_2 ex:c1 .
ex:d a rdf:Seq;
    rdf:_0 ex:d1 ;
    rdf:_1 ex:d2 .

Query:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?container ?containerMembershipProperty ?item ?error WHERE {
  {
    ?container a rdf:Seq .
  } UNION {
    ?container a rdf:Bag .
  } UNION {
    ?container a rdf:Alt .
  }
  {
    BIND("Duplicated Index" AS ?error)
    ?container ?containerMembershipProperty ?item .
    FILTER strstarts(str(?containerMembershipProperty),"http://www.w3.org/1999/02/22-rdf-syntax-ns#_")
    FILTER EXISTS {
      ?container ?containerMembershipProperty ?item2 .
      FILTER (?item!=?item2)
    }
  } UNION {
    BIND("Missing Predecessor" AS ?error)
    ?container ?containerMembershipProperty ?item .
    BIND(xsd:integer(STRAFTER(STR(?containerMembershipProperty),"http://www.w3.org/1999/02/22-rdf-syntax-ns#_")) - 1 AS ?index)
    BIND(IRI(CONCAT("http://www.w3.org/1999/02/22-rdf-syntax-ns#_", STR(?index))) AS ?previousContainerMembershipProperty)
    FILTER (?index >= 1)
    FILTER NOT EXISTS {
      ?container ?previousContainerMembershipProperty ?item3
    }
  } UNION {
    BIND("Illegal Index" AS ?error)
    ?container ?containerMembershipProperty ?item .
    BIND(xsd:integer(STRAFTER(STR(?containerMembershipProperty),"http://www.w3.org/1999/02/22-rdf-syntax-ns#_")) AS ?index)
    FILTER (?index < 1)
  }
}
ORDER BY ?container ?containerMembershipProperty ?item

Result:

container containerMembershipProperty item error
http://example.org/b rdf:_1 http://example.org/b1 "Duplicated Index"
http://example.org/b rdf:_1 http://example.org/b2 "Duplicated Index"
http://example.org/c rdf:_2 http://example.org/c1 "Missing Predecessor"
http://example.org/d rdf:_0 http://example.org/d1 "Illegal Index"

Upvotes: 3

Related Questions