You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Apache Jena中使用DASH执行SHACL验证时出现异常约束错误的问题

问题:Apache Jena中使用DASH的dash:closedByTypes验证异常

我尝试在Apache Jena中使用DASH形状词汇对本体进行SHACL验证,编写代码如下:

String SHAPES = """
        @prefix : <https://example.com/> .
        @prefix sh: <http://www.w3.org/ns/shacl#> .
        @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
        @prefix owl: <http://www.w3.org/2002/07/owl#> .
        @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
        @prefix dash: <http://datashapes.org/dash#> .
        
        <https://example.com/> a owl:Ontology ;
          owl:imports <http://datashapes.org/dash> .
        
        :person a sh:NodeShape ; a rdfs:Class ;
          dash:closedByTypes true ;
          sh:ignoredProperties (
            rdf:type
          ) ;
          sh:property [
            sh:path :name ;
          ]
        .
        """;

String DATA = """
        @prefix : <https://example.com/> .
        @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
        :person-1 a :person ;
          :name "John"^^xsd:string ;
        .  
        """;

RDFParser shapesTurtleParser = RDFParser.source(new ByteArrayInputStream(SHAPES.toString().getBytes(StandardCharsets.UTF_8)))
       .forceLang(Lang.TTL)
       .build();

Graph shapesGraph = shapesTurtleParser.toGraph();

// 不加这行验证能通过
shapesGraph = Imports.withImports(shapesGraph);

RDFParser dataTurtleParser = RDFParser.source(new ByteArrayInputStream(DATA.toString().getBytes(StandardCharsets.UTF_8)))
       .forceLang(Lang.TTL)
       .build();

Graph dataGraph = dataTurtleParser.toGraph();

ValidationReport report = ShaclValidator.get().validate(shapesGraph, dataGraph);
RDFDataMgr.write(System.out, report.getModel(), Lang.TTL);

验证结果输出:

@prefix :     <https://example.com/> .
@prefix dash: <http://datashapes.org/dash#> .
@prefix owl:  <http://www.w3.org/2002/07/owl#> .
@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sh:   <http://www.w3.org/ns/shacl#> .
@prefix tosh: <http://topbraid.org/tosh#> .
@prefix xsd:  <http://www.w3.org/2001/XMLSchema#> .

[ rdf:type     sh:ValidationReport;
  sh:conforms  false;
  sh:result    [ rdf:type                      sh:ValidationResult;
                 sh:focusNode                  :person-1;
                 sh:resultMessage              "Property <https://example.com/name> is not among those permitted for any of the types";
                 sh:resultPath                 :name;
                 sh:resultSeverity             sh:Violation;
                 sh:sourceConstraintComponent  dash:ClosedByTypesConstraintComponent;
                 sh:sourceShape                :person;
                 sh:value                      "John"
               ]
] .

明明:name属性已经在Shape中声明,却得到了dash:ClosedByTypesConstraintComponent的验证错误,请问问题出在哪里?


问题原因与解决方案

原因分析

dash:closedByTypes的核心逻辑是仅允许目标类在本体中定义的属性,而非Shape里sh:property声明的属性。你的代码中:name没有被关联为:person类的属性(比如通过rdfs:domain),因此导入DASH本体后,验证器会检查数据图中:person-1的属性是否属于:person类允许的属性集合,:name不在这个集合内,所以触发错误。

另外,不调用Imports.withImports(shapesGraph)时,DASH的约束组件未被正确加载,dash:closedByTypes并未生效,所以验证能通过,但这属于未启用约束的无效状态。

解决方案

有两种可行的修复方式:

  1. 为:name属性关联:person类
    在SHAPES的Turtle代码中添加:name的领域声明,明确它属于:person类的合法属性:

    :name a rdf:Property ;
      rdfs:domain :person ;
    .
    

    这样dash:closedByTypes会识别:name是:person允许的属性,验证即可通过。

  2. 改用SHACL标准的sh:closed约束
    如果你不需要基于本体类的属性闭合验证,而是想基于Shape中声明的属性做检查,直接使用SHACL原生的sh:closed即可,无需依赖DASH:

    :person a sh:NodeShape ; a rdfs:Class ;
      sh:closed true ;
      sh:ignoredProperties ( rdf:type ) ;
      sh:property [ sh:path :name ] ;
    .
    

    这种方式下,验证器只会检查数据中的属性是否都在Shape的sh:property列表中,符合你的预期。


内容的提问来源于stack exchange,提问作者sha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:00:17