如何向OWLOntology添加RDF三元组?

4

我从RabbitMQ接收到一些数据。这些数据采用三元组格式,因此消息队列中的消息可能如下所示:

:Tom foaf:knows :Anna

其中 : 是本体命名空间,我想将数据导入到其中,但其他导入的前缀也是可能的。这些三元组由主语、属性/谓词和对象组成,我知道在每个消息中它们分别是什么。

在接收方,我有一个Java程序,有一个 OWLOntology 对象,表示本体,在其中新到达的三元组应该被暂时存储以供推理和其他操作使用。我已经成功将三元组放入了Jena的 OntModel 中,但那就是全部。我尝试使用OWLRDFConsumer,但我找不到如何应用它的任何信息。

我的函数大致如下:

public void addTriple(RDFTriple triple) {

    //OntModel model = ModelFactory.createOntologyModel();

    String subject = triple.getSubject().toString();
    subject = subject.substring(1,subject.length()-1);
    Resource s = ResourceFactory.createResource(subject);

    String predicate = triple.getPredicate().toString();
    predicate = predicate.substring(1,predicate.length()-1);
    Property p = ResourceFactory.createProperty(predicate);

    String object = triple.getObject().toString();
    object = object.substring(1,object.length()-1);
    RDFNode o = ResourceFactory.createResource(object);

    Statement statement = ResourceFactory.createStatement(s, p, o);
    //model.add(statement);

    System.out.println(statement.toString());
}

我进行了子字符串操作,因为RDFTriple类会在三元组的参数周围添加<>,这导致Statement构造函数失败。

如果有人能给我指出一个示例就太好了。也许有一个更好的方法来达到同样的效果,但我还没有想到?


