【问题标题】:Traversing anonymous/blank nodes in Jena遍历耶拿中的匿名/空白节点
【发布时间】:2018-01-04 00:08:25
【问题描述】:

我正在使用 Apache Jena 的 API,其中由于 unionOf 和 intersectionOf,一个图还包含一些匿名/空白节点。这样的例子之一是:

<owl:Class>
   <owl:unionOf rdf:parseType="Collection">
        <rdf:Description rdf:about="http://www.summyUrl.com/something#Entity1"/>
        <rdf:Description rdf:about="http://www.summyUrl.com/something#Entity2"/>
   </owl:unionOf>
</owl:Class>

这是一个匿名节点/资源。当我尝试获取它的 URI 时,它类似于:

“-50a5734d:15d839467d9:-1b8b”

我既无法使用此类 URI 进行 SPARQL 查询(由于解析此类 URI 时出现异常),也无法找到合适的 Jena 方法来处理它。

我正在寻找一种方法来分解这些节点并获取它的所有嵌套资源。

例如在下面的情况下,它应该返回&lt;http:/.../Entity1&gt;&lt;http:/.../Entity2&gt;&lt;http:/.../Entity3&gt;

<owl:Class>
   <owl:unionOf rdf:parseType="Collection">
        <rdf:Description rdf:about="http://www.summyUrl.com/something#Entity1"/>
        <owl:unionOf rdf:parseType="Collection">
            <rdf:Description rdf:about="http://www.summyUrl.com/something#Entity2"/>
            <rdf:Description rdf:about="http://www.summyUrl.com/something#Entity3"/>
        </owl:unionOf>
   </owl:unionOf>
</owl:Class>
  1. 有没有 Jena 的内置方法来处理它?

  2. 如果没有,我怎样才能有效地做到这一点?

【问题讨论】:

  • 您应该始终查看数据的 Turtle 序列化而不是 RDF/XML 序列化。然后您将看到您可以使用 SPARQL 属性路径。确实,这不适用于任意嵌套类,但由于它是 OWL,因此 OWL 推理器是要走的路
  • 最好先查看整个查询,但原则上,如果您正在寻找由 OWL 中的类联合定义的超类,则常见的模式是 ?subclass rdfs:subClassOf/(owl:unionOf/rdf:rest*/rdf:first)+ ?superclass

标签: java sparql jena semantic-web blank-nodes


【解决方案1】:

我试过用这种方式做,效果很好:

/**
 * Explodes <b>Anonymous resource</b> (Collection resource) in recursive way and provides
 * nested resources. Mainly considers <code>owl:unionOf</code>, <code>owl:intersactionOf</code>, <code>rdf:first</code> and <code>rdf:rest</code>
 * while traversing.
 * 
 * @param resource
 * @return LinkedList<Resource>
 */
private List<Resource> explodeAnonymousResource(Resource resource)
{
    private static List<Property> collectionProperties = new LinkedList<Property>(Arrays.asList(OWL.unionOf,OWL.intersectionOf,RDF.first,RDF.rest));

    List<Resource> resources=new LinkedList<Resource>();
    Boolean needToTraverseNext=false;

    if(resource.isAnon())
    {
        for(Property cp:collectionProperties)
        {
            if(resource.hasProperty(cp) && !resource.getPropertyResourceValue(cp).equals(RDF.nil))
            {
                Resource nextResource=resource.getPropertyResourceValue(cp);
                resources.addAll(explodeAnonymousResource(nextResource));

                needToTraverseNext=true;
            }
        }

        if(!needToTraverseNext)
        {
            resources.add(resource);
        }
    }
    else
    {
        resources.add(resource);
    }

    return resources;
}

【讨论】:

    【解决方案2】:

    使用jena-model-api:

            String s = "<rdf:RDF\n" +
                "    xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n" +
                "    xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n" +
                "    xmlns:owl=\"http://www.w3.org/2002/07/owl#\"\n" +
                "    xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\"\n" +
                "    xmlns:xsd=\"http://www.w3.org/2001/XMLSchema#\">\n" +
                "  <owl:Ontology/>\n" +
                "  <owl:Class>\n" +
                "    <owl:unionOf rdf:parseType=\"Collection\">\n" +
                "      <owl:Class rdf:about=\"http://www.summyUrl.com/something#Entity1\"/>\n" +
                "      <owl:Class>\n" +
                "        <owl:unionOf rdf:parseType=\"Collection\">\n" +
                "          <owl:Class rdf:about=\"http://www.summyUrl.com/something#Entity1\"/>\n" +
                "          <owl:Class rdf:about=\"http://www.summyUrl.com/something#Entity2\"/>\n" +
                "        </owl:unionOf>\n" +
                "      </owl:Class>\n" +
                "    </owl:unionOf>\n" +
                "  </owl:Class>\n" +
                "</rdf:RDF>";
        Model m = ModelFactory.createDefaultModel();
        try (InputStream in = new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8))) {
            m.read(in, Lang.RDFXML.getLabel());
        }
        //m.write(System.out, "ttl");
        m.listStatements()
                .mapWith(Statement::getObject)
                .filterKeep(RDFNode::isURIResource)
                .mapWith(RDFNode::asResource)
                .filterDrop(OWL.Class::equals)
                .filterDrop(OWL.Ontology::equals)
                .filterDrop(RDF.nil::equals)
                .mapWith(Resource::getURI)
                .forEachRemaining(System.out::println);
    

    输出:

    http://www.summyUrl.com/something#Entity1
    http://www.summyUrl.com/something#Entity2
    http://www.summyUrl.com/something#Entity1
    

    这只是一个例子。有很多方法可以处理任何事情

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-02
      相关资源
      最近更新 更多