Подтверждение того, что у каждого предмета есть тип класса - PullRequest
1 голос
/ 13 апреля 2020

У меня есть следующий график данных и формы.

@prefix hr: <http://learningsparql.com/ns/humanResources#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix schema: <http://schema.org/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

hr:Employee a rdfs:Class .
hr:BadThree rdfs:comment "some comment about missing" .
hr:BadTwo a hr:BadOne .
hr:YetAnother a hr:Another .
hr:YetAnotherName a hr:AnotherName .
hr:Another a hr:Employee .
hr:AnotherName a hr:name .
hr:BadOne a hr:Dangling .
hr:name a rdf:Property .

schema:SchemaShape
    a sh:NodeShape ;
    sh:target [
        a sh:SPARQLTarget ;
        sh:prefixes hr: ;
        sh:select """
            SELECT ?this
            WHERE {
                ?this ?p ?o .
            }
            """ ;
    ] ; 

    sh:property [                
        sh:path rdf:type ;
        sh:nodeKind sh:IRI ;
        sh:hasValue rdfs:Class
    ] ; 
.

Использование pySHACL :

import rdflib

from pyshacl import validate

full_graph = open( "/Users/jamesh/jigsaw/shacl_work/data_graph.ttl", "r" ).read()

g = rdflib.Graph().parse( data = full_graph, format = 'turtle' )

report = validate( g, inference='rdfs', abort_on_error = False, meta_shacl = False, debug = False )
print( report[2] )

Я думаю, что должно произойти, цель на основе SPARQL должна выберите каждый предмет в графе данных и затем убедитесь, что существует путь rdf: type со значением rdfs: Class.

Я получаю следующий результат:

Validation Report
Conforms: True

Ожидаемые ошибки проверки должны включать только следующие темы:

| <http://learningsparql.com/ns/humanResources#BadOne>         |
| <http://learningsparql.com/ns/humanResources#BadTwo>         |
| <http://learningsparql.com/ns/humanResources#BadThree>       |
| <http://learningsparql.com/ns/humanResources#AnotherName>    |
| <http://learningsparql.com/ns/humanResources#name>           |
| <http://learningsparql.com/ns/humanResources#YetAnotherName> |

Возможно ли это с SHACL? Если да, то каким должен быть файл формы?

1 Ответ

0 голосов
/ 14 апреля 2020

То, что следует, приводит к ожидаемым ошибкам проверки, однако есть еще несколько вещей, которые я не понимаю.

  1. sh:prefixes hr: ; не требуется. Он предназначен для предоставления префиксов для самого целевого оператора SELECT SPARQL и ничего более.

  2. Вывод необходимо отключить. Он вставлял тройки и пытался их проверить. В этом случае это не то, что нужно. Что должно быть проверено, так это то, что находится в схеме и ничего больше.

  3. Я также думал, что не будет проблемой поместить все в один граф, основанный на том, что, по-видимому, было неправильное понимание https://github.com/RDFLib/pySHACL/issues/46.

graph_data = """
@prefix hr: <http://learningsparql.com/ns/humanResources#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix schema: <http://schema.org/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

hr:Employee a rdfs:Class .
hr:BadThree rdfs:comment "some comment about missing" .
hr:BadTwo a hr:BadOne .
hr:YetAnother a hr:Another .
hr:YetAnotherName a hr:AnotherName .
hr:Another a hr:Employee .
hr:AnotherName a hr:name .
hr:BadOne a hr:Dangling .
hr:name a rdf:Property .
"""

shape_data = '''
@prefix hr: <http://learningsparql.com/ns/humanResources#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix schema: <http://schema.org/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

schema:SchemaShape
    a sh:NodeShape ;
    sh:target [
        a sh:SPARQLTarget ;
        sh:prefixes hr: ;
        sh:select """
            SELECT ?this
            WHERE {
                ?this ?p ?o .
            }
            """ ;
    ] ; 

    sh:property [                
        sh:path ( rdf:type [ sh:zeroOrMorePath rdf:type ] ) ;
        sh:nodeKind sh:IRI ;
        sh:hasValue rdfs:Class
    ] ; 
.
'''

data  = rdflib.Graph().parse( data = graph_data, format = 'turtle' )
shape = rdflib.Graph().parse( data = shape_data, format = 'turtle' )

report = validate( data, shacl_graph=shape, abort_on_error = False, meta_shacl = False, debug = False, advanced = True )

Альтернатива, использующая ограничение на основе SPARQL, будет выглядеть так:

graph_data = """
@prefix hr: <http://learningsparql.com/ns/humanResources#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix schema: <http://schema.org/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

hr:Employee a rdfs:Class .
hr:BadThree rdfs:comment "some comment about missing" .
hr:BadTwo a hr:BadOne .
hr:YetAnother a hr:Another .
hr:YetAnotherName a hr:AnotherName .
hr:Another a hr:Employee .
hr:AnotherName a hr:name .
hr:BadOne a hr:Dangling .
hr:name a rdf:Property .
"""

shape_data = '''
@prefix hr: <http://learningsparql.com/ns/humanResources#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix schema: <http://schema.org/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

schema:SchemaShape
    a sh:NodeShape ;
    sh:target [
        a sh:SPARQLTarget ;
        sh:select """
            SELECT ?this
            WHERE {
                ?this ?p ?o .
            }
            """ ;
    ] ; 

    sh:sparql [ 
        a sh:SPARQLConstraint ; 
        sh:message "Node does not have type rdfs:Class." ; 
        sh:prefixes hr: ; 
        sh:select """ 
            SELECT $this 
            WHERE { 
                $this rdf:type ?o . 

                FILTER NOT EXISTS {
                    ?o rdf:type* rdfs:Class
                }
                FILTER ( strstarts( str( $this ), str( hr: ) ) ) 
            }
            """ ;
    ]
.
'''


data  = rdflib.Graph().parse( data = graph_data, format = 'turtle' )
shape = rdflib.Graph().parse( data = shape_data, format = 'turtle' )

report = validate( data, shacl_graph=shape, abort_on_error = False, meta_shacl = False, debug = False, advanced = True )
...