繁体   English   中英

RDF4j Shacl 验证为 Turtle 和 JSON-LD 提供了不同的结果

[英]RDF4j Shacl validation gives different results for Turtle and JSON-LD

我对 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". 不是规则中定义的 integer: shacl:datatype xsd:integer; . 这是我所期望的行为。

但是当我使用完全相同的数据但采用 JSON-LD 格式时:

...
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 Jena 或在线https://shacl.org/playground/正在返回正确的数据类型违规。

当我从 @context 中删除property类型时,出现数据类型冲突:

"@type": "http://www.w3.org/2001/XMLSchema#integer"

或将property更改为 ObjectProperty:

"property": {
  "@id": "http://example.com/property1"
  ...
}

但是当我使用字符串而不是 integer 时,没有数据类型违规。

这是 RDF4J 中的错误还是预期的行为?

您正在观察的是 JSON-LD 中类型强制的影响。 似乎某些解析器(甚至是EasyRDF解析器)在接受类型化值时会执行额外的步骤,如果该类型是已知的数字类型 - 他们尝试将其解析为实际数字并使用 output 中的结果,而忽略原始词汇价值。 尝试解析"property": " 100.0 " ——它会在将其转换为 integer 之前修剪空格并删除.0

这种解析可能显然会失败,但解析器可能没有正确编写以适应这种情况,所以在 EasyRDF 的情况下,这是"property": "test"的结果:

<http://example.com/1>
  a <http://example.com/Class> ;
  <http://example.com/Property> 0 .

我假设 SHACL Playground 使用的解析器更智能一些,可以将其视为以下内容:

<http://example.com/1>
  a <http://example.com/Class> ;
  <http://example.com/Property> "test"^^<http://www.w3.org/2001/XMLSchema#integer> .

请注意,这是您在 JSON-LD 中实际指定的内容:通过说属性的类型为xsd:integer ,如果您不使用值 ZA8CFDE6331BD59EB66AC96F891C ,它永远不会是字符串。 根据 SHACL 规则,结果不仅应该是无效的,而且在 RDFS 和 OWL 中也是矛盾的。


我没有明确的解决方案,因为我不知道 RDF4J JSON-LD 解析器是否可以配置为表现不同。 但是,这些是我能想到的选项:

  • 不要使用"@type": "http://www.w3.org/2001/XMLSchema#integer" JSON-LD 的生产者必须明确说明值的类型,甚至像"10"这样的东西也不会通过——它必须是10作为 JSON 中的数字。 这仍然可以通过值 object (使用@type )来规避。
  • 不要忽视解析的 JSON-LD 数据; 将其与输入一起保存,以便在所有 SHACL 处理器中都有效(但可能不是 JSON-LD 的生产者想要的)。
  • 在将数据提供给 SHACL 验证器之前,不要先使用RDFFormat.JSONLD或使用不同的解析器。
  • 要求http://example.com/Property在 SHACL 中为非零,假设 0 确实是出现在那里的值。

旁注:SHACL Playground 使用的 JSON-LD 解析器绝对不是完美的,因为它还将"10.5""10whatever"解析为10 似乎它使用 JavaScript 的parseInt或类似的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM