// 创建使用OWL语言的内存模型
OntModel ontModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM)
ontModel.read("file:./Creature.owl")// 读取当前路径下的文件,加载模型
// 定义一个类作为模型中Animal类的等等价类,并添加注释
OntClass cls = ontModel.createClass(":DongwuClass")
cls.addComment("the EquivalentClass of Animal...", "EN")
// 通过完整的URI取得模型中的Animal类
OntClass oc = ontModel.
getOntClass("http://www.owl-ontologies.com/marine.owl#Animal")
oc.addEquivalentClass(cls)// 将先前定义的类添加为Animal的等价类
// 迭代显示模型中的类,在迭代过程中完成各种 *** 作
for (Iterator i = ontModel.listClasses()i.hasNext()) {
OntClass c = (OntClass) i.next()// 返回类型强制转换
if (!c.isAnon()) { // 如果不是匿名类,则打印类的名字
System.out.print("Class")
// 获取类的URI并输出,在输出时对URI做了简化(将命名空间前缀省略)
System.out.println(c.getModel().getGraph().
getPrefixMapping().shortForm(c.getURI()))
// 处理Animal类
if (c.getLocalName().equals("Animal")) { // 如果当前类是Animal
System.out.println(" URI@" + c.getURI())// 输出它的完整URI // 取得它的的等价类并打印
System.out.print(" Animal's EquivalentClass is "+
c.getEquivalentClass())
// 输出等价类的注释
System.out.println(" [comments:" +
c.getEquivalentClass().getComment("EN")+"]")
}// 处理Animal结束
// 迭代显示当前类的直接父类
for (Iterator it = c.listSuperClasses()it.hasNext())
{
OntClass sp = (OntClass) it.next()
String str = c.getModel().getGraph()
.getPrefixMapping().shortForm(c.getURI()) // 获取URI
+ "'s superClass is "
String strSP = sp.getURI()
try{ // 另一种简化处理URI的方法
str = str + ":" + strSP.substring(strSP.indexOf('#')+1)
System.out.println(" Class" +str)
}catch( Exception e ){}
} // super class ends
// 迭代显示当前类的直接子类
for (Iterator it = c.listSubClasses()it.hasNext()){
System.out.print(" Class")
OntClass sb = (OntClass) it.next()
System.out.println(c.getModel().getGraph().getPrefixMapping()
.shortForm(c.getURI())+ "'s suberClass is "
+ sb.getModel().getGraph().getPrefixMapping()
.shortForm(sb.getURI()))
}// suber class ends
// 迭代显示与当前类相关的所有属性
for(Iterator ipp = c.listDeclaredProperties()ipp.hasNext()){
OntProperty p = (OntProperty)ipp.next()
System.out.println(" associated property: " + p.getLocalName())
}// property ends
}// anonymity ends
下面以具体试验来说明,由算法生成的大连湾区域土地利用应用本体实例,如图5.42 所示,描述了大连湾地区土地利用方面的信息,包含空间数据和非空间数据的语义信息,图 5.42 是对应土地利用本体的树状结构图。本体构建过程参照 《国家资源环境遥感宏观调查土地资源分类系统》和中国科学院地理科学与资源研究所数据中心土地利用本体分类体系。
当用户提出查找在大连湾东北方向,并位于大连湾50 km 内包含湖泊的所有林地地理实体时,此查询语句较为复杂包括方位关系(大连湾东北方向)、距离关系(大连湾 50km 内)、拓扑关系(林地包含湖泊)和语义关系(林地是有林地、灌木林、疏林地和宜林地的父类)。传统的方法很难实现这种复杂的查询请求,通过创建 DALIAN Region 应用本体就可以很好的解决这种复杂的查询请求。本试验是基于 Jena 和 ArcServer 开发的,首先在服务器端调用编写的本体查询函数(用 Jena 解析),利用应用本体实例中的空间语义关系进行推理。如图 5.42 和图 5.43,“有林地”、“灌木林”、“疏林地”和 “宜林地”是林地的子类,宜林地和草山草坡是同义关系,灌木林和疏林地是林间草地的父类。利用Jena 工具很容易就可以把对林地的查询自动的推理到 “有林地”、“灌木林”、“疏林地”、“宜林地”、“草山草坡”和林间草地中去对空间关系的查询,应用本体中已经描述了拓扑关系(Contain)、方位关系(EastNorth)和距离关系(11.7,36.5)只需要用 Xpath、Xquery 查询语言进行查询转换即可。然后将查询到的 DALIAN Region 土地利用应用本体的结果,组织成 SQL 语句传递给 ArcServer 的 GetFeatureClass 类,由 ArcServer 返回查询结果,在客户端显示。客户端显示的查询结果如彩图 5.1 所示,其中黄色高亮显示的为查询结果。
图 5.43 土地利用应用本体实例(局部)
空间信息的查询与检索是空间信息共享的前提条件。但由于用户认知和概念世界中的概念与系统模型中的概念之间存在语义异质性,用户检索出来的数据往往并不是他们真正想要的。通过建立等价关系、继承关系、逆反关系以及拓扑、方位和距离等空间关系的地理本体并将之用于检索请求可以解决这种语义异质性,从而实现更高级别的检索。在检索处理过程中,以空间数据的属性关系图 ARG 作为描述地理实体空间关系的基础,基于应用本体实例生成算法 AOGA 和语义推理工具 Jena 实现异构消解和语义扩展,极大地提高了检索准确率。以下是本解决方案的优点和将来的工作。
(1)提出了描述空间关系的 ARG 模型,利用 ARG 可以方便地查询任意两个地理实体的空间关系,改进以往空间关系查询时 SQL 扩展的不便性
(2)建立了非空间数据之间的语义关系,可以更全面的检索出所需数据
(3)提出了应用本体实例生成方法,可以较为方便的生成所需应用本体实例作为将来的工作,将集中在以下两点。
(4)建立 ARG 模型时,需花费大量的时间,且容易出错,下一步将研究更自动化的方法建立所需的 ARG。
(5)本体建立层次还较低,只是建立到大类,后续工作,需要在建立地理本体时,建立到具体地理实例一级,要具体到地理实体的名称。
使用 D2R server 默认的数据处理和访问方式浏览 Linked data。该方法很简单,不需要自己写代码,只需要在命令行下面进入 D2R 所在文件路径,执行下面的命令启动 D2R Server:
d2r-server Academic.n3
其中 Academic.n3 即为上一节中生成 Mapping 文件。
然后在 Web 浏览器中访问 http://localhost:2020, 便可以默认的 HTML 浏览器、DF 浏览器以及 SPARQL 查询端对我们的数据进行访问:
图 2. D2R Server 运行的入口页面
图 2. D2R Server 运行的入口页面
从图 2 中可以看出,虽然我们的 schema 一共有五个,但是 D2R Server 在显示时仅生成了四种类资源:HomepagePeople,wikiPeople, paper,以及 author(图 2 第一行),而是将 paper2author 看作是类资源 author 与 Paper 之间的关系。其概念模型如下所示:
图 3. Academic 数据概念模型
图 3. Academic 数据概念模
点击图 2 第一行的 Author,呈现出 5 个作者,如图 4 所示:
图 4. 点击 Author 的 HTML 显示结果
图 4. 点击 Author 的 HTML 显示结果
点击 Author#2,得到 Author#2 的详细属性与关系。如图 5 所示:
图 5. 访问类资源 Author 中标号为 2 的作者 HTML 显示结果
图 5. 访问类资源 Author 中标号为 2 的作者 HTML 显示结果
注意在这里,Paper2Atuhor 被映射成了 Author 的一个关系属性,点击该关系关联的资源“<http://localhost:2020/resource/ZJ.PAPER/1>”,得到 Paper#1 的详细属性与关系,如图 6 所示:
图 6. 访问类资源 Paper 中标号为 1 的论文 HTML 显示结果
图 6. 访问类资源 Paper 中标号为 1 的论文 HTML 显示结果
注意在浏览 Paper 的详细信息时,也可以通过反属性 (is vocab:Paper2Author of) 跳转到相关 Author 的详细信息。
点击图 2 中的类资源 HomepagePeople,再点击 1 号资源,呈现出 James A. Hendler 的 homepage 详细信息,如图 7 所示:
图 7. 访问类资源 HomepagePeople 中标号为 1 的人 HTML 显示结果
图 7. 访问类资源 HomepagePeople 中标号为 1 的人 HTML 显示结果
点击图 2 中的类资源 WikiPeople,再点击 1 号资源,呈现出 James Hendler 的 wikipedia 详细信息,如图 8 所示:
图 8. 访问类资源 WikiPeople 中标号为 1 的人 HTML 显示结果
图 8. 访问类资源 WikiPeople 中标号为 1 的人 HTML 显示结果
使用 Jena API 构建自己的应用
如果需要在 RDF 数据层上构建自己的应用,开发自己的客户端展示方法,就要用到第二种方式,即直接在自己的 Java 工程中通过 Jena/Seasame 的 API 去使用 D2RQ, 这里仅介绍 Jena 的使用方式,Seasame 的使用留给读者自己去实践。
首先需要在你的工程中引用 D2RQ 与 Jena 相关的 jar 包:
将你下载的 D2R server 目录下的 lib/d2rq-0.7.jar 加入你工程的 classpath;
下载 ARQ2.8.1,将其 lib 目录下的所有 jar 包加入你工程的 classpath。
使用 Jena API 可以多种方式调用 D2RQ, 其中最简洁的方式为直接编写 SPARQL 查询语言,其余方式都需要调用 Jena 的封装类,如 Resource,Property, RDFNode 等,需要读者非常熟悉 Jena 的接口,并需要为自己的数据创建相应的 Jena 类对象,因此比较麻烦。本文在此介绍最容易上手也是最灵活的访问方式,SPARQL 查询。
假定我们现在需要构建一个应用,展示所有作者的 name, email 和 paper,因此在 server 端需要提供一个查询类,如清单 2 所示:
清单 2. 使用 Jena API 的 SPARQL 查询
package test
import com.hp.hpl.jena.query.Query
import com.hp.hpl.jen www.hbbz08.com a.query.QueryExecutionFactory
import com.hp.hpl.jena.query.QueryFactory
import com.hp.hpl.jena.query.QuerySolution
import com.hp.hpl.jena.query.ResultSet
import de.fuberlin.wiwiss.d2rq.ModelD2RQ
public class AcademicTest {
public void queryBySPARQL(){
ModelD2RQ m = new ModelD2RQ("file:/D:/Academic.n3")
String SPARQLPrefix = "PREFIX vocab: http://localhost:2020/vocab/resource/"
String SPARQL = SPARQLPrefix +
"SELECT ?name ?email ?paper WHERE {" +
"?author vocab:Name ?name . " +
"?author vocab:Email ?email ." +
"?author vocab:Paper2Author ?paper . }"
Query query = QueryFactory.create(SPARQL)
ResultSet rs = QueryExecutionFactory.create(query, m).execSelect()
while (rs.hasNext()) {
QuerySolution row = rs.nextSolution()
System.out.println("name:"+row.get("name")+",email:"+row.get("email")+",
paper:"+row.get("paper"))
}
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)