参考资料:
web3.0与Semantic Web编程(中文版)
Web 3.0与Semantic Web编程 英文版
随书代码下载
【语义网】【读书笔记】Web 3.0与Semantic Web编程(一)语义Web程序设计简介
【语义网】【读书笔记】Web 3.0与Semantic Web编程(二)语义Web程序设计基础 之 本体与知识建模
【语义网】【读书笔记】Web 3.0与Semantic Web编程(三)查询、推理与语义网应用程序框架设计
Getting started with Apache Jena
Using Jena with Eclipse

目录

  • 1. 概述
  • 2. RDF和Jena RDF API
    • 2.1 核心概念
    • 2.2 相关的Jena Package
    • 2.3 上手实践
      • 2.3.1 创建RDF图
      • 2.3.2 RDF图的输出
      • 2.3.3 RDF图的读取
      • 2.3.4 RDF模型的信息访问(Navigating and Querying)
      • 2.3.5 模型操作
  • 3. Ontology和Jena Ontology API
    • 3.1 载入Onotlogy文件
    • 3.2 保存Ontology文件
    • 3.3 创建Ontology模型
  • 4. 查询与推理

1. 概述


在Jena框架中,不同API之间的交互如上图所示。首先,RDF API是Jena最核心、最基础的API,支持对RDF数据模型的查询、读写等操作。Ontology API是RDF API的一个扩展,以支持本体文件的操作;SPARQL API提供了更复杂的查询接口。Inference API提供了基于规则进行推理的推理引擎。Store API提供了本体的存储。

2. RDF和Jena RDF API

这一节主要参考了官网的两个教程:

  • The RDF API
  • An Introduction to RDF and the Jena RDF API,这个教程也有小伙伴翻译了中文版。

2.1 核心概念

Graphs, models

在Jena中,RDF三元组信息被存储在Model这一数据结构中。Model表示一个RDF图,之所以这样称呼是因为它包含一个RDF节点集合,通过标记关系彼此连接。

Jena API 作用
Model a rich Java API with many convenience methods for Java application developers. 我们通常会更关注Model API。
Graph a simpler Java API intended for extending Jena’s functionality

Nodes: resources, literals and blank nodes

既然RDF是一个图,图中的节点(Nodes)就表示资源(resources)或者值(literals)。

A resource represented as a URI (可以参考这篇文章对URI的解释:What Do URIs Mean Anyway?) denotes a named thing - it has an identity. We can use that identity to refer to directly the resource, as we will see below. Another kind of node in the graph is a literal, which just represents a data value such as the string “ten” or the number 10. Literals representing values other than strings may have an attached datatype, which helps an RDF processor correctly convert the string representation of the literal into the correct value in the computer. By default, RDF assumes the datatypes used XSD are available, but in fact any datatype URI may be used.

Triples and Properties

在RDF图中,由两个节点和连接它们的边组成的关系对称为三元组(Triples),如下图所示。一般来说,三元组表示为(主语,谓语,宾语)(即(Subject, Predicate, Object))的形式。在Jena中,用类Statement表示一个三元组。


根据RDF的标准,只有资源可以作为RDF三元组的主语,而宾语可以是资源或值。因此,提取Statement中相关元素的方法为:

  • getSubject()返回的是Resource
  • getObject()返回的是RDFNode
  • getPredicate()返回的是Property

Namespaces

命名空间(Namespaces)的作用是区分拥有相同名字的URI。比如说,红富士苹果和嘎啦苹果虽然都是苹果,但是它们的品种不同。因此,可以用“红富士”和“嘎啦”两个命名空间进行区分。

2.2 相关的Jena Package

注:org.apache.jena简写为oaj

Package 功能
oaj.jena.rdf.model 是Jena的核心模块,用于创建和复制RDF图。
oaj.riot 用于读写RDF。
oaj.jena.datatypes 提供向Jena描述数据类型的核心接口。可以参考Typed literals how-to
oaj.jena.ontology Abstractions and convenience classes for accessing and manipulating ontologies represented in RDF. 这一部分可以参考后面关于Ontology API介绍的章节。
oaj.jena.rdf.listeners Listening for changes to the statements in a model
oaj.jena.reasoner The reasoner subsystem is supports a range of inference engines which derive additional information from an RDF model. 具体的可以看下面关于推理的小节。
oaj.jena.shared Common utility classes
oaj.jena.vocabulary A package containing constant classes with predefined constant objects for classes and properties defined in well known vocabularies.
oaj.jena.xmloutput Writing RDF/XML.

2.3 上手实践

