我对RDF4J SHACL验证引擎有问题。
这是我使用shacl规则和示例有效负载文件作为TTL输入的代码:
String SHAPES = "rules.ttl";
String DATA = "input.ttl";
ShaclSail shaclSail = new ShaclSail(new MemoryStore());
Repository repo = new SailRepository(shaclSail);
try (RepositoryConnection connection = repo.getConnection()) {
connection.begin();
connection.add(new StringReader(Files.readString(Path.of(SHAPES))), RDFFormat.TURTLE, RDF4J.SHACL_SHAPE_GRAPH);
connection.commit();
connection.begin();
connection.add(new StringReader(Files.readString(Path.of(DATA))), RDFFormat.TURTLE);
connection.commit();
connection.begin();
connection.clear(RDF4J.SHACL_SHAPE_GRAPH);
connection.commit();
} catch (Exception e) {
Throwable cause = e.getCause();
if (cause instanceof ValidationException) {
Model validationReportModel = ((ValidationException) cause).validationReportAsModel();
Rio.write(validationReportModel, System.out, RDFFormat.TURTLE);
}
}shacl规则文件如下所示:
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix shacl: <http://www.w3.org/ns/shacl#> .
<http://example.com/Property>
a owl:DatatypeProperty, rdf:Property .
<http://example.com/Class>
a owl:Class .
<http://example.com/ClassShape>
a <http://www.w3.org/ns/shacl#NodeShape> ;
shacl:property <http://example.com/PropertyShape> ;
shacl:targetClass <http://example.com/Class> .
<http://example.com/PropertyShape>
a shacl:PropertyShape ;
shacl:datatype xsd:integer ;
shacl:maxCount 1 ;
shacl:minCount 1 ;
shacl:path <http://example.com/Property> .以及输入文件:
<http://example.com/1>
a <http://example.com/Class> ;
<http://example.com/Property> "test" .上面的代码段返回一个正确的数据类型冲突结果,因为<http://example.com/Property> "test" .不是规则:shacl:datatype xsd:integer ;中定义的整数。我希望这是一种行为。
但是,当我使用完全相同的数据(但使用JSON格式)时:
...
connection.add(new StringReader(Files.readString(Path.of(SHAPES))), RDFFormat.JSONLD, RDF4J.SHACL_SHAPE_GRAPH);
...
connection.add(new StringReader(Files.readString(Path.of(DATA))), RDFFormat.JSONLD);
...使用此规则文件:
{
"@context": {
"id": "@id",
"type": "@type",
"datatype": {
"@id": "http://www.w3.org/ns/shacl#datatype",
"@type": "@id"
},
"path": {
"@id": "http://www.w3.org/ns/shacl#path",
"@type": "@id"
},
"class": {
"@id": "http://www.w3.org/ns/shacl#class",
"@type": "@id"
},
"property": {
"@id": "http://www.w3.org/ns/shacl#property",
"@type": "@id",
"@container": "@set"
},
"targetClass": {
"@id": "http://www.w3.org/ns/shacl#targetClass",
"@type": "@id"
},
"maxCount": "http://www.w3.org/ns/shacl#maxCount",
"minCount": "http://www.w3.org/ns/shacl#minCount",
"PropertyShape": "http://www.w3.org/ns/shacl#PropertyShape",
"Property": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property",
"NodeShape": "http://www.w3.org/ns/shacl#NodeShape",
"Class": "http://www.w3.org/2002/07/owl#Class",
"DatatypeProperty": "http://www.w3.org/2002/07/owl#DatatypeProperty"
},
"@graph": [
{
"id": "http://example.com/Property",
"type": [
"DatatypeProperty",
"Property"
]
},
{
"id": "http://example.com/Class",
"type": "Class"
},
{
"id": "http://example.com/ClassShape",
"type": "NodeShape",
"property": [
"http://example.com/PropertyShape"
],
"targetClass": "http://example.com/Class"
},
{
"id": "http://example.com/PropertyShape",
"type": "PropertyShape",
"datatype": "http://www.w3.org/2001/XMLSchema#integer",
"maxCount": 1,
"minCount": 1,
"path": "http://example.com/Property"
}
]
}和内容文件:
{
"@context": {
"Class": "http://example.com/Class",
"property": {
"@id": "http://example.com/Property",
"@type": "http://www.w3.org/2001/XMLSchema#integer"
}
},
"@graph": {
"@type": "Class",
"@id": "http://example.com/1",
"property": "test"
}
}我没有违规,这是非常令人惊讶的其他SHACL引擎线Apache或在线https://shacl.org/playground/返回正确的数据类型违规。
当我从@上下文中删除property类型时,会出现数据类型冲突:
"@type": "http://www.w3.org/2001/XMLSchema#integer"或者将property更改为ObjectProperty:
"property": {
"@id": "http://example.com/property1"
...
}但是,例如,当我使用字符串而不是整数时,不存在数据类型冲突。
这是RDF4J中的一个bug还是预期的行为?
发布于 2022-08-26 09:44:08
您所观察到的是类型强制在JSON中的影响。似乎有些解析器(甚至是EasyRDF解析器)在接受类型化值时会执行额外的步骤,如果类型是已知的数字类型--他们试图将其解析为实际数字,并在输出中使用结果,而忽略了原始词法值。尝试解析"property": " 100.0 " --在将其转换为整数之前,它将修剪空格并删除.0。
此解析显然可能失败,但可能无法正确地编写解析器以适应这种情况,因此在EasyRDF的情况下,这是"property": "test"的结果。
<http://example.com/1>
a <http://example.com/Class> ;
<http://example.com/Property> 0 .我假设SHACL游乐场使用的解析器更智能一些,并可以将其处理为:
<http://example.com/1>
a <http://example.com/Class> ;
<http://example.com/Property> "test"^^<http://www.w3.org/2001/XMLSchema#integer> .请注意,这是您在JSON中实际指定的内容:通过声明属性具有xsd:integer类型,如果不使用值对象,则它永远不可能是字符串。根据SHACL规则,结果不仅是无效的,而且在RDFS和OWL中也是矛盾的。
我没有明确的解决方案,因为我不知道RDF4J JSON解析器是否可以配置为不同的行为。然而,这些是我能想到的选择:
"@type": "http://www.w3.org/2001/XMLSchema#integer"。JSON的生产者必须明确说明值的类型,甚至像"10"这样的东西也不会传递--它必须是10作为JSON中的一个数字。这仍然可以通过一个值对象(使用@type)来规避。RDFFormat.JSONLD或使用不同的解析器。http://example.com/Property在SHACL中为非零,假设0确实是出现在那里的值。附带注意:不过,SHACL游乐场使用的JSON解析器显然并不完美,因为它还将"10.5"或"10whatever"解析为10。它似乎使用了JavaScript的parseInt或类似的。
https://stackoverflow.com/questions/73490841
复制相似问题