问题标题是“如何将RDF三元组添加到OWLOntology中?”,你在问题中说你“已经成功将三元组放入了Jena OntModel中。”那么你还需要做什么呢?能否展示一下你目前所做的工作? - Joshua Taylor
啊,OWLOntology和OWLRDFConsumer是OWL API的类,所以看起来你正在尝试使用OWL API做一些事情。你能提供一些关于你目前所做的工作的更多细节吗?还有可能会感兴趣的是你是如何将三元组导入到Jena OntModel中的。 - Joshua Taylor
是的,抱歉我没有提到它们是OWLAPI类。我一直在尝试让它工作,现在将其添加到模型中的操作也失败了,我在其中更改了很多东西,不记得它的工作方式了:( 我会将我的代码添加到原始问题中。 - casualcoder
RDFTriple具有RDFResource作为主语和谓语,以及RDFNode作为宾语。如果您使用getSubject获取RDFResource,然后使用getResource获取IRI,然后在其上使用toString,我认为您将获得IRI文本(而不是toQuotedString,它返回由尖括号包围的文本)。 - Joshua Taylor
我不必使用RDFTriple。我的输入是纯JSON,只是因为RDFTriple类是三元组,所以我认为应该使用它。或者不用? - casualcoder
2个回答

3
似乎 OWLRDFConsumer 通常用于将 RDF 解析器与 OWL 感知处理器连接。以下代码似乎可以工作,但正如我在注释中指出的那样,有几个地方我需要一个参数并放入唯一可用的东西。
以下代码:创建本体;声明两个命名个体,Tom和Anna;声明一个对象属性likes和一个数据属性age。一旦这些被声明,我们打印本体以确保它符合我们的期望。然后创建一个OWLRDFConsumer。消费者构造函数需要一个本体、一个AnonymousNodeChecker和一个OWLOntologyLoaderConfiguration。对于配置,我只使用了一个通过无参构造函数创建的配置,我认为这是可以的。对于节点检查器,唯一方便的实现者是TurtleParser,因此我创建了一个TurtleParser,将null作为Reader传递。我认为这将是可以的,因为解析器不会被调用来读取任何内容。然后使用消费者的handle(IRI,IRI,IRI)handle(IRI,IRI,OWLLiteral)方法逐个处理三元组。我们添加这些三元组。
:Tom :likes :Anna
:Tom :age 35

然后再次打印本体以确保已添加断言。由于您已经获取了RDFTriples,因此应该能够提取出handle()需要的参数。在处理三元组之前,本体包含:
<NamedIndividual rdf:about="http://example.org/Tom"/>

然后是这个:
<NamedIndividual rdf:about="http://example.org/Tom">
  <example:age rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">35</example:age>
  <example:likes rdf:resource="http://example.org/Anna"/>
</NamedIndividual>

这里是代码:

import java.io.Reader;

import org.coode.owlapi.rdfxml.parser.OWLRDFConsumer;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyLoaderConfiguration;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.model.OWLOntologyStorageException;

import uk.ac.manchester.cs.owl.owlapi.turtle.parser.TurtleParser;


public class ExampleOWLRDFConsumer {
    public static void main(String[] args) throws OWLOntologyCreationException, OWLOntologyStorageException {
        // Create an ontology.
        OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
        OWLDataFactory factory = manager.getOWLDataFactory();
        OWLOntology ontology = manager.createOntology();

        // Create some named individuals and an object property.
        String ns = "http://example.org/";
        OWLNamedIndividual tom = factory.getOWLNamedIndividual( IRI.create( ns+"Tom" ));
        OWLObjectProperty likes = factory.getOWLObjectProperty( IRI.create( ns+"likes" ));
        OWLDataProperty age = factory.getOWLDataProperty( IRI.create( ns+"age" ));
        OWLNamedIndividual anna = factory.getOWLNamedIndividual( IRI.create( ns+"Anna" ));

        // Add the declarations axioms to the ontology so that the triples involving
        // these are understood (otherwise the triples will be ignored).
        for ( OWLEntity entity : new OWLEntity[] { tom, likes, age, anna } ) {
            manager.addAxiom( ontology, factory.getOWLDeclarationAxiom( entity ));
        }

        // Print the the ontology to see that the entities are declared. 
        // The important result is
        //  <NamedIndividual rdf:about="http://example.org/Tom"/>
        // with no properties
        manager.saveOntology( ontology, System.out );

        // Create an OWLRDFConsumer for the ontology.  TurtleParser implements AnonymousNodeChecker, so 
        // it was a candidate for use here (but I make no guarantees about whether it's appropriate to 
        // do this).  Since it won't be reading anything, we pass it a null InputStream, and this doesn't
        // *seem* to cause any problem.  Hopefully the default OWLOntologyLoaderConfiguration is OK, too.
        OWLRDFConsumer consumer = new OWLRDFConsumer( ontology, new TurtleParser((Reader) null), new OWLOntologyLoaderConfiguration() );

        // The consumer handles (IRI,IRI,IRI) and (IRI,IRI,OWLLiteral) triples.
        consumer.handle( tom.getIRI(), likes.getIRI(), anna.getIRI() );
        consumer.handle( tom.getIRI(), age.getIRI(), factory.getOWLLiteral( 35 ));

        // Print the ontology to see the new object and data property assertions.  The import contents is
        // still Tom: 
        //   <NamedIndividual rdf:about="http://example.org/Tom">
        //     <example:age rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">35</example:age>
        //     <example:likes rdf:resource="http://example.org/Anna"/>
        //  </NamedIndividual>
        manager.saveOntology( ontology, System.out );
    }
}

首先非常感谢您的努力。我认为您稍微误解了我的意图,我想更加精确地说明一下:我得到的三元组是异构的,如果您愿意的话。我从不知道它们描述的是什么类型的关系。在您的示例中,您必须手动创建OWLObjectProperty/OWLDataProperty/... - 类。我的问题是我事先不知道它们是什么,我希望找到一种自动添加它们到现有本体中的方法。如果这不可能,我将不得不回去让JSON生产者将关系类型添加到三元组(然后四元组?)中。 - casualcoder
@casualcoder 我默认它们已经在你的本体中声明了。我在这里包括它们的唯一原因是因为OWLRDFConsumer如果不能确定要断言什么,就无法处理三元组。这里的想法是一旦你拥有了本体,就创建消费者并调用其处理方法。在这个例子中,你可以从本体中加载初始文件,并只使用个体的IRI调用handle。这段代码之所以有声明公理等,仅是为了成为一个最小的工作示例。 - Joshua Taylor
@casualcoder 为了澄清,handle方法只接受IRI,就像我们在你的基于Java的代码中看到的那样。既然你已经在某个地方得到了OWLOntology ontology,那么你只需要使用它(以及TurtleParser和LoaderConfiguration)创建OWLRDFConsumer,然后让你的addTriple()调用consumer的handle()而不是model.add()。 - Joshua Taylor
抱歉,我错了。经过8个小时思考同一件事情后,我的大脑快要爆炸了。 你说得对,我已经在本体论中拥有了所有这些内容,你的答案正是我一直在寻找的。 - casualcoder
@ casualcoder 很高兴听到这个消息!逐个处理OWL三元组要困难得多,因为很多情况都取决于上下文。例如,我们无法在不知道“likes”是注释还是对象属性的情况下处理“Tom likes Anna”这样的语句。然而,基于三元组的处理对于对象和数据类型属性断言来说更加合适,就像我们在这种情况下所做的一样。 - Joshua Taylor
显示剩余2条评论

0
在ONT-API中,它是一个基于Jena的扩展实现的OWL-API,非常简单:
    OWLOntologyManager manager = OntManagers.createONT();
    OWLOntology ontology = manager.createOntology(IRI.create("http://example.com#test"));
    ((Ontology)ontology).asGraphModel().createResource("http://example.com#clazz1").addProperty(RDF.type, OWL.Class);
    ontology.axioms(AxiomType.DECLARATION).forEach(System.out::println);

更多信息请参见ONT-API wiki, examples


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接