官网的程序下载

2.3.1 创建RDF图

首先,我们尝试着构建这样的一个RDF图:

Java程序如下:

import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.vocabulary.VCARD;public class createRDF {// some definitionsstatic String personURI = "http://somewhere/JohnSmith";static String fullName = "John Smith";public static void main(String[] args) {// create an empty ModelModel model = ModelFactory.createDefaultModel();// create the resourceResource johnSmith = model.createResource(personURI);// add the propertyjohnSmith.addProperty(VCARD.FN, fullName);}
}

首先定义两个常量表示人和他的名字。接着,创建一个RDF图model,通过Model API中的ModelFactory.createDefaultModel()方法实现。然后,在RDF图中添加一个资源johnSmith,并添加该资源的属性。我们同样可以将资源创建利用更简洁的写法表示:

Resource johnSmith = model.createResource(personURI).addProperty(VCARD.FN, fullName);

这样,我们就完成了一个最简单的额RDF图的构建,该RDF图中只包含一个三元组。接下来,我们来看一下更负责一点的RDF图怎么实现:


实际上程序也十分简单,也是先创建一个空的RDF图,然后添加节点就可以了。

package dealWithRDF;import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.vocabulary.VCARD;public class createRDF {// some definitionsstatic String personURI = "http://somewhere/JohnSmith";static String givenName    = "John";static String familyName   = "Smith";static String fullName     = givenName + " " + familyName;public static void main(String[] args) {// create an empty ModelModel model = ModelFactory.createDefaultModel();// create the resource and add the properties cascading styleResource johnSmith = model.createResource(personURI).addProperty(VCARD.FN, fullName).addProperty(VCARD.N, model.createResource().addProperty(VCARD.Given, givenName).addProperty(VCARD.Family, familyName));}
}

在Jena中,每一个三元组称作一个statement。在上面这个程序中,每一步addProperty的操作就相当于在RDF图中添加了一个statement。为了获得RDF图中的所有statement,我们可以通过StmtIterator中的listStatements()方法得到,并对每一个statement,我们用上述提到的getSubject()getObject()getPredicate()方法得到statementResourceRDFNodeProperty,并输出。

import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.Statement;
import org.apache.jena.rdf.model.StmtIterator;
import org.apache.jena.vocabulary.VCARD;public class createRDF {// some definitionsstatic String personURI = "http://somewhere/JohnSmith";static String givenName    = "John";static String familyName   = "Smith";static String fullName     = givenName + " " + familyName;public static void main(String[] args) {// create an empty ModelModel model = ModelFactory.createDefaultModel();// create the resource and add the properties cascading styleResource johnSmith = model.createResource(personURI).addProperty(VCARD.FN, fullName).addProperty(VCARD.N, model.createResource().addProperty(VCARD.Given, givenName).addProperty(VCARD.Family, familyName));// list the statements in the ModelStmtIterator iter = model.listStatements();// print out the predicate, subject and object of each statementwhile (iter.hasNext()) {Statement stmt = iter.nextStatement(); // get next statementResource subject = stmt.getSubject(); // get the subjectProperty predicate = stmt.getPredicate(); // get the predicateRDFNode object = stmt.getObject(); // get the objectSystem.out.print(subject.toString());System.out.print(" " + predicate.toString() + " ");if (object instanceof Resource) {System.out.print(object.toString());}else {// object id a literalSystem.out.print("\"" + object.toString() + "\"");}System.out.println(".");}}
}

最后的输出为:

http://somewhere/JohnSmith http://www.w3.org/2001/vcard-rdf/3.0#N 41ba8556-85e4-465e-966e-32da92e83951.
http://somewhere/JohnSmith http://www.w3.org/2001/vcard-rdf/3.0#FN "John Smith".
41ba8556-85e4-465e-966e-32da92e83951 http://www.w3.org/2001/vcard-rdf/3.0#Family "Smith".
41ba8556-85e4-465e-966e-32da92e83951 http://www.w3.org/2001/vcard-rdf/3.0#Given "John".

因为RDF图中含有空白节点,空白节点的地址是随机分配的。

2.3.2 RDF图的输出

在Jena中,直接通过model.write(System.out);就可以在Console面板看到输出的RDF模型了,默认采用的是RDF/XML的序列化方式——

<rdf:RDFxmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#"><rdf:Description rdf:about="http://somewhere/JohnSmith"><vcard:N rdf:parseType="Resource"><vcard:Family>Smith</vcard:Family><vcard:Given>John</vcard:Given></vcard:N><vcard:FN>John Smith</vcard:FN></rdf:Description>
</rdf:RDF>

我们同样可以用RDFDataMgr将RDF图通过不同的格式输出:

格式 输出语句 输出
RDF/XML RDFDataMgr.write(System.out, model, Lang.RDFXML);
TURTLE RDFDataMgr.write(System.out, model, Lang.TURTLE);
N-Triples RDFDataMgr.write(System.out, model, Lang.NTRIPLES);

2.3.3 RDF图的读取

我们将上述创建的RDF图保存为vc-db-1.rdf文件,通过输入流完成RDF图的读取。

import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.riot.RDFDataMgr;public class readRDF {static final String inputFileName  = "vc-db-1.rdf";public static void main(String[] args) {// create an empty modelModel model = ModelFactory.createDefaultModel();//use the RDFDataMgr to find the input filesInputStream in = RDFDataMgr.open(inputFileName);if (in == null) {throw new IllegalArgumentException("File:" + inputFileName + " not found");}// read the RDF/XML filemodel.read(in, null);// write it to standard outmodel.write(System.out);}}

2.3.4 RDF模型的信息访问(Navigating and Querying)

基于创建好的模型,我们可以对模型中的一些信息进行访问。(完整代码)

     // retrieve the Adam Smith vcard resource from the modelResource vcard = model.getResource(johnSmithURI);// retrieve the values of the N propertyResource name = (Resource) vcard.getRequiredProperty(VCARD.N).getObject();// retrieve the given name propertyString fullName = vcard.getRequiredProperty(VCARD.FN).getString();// add two nick name properties to vcardvcard.addProperty(VCARD.NICKNAME, "Smith").addProperty(VCARD.NICKNAME, "Adman");// set up the outputSystem.out.println("The nicknames of \"" + fullName + "\" are:");// list the nicknamesStmtIterator iter = vcard.listProperties(VCARD.NICKNAME);while (iter.hasNext()) {System.out.println("    " + iter.nextStatement().getObject().toString());}

给定一个资源的URI,可以使用Model.getResource(String uri)方法检索模型中的资源对象。这个方法会返回一个Resource对象,如果模型中存在,则返回资源,不存在话,创建一个新的资源对象返回。

Resource.getRequiredProperty(Property p)方法可以获取资源的属性。

语句 作用
Resource name = (Resource) vcard.getRequiredProperty(VCARD.N).getObject(); 获得该属性连接的另一个资源。这里是对获取接过进行了强制格式转换,如果已经知道获取到的结果是资源类型,也可以不需要执行强制转换。
String fullName = vcard.getRequiredProperty(VCARD.FN).getString(); 获取属性值

虽然教程中给出了基本的查询方法,但是其查询功能的实现远不如SPARQL强大,这一部分在此就不多介绍了。一般在使用的时候也是以SPARQL为主。

2.3.5 模型操作

Jena提供了三种操作模型的方法——union(求和), intersection(求交集) and difference(求差集)。分别通过.union(Model).intersection(Model).difference(Model)来实现。

3. Ontology和Jena Ontology API

OWL语言被细分为三类——OWL Lite、OWL DL和OWL Full。这三种语言之间的区别和联系可参考这篇文章:OWL本体语言中OWL Lite、OWL DL、OWL Full理解。

为了更好地理解Jena的Ontology API,我们通过一个例子去理解。该例子用到的是ESWC ontology。这个本体提供了一个简单的模型来描述与学术会议相关的概念和活动,其中的一些概念及其之间的关系如下图所示:

3.1 载入Onotlogy文件

可以通过read方法来载入(本地的)本体文件,不同的read方法包括:

  • read( String url )
  • read( Reader reader, String base )
  • read( InputStream reader, String base )
  • read( String url, String lang )
  • read( Reader reader, String base, String Lang )
  • read( InputStream reader, String base, String Lang )

例如:

     OntModel m = ModelFactory.createOntologyModel();File myFile = new File("example.ttl");m.read(new FileInputStream(myFile), "", "TURTLE");

3.2 保存Ontology文件

保存Ontology文件通过write方法来实现,具体的实现方式和read方法类似:

 public static void outprintmodel(Model outmodel, String name) throws IOException {String filepath = name;FileOutputStream fileOS = new FileOutputStream(filepath);
//      RDFWriter rdfWriter = outmodel.getWriter("RDF/XML");
//      rdfWriter.setProperty("showXMLDeclaration","true");
//      rdfWriter.setProperty("showDoctypeDeclaration", "true");
//      rdfWriter.write(model, fileOS, null);//用writer就不需要用下面的方法了outmodel.write(fileOS, "Turtle");fileOS.close();}

3.3 创建Ontology模型

Ontology模型是Jena RDF模型的扩展,提供了处理本体的额外功能。本体模型是通过Jena ModelFactory创建的。最简单的就是通过OntModel m = ModelFactory.createOntologyModel();来创建。这样创建得到的本体默认是OWL-Full语言、内存存储和RDFS推理的。

org.apache.jena.ontology.OntModel是专门处理本体(Ontology)的,他是org.apache.jena.rdf.model.Model的子接口,具有Model的全部功能和一些额外的功能。

如果要创建特定语言的本体,则需要传入不同的参数——createOntologyModel(String languageURI),如果记不住ProfileRegistry,可以直接用ProfileRegistry中的相关参数来实现。

本体语言 ProfileRegistry 传入参数
RDFS http://www.w3.org/2000/01/rdf-schema# ProfileRegistry.RDFS_LANG
OWL Full http://www.w3.org/2002/07/owl# ProfileRegistry.OWL_LANG
OWL DL http://www.w3.org/TR/owl-features/#term_OWLDL ProfileRegistry.OWL_DL_LANG
OWL Lite http://www.w3.org/TR/owl-features/#term_OWLLite ProfileRegistry.OWL_LITE_LANG

createOntologyModel方法同样提供了其他参数的选择——createOntologyModel(OntModelSpec spec),具体的参数值表示了本体的不同配置(如下),可以参考OntModelSpec的文档。

OntModelSpec Language profile Storage model Reasoner
OWL_MEM OWL full in-memory none
OWL_MEM_TRANS_INF OWL full in-memory transitive class-hierarchy inference
OWL_MEM_RULE_INF OWL full in-memory rule-based reasoner with OWL rules
OWL_MEM_MICRO_RULE_INF OWL full in-memory optimised rule-based reasoner with
OWL_MEM_MINI_RULE_INF OWL full in-memory rule-based reasoner with subset of OWL rules
OWL_DL_MEM OWL DL in-memory none
OWL_DL_MEM_RDFS_INF OWL DL in-memory rule reasoner with RDFS-level entailment-rules
OWL_DL_MEM_TRANS_INF OWL DL in-memory transitive class-hierarchy inference
OWL_DL_MEM_RULE_INF OWL DL in-memory rule-based reasoner with OWL rules
OWL_LITE_MEM OWL Lite in-memory none
OWL_LITE_MEM_TRANS_INF OWL Lite in-memory transitive class-hierarchy inference
OWL_LITE_MEM_RDFS_INF OWL Lite in-memory rule reasoner with RDFS-level entailment-rules
OWL_LITE_MEM_RULES_INF OWL Lite in-memory rule-based reasoner with OWL rules
RDFS_MEM RDFS in-memory none
RDFS_MEM_TRANS_INF RDFS in-memory transitive class-hierarchy inference
RDFS_MEM_RDFS_INF RDFS in-memory rule reasoner with RDFS-level entailment-rules

默认的Ontology文件输出时只会包含四个前缀:


和本体构建相关的常用方法总结如下:

功能 方法
定义前缀 setNsPrefix(String prefix, String uri)
创建类 createClass(String uri)
创建实例 createIndividual(String uri, Resource cls)
创建DatatypeProperty createDatatypeProperty(String uri)
创建SubProperty 以DatatypeProperty,先获取相应的DatatypeProperty,然后使用addSubProperty(Property prop)方法。其他的创建子类和子属性的方法类似。
添加三元组 最基本的就是add(s,p,o)方法,在不同情况下有不同的声明实现,具体可以看文档。

4. 查询与推理

基于Jena的查询与推理主要使用的是SPARQL和Jena规则。这两部分应用起来相对比较简单,理论部分主要是这两种语言的语法,这些在官网上都由介绍。关于SPARQL的介绍,可以看我的另外的一篇笔记——SPARQL——语义网的查询语言。关于查询、推理和语义网框架的设计,可以看另一篇文章。

【语义网】Jena框架简介及实战相关推荐

  1. 语义网简介(非应用)

    语义网 简介 语义网(Semantic Web)的核心是:通过给万维网上的文档(如: HTML)增加能够被计算机所理解的语义(Meta data),从而使整个互联网成为一个通用的信息交换媒介.换言之, ...

  2. 最新后盾网Laravel框架重入门到实战 Laravel博客项目实战 陈华主讲 包含课件源码

    老师介绍 陈华,PHP明星讲师,大学生演讲网创始人,2010年开始开发整站项目,精通Laravel,Yii框架. 简 介 本套课程是一套以项目实战为主的Laravel5.2实战开发教程,是真正意义上的 ...

  3. 《HiWind企业快速开发框架实战》(0)目录及框架简介

    <HiWind企业快速开发框架实战>(0)目录及框架简介 本系列主要介绍一款企业管理系统快速开发框架,该框架旨在快速完成企业管理系统,并实现易维护可移植的目标. 使用逐个系统模块进行编码的 ...

  4. 语义网络与知识图谱(二)知识表示(谓词逻辑产生式规则表示框架表示语义网表示XMLRDFOWL

    知识表示:用计算机符号来描述人脑中的知识,以及通过符号之间的运算来模拟人脑的推理过程. 语义网核心:RDF OWL 知识表示方法  一阶谓词逻辑表示法  产生式规则表示法  框架表示法  语义 ...

  5. SHU语义网与知识图谱

    SHU语义网与知识图谱 文章目录 SHU语义网与知识图谱 前言 课程笔记 第一讲:语义网概述 第二讲:RDF和RDFs RDF部分 RDFs及其形式语义 第三讲:本体论与OWL语言 本体论 OWL语言 ...

  6. 从本体论到知识图谱, 著名学者Pascal Hitzler长文回顾语义网20年发展

    作者:Pascal Hitzler(堪萨斯州立大学计算机科学系教授,著名语义网技术专家) 原文:A Review of the Semantic Web Field,Communications of ...

  7. 黄智生博士谈语义网与Web 3.0

    作者 黄智生,采访: 徐涵 发布于 2009年3月26日 下午6时0分 社区 Architecture, SOA 主题 语义网 标签 Web 2.0, 采访, 元数据, 语义网 近 两年来," ...

  8. 【笔记-node】《Egg.js框架入门与实战》、《用 React+React Hook+Egg 造轮子 全栈开发旅游电商应用》

    20210226-20210227:<Egg.js框架入门与实战> 课程地址:https://www.imooc.com/learn/1185 第一章 课程导学 01-01 课程介绍 一. ...

  9. Django框架简介

    Django框架简介 MVC框架和MTV框架 MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View) ...

  10. Apache Shiro权限控制框架简介

    Apache Shiro权限控制框架简介 要想实现权限控制,可以自己写代码实现,蓄力都的权限控制可以通过过滤器Filter实现,细粒度的权限控制是基于代理对象结合自定义的注解和反射技术来实现,反射技术 ...

最新文章

  1. 寿光一中2021年高考成绩查询,2021年寿光市高考状元名单资料,今年寿光市高考状元多少分...
  2. ffmpeg文件拼接
  3. mybatis 中#与$的区别
  4. jquery each函数的使用
  5. 10分钟写一个markdown编辑器
  6. Python 技术篇-利用pymouse库操作windows系统电脑实现鼠标指针移动、点击
  7. 建设世界级数据中心正当时
  8. 【直播回放】100分钟全面剖析图像分割任务,学习CV必知
  9. 笔记-知识产权与标准化知识-GB/T-12504-1990计算机软件质量保证计划规范
  10. Js判断下拉框是否为空值
  11. Razor Engine,动态脚本语言,mvc上的语法,适用于文件内容生成,静态网页生成等。...
  12. 多个asp.net程序共用Session(sso程序的外设接口)
  13. 【牛客 - 370 I 】Rinne Loves Xor(按位前缀和,异或)
  14. SQL Server 关联
  15. java 路径中代替斜杠_老生常谈java路径中的反斜杠和斜杠的区别
  16. Ubuntu安装Apache+PHP
  17. 一次完整的http请求过程
  18. 动态规划经典入门题(初学必刷)
  19. window安全中心关闭防火墙后仍然会将xx文件删除的解决办法
  20. 数据包络分析--SBM模型(第一篇)

热门文章

  1. android-player 本地服务器联调
  2. U盘里的文件夹以应用程序的方式出现-文件夹伪装病毒
  3. DSP开发的一点概念
  4. [RK356x] [Firefly-Ubuntu] 1min教你在Ubuntu系统安装GCC开发工具
  5. 小米路由 php 服务器地址,小米路由器ip地址能改吗 小米路由器ip地址修改-192路由网...
  6. 记录帖-电脑版微信多开
  7. 打造自己备份的系统镜像
  8. Java实现仿win10计算器——微升级版
  9. Python Django 添加首页尾页上一页下一页代码实例
  10. 基于回声状态网络(ESN)的时间序列预测