知识图谱-Ontology应用建模实例:紧急联动的一个简单建模
title: Ontology应用建模实例
tags: Ontology,知识图谱,小书匠
grammar_cjkRuby: true
[toc]
紧急联动的一个简单建模
UML模型(应急联动机构)
Ontology模型
<?xml version="1.0" encoding="GB2312"?>
<rdf:RDF
xmlns ="http://gis.pku.edu.cn/应急联动机构#"
xmlns: 应急联动机构="http://www.example.org/应急联动机构#"
xmlns:owl ="http://www.w3.org/2002/07/owl#"
xmlns:rdf ="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:xsd =http://www.w3.org/2000/10/XMLSchema#>
<owl:Ontology rdf:about=" http://gis.pku.edu.cn/应急联动机构">
<rdfs:comment>中国城市应急联动机构的Ontology</rdfs:comment>
<owl:versionInfo>
$Id: test.html,v 1.0 2003/03/20 22:22:00 Lxp $
</owl:versionInfo>
</owl:Ontology>
<owl:Class rdf:ID="&应急联动机构;联动单位"/ >
<owl:Class rdf:ID="&应急联动机构;消防局:">
<rdfs:subClassOf rdf:resource="&应急联动机构;联动单位"/>
</owl:Class>
<owl:Class rdf:ID="&应急联动机构;联动单位调度中心"/ >
<owl:Class rdf:ID="&应急联动机构;处置力量分支"/ >
<owl:Class rdf:ID="&应急联动机构;消防指挥调度中心:">
<rdfs:subClassOf rdf:resource="&应急联动机构;联动单位调度中心"/>
</owl:Class>
<owl:Class rdf:ID="&应急联动机构;消防支队:">
<rdfs:subClassOf rdf:resource="&应急联动机构;处置力量分支"/>
</owl:Class>
<owl:Class rdf:ID="&应急联动机构;处置力量部门"/ >
<owl:Class rdf:ID="&应急联动机构;消防中队:">
<rdfs:subClassOf rdf:resource="&应急联动机构; 处置力量部门"/>
</owl:Class>
<owl:Class rdf:ID="&应急联动机构;消防车"/ >
<owl:ObjectProperty rdf:ID="&应急联动机构;包含中心">
<rdf:type rdf:resource="&owl;FunctionalProperty" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含分支">
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含联动调度中心">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含中心"/>
<rdfs:domain rdf:resource="&应急联动机构;联动单位" />
<rdfs:range rdf:resource="&应急联动机构;联动单位调度中心" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含力量分支">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含分支"/>
<rdfs:domain rdf:resource="&应急联动机构;联动单位" />
<rdfs:range rdf:resource="&应急联动机构;处置力量分支" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含力量部门">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含分支"/>
<owl:allValuesFrom rdf:resource="&应急联动机构;处置力量部门"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含消防调度中心">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含中心"/>
<rdfs:domain rdf:resource="&应急联动机构;消防局" />
<rdfs:range rdf:resource="&应急联动机构;消防指挥调度中心" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含消防支队">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含分支"/>
<rdfs:domain rdf:resource="&应急联动机构;消防局" />
<rdfs:range rdf:resource="&应急联动机构;消防支队" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含中队">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含分支"/>
<owl:allValuesFrom rdf:resource="&应急联动机构;消防中队"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含车">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含分支"/>
<rdfs:domain rdf:resource="&应急联动机构;消防中队" />
<rdfs:range rdf:resource="&应急联动机构;消防车" />
</owl:ObjectProperty>
</rdf:RDF>
一个比较复杂的应急联动的建模
UML模型
Ontology模型
<?xml version="1.0" encoding="GB2312"?>
<rdf:RDF
xmlns ="http://gis.pku.edu.cn/应急联动机构#"
xmlns: 应急联动机构="http://www.example.org/应急联动机构#"
xmlns:owl ="http://www.w3.org/2002/07/owl#"
xmlns:rdf ="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:xsd =http://www.w3.org/2000/10/XMLSchema#>
<owl:Ontology rdf:about=" http://gis.pku.edu.cn/应急联动机构">
<rdfs:comment>中国城市应急联动机构的Ontology</rdfs:comment>
<owl:versionInfo>
$Id: test.html,v 1.1 2003/03/21 13:28:00 Lxp $
</owl:versionInfo>
</owl:Ontology>
<owl:Class rdf:ID="&应急联动机构;联动单位"/ >
<owl:Class rdf:ID="&应急联动机构;消防局:">
<rdfs:subClassOf rdf:resource="&应急联动机构;联动单位"/>
</owl:Class>
<owl:Class rdf:ID="&应急联动机构;联动单位调度中心"/ >
<owl:Class rdf:ID="&应急联动机构;处置力量分支"/ >
<owl:Class rdf:ID="&应急联动机构;处置力量编组"/ >
<owl:Class rdf:ID="&应急联动机构;消防指挥调度中心:">
<rdfs:subClassOf rdf:resource="&应急联动机构;联动单位调度中心"/>
</owl:Class>
<owl:Class rdf:ID="&应急联动机构;消防支队:">
<rdfs:subClassOf rdf:resource="&应急联动机构;处置力量分支"/>
</owl:Class>
<owl:Class rdf:ID="&应急联动机构;处置力量部门"/ >
<owl:Class rdf:ID="&应急联动机构;消防中队">
<rdfs:subClassOf rdf:resource="&应急联动机构; 处置力量部门"/>
</owl:Class>
<owl:Class rdf:ID="&应急联动机构;消防车组">
<rdfs:subClassOf rdf:resource="&应急联动机构; 处置力量编组"/>
</owl:Class>
<owl:Class rdf:ID="&应急联动机构;消防车"/ >
<owl:Class rdf:ID="&应急联动机构;联动单位调度员"/ >
<owl:Class rdf:ID="&应急联动机构;值班主任">
<rdfs:subClassOf rdf:resource="&应急联动机构;联动单位调度员"/>
</owl:Class>
<owl:Class rdf:ID="&应急联动机构;处置部门调度员"/ >
<owl:Class rdf:ID="&应急联动机构;编组信息员"/ >
<owl:Class rdf:ID="&应急联动机构;调度单"/ >
<owl:Class rdf:ID="&应急联动机构;接警单"/ >
<owl:Class rdf:ID="&应急联动机构;消防调度单">
<rdfs:subClassOf rdf:resource="&应急联动机构;调度单"/>
</owl:Class>
<owl:Class rdf:ID="&应急联动机构;通讯员">
<rdfs:subClassOf rdf:resource="&应急联动机构; 编组信息员"/>
</owl:Class>
<owl:Class rdf:ID="&应急联动机构;电话员">
<rdfs:subClassOf rdf:resource="&应急联动机构; 处置部门调度员"/>
</owl:Class>
<owl:Class rdf:ID="&应急联动机构;消防调度员"/ >
<owl:Class rdf:ID="&应急联动机构; 值班班长">
<rdfs:subClassOf rdf:resource="&应急联动机构; 消防调度员"/>
</owl:Class>
<owl:Class rdf:ID="&应急联动机构;消防调度机"/ >
<owl:Class rdf:ID="&应急联动机构;调度机"/ >
<owl:Class rdf:ID="&应急联动机构;决策指挥中心"/ >
<owl:Class rdf:ID="&应急联动机构;决策指挥员"/ >
<owl:Class rdf:ID="&应急联动机构;决策指挥机"/ >
<owl:Class rdf:ID="&应急联动机构;应急联动中心"/ >
<owl:Class rdf:ID="&应急联动机构;综合调度员"/ >
<owl:Class rdf:ID="&应急联动机构;综合调度机"/ >
<owl:Class rdf:ID="&应急联动机构;接警员"/ >
<owl:Class rdf:ID="&应急联动机构;报警人"/ >
<owl:Class rdf:ID="&应急联动机构;接警机"/ >
<owl:Class rdf:ID="&应急联动机构;报警装置"/ >
<owl:ObjectProperty rdf:ID="&应急联动机构;包含中心">
<rdf:type rdf:resource="&owl;FunctionalProperty" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含分支">
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含人员">
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含调度员">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含人员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含设备">
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含调度机">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含设备"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含联动调度中心">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含中心"/>
<rdfs:domain rdf:resource="&应急联动机构;联动单位" />
<rdfs:range rdf:resource="&应急联动机构;联动单位调度中心" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含力量分支">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含分支"/>
<rdfs:domain rdf:resource="&应急联动机构;联动单位" />
<rdfs:range rdf:resource="&应急联动机构;处置力量分支" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含力量部门">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含分支"/>
<owl:allValuesFrom rdf:resource="&应急联动机构;处置力量部门"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含消防调度中心">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含中心"/>
<rdfs:domain rdf:resource="&应急联动机构;消防局" />
<rdfs:range rdf:resource="&应急联动机构;消防指挥调度中心" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含消防支队">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含分支"/>
<rdfs:domain rdf:resource="&应急联动机构;消防局" />
<rdfs:range rdf:resource="&应急联动机构;消防支队" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含中队">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含分支"/>
<owl:allValuesFrom rdf:resource="&应急联动机构;消防中队"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含车组">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含分支"/>
<rdfs:domain rdf:resource="&应急联动机构;消防中队" />
<rdfs:range rdf:resource="&应急联动机构;消防车组" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含车">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含分支"/>
<rdfs:domain rdf:resource="&应急联动机构;消防车组" />
<rdfs:range rdf:resource="&应急联动机构;消防车" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含信息员">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含人员"/>
<rdfs:domain rdf:resource="&应急联动机构;处置力量编组" />
<rdfs:range rdf:resource="&应急联动机构;编组信息员" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含部门调度员">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含调度员"/>
<rdfs:domain rdf:resource="&应急联动机构;处治力量部门" />
<rdfs:range rdf:resource="&应急联动机构;处置部门调度员" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含主任">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含人员"/>
<rdfs:domain rdf:resource="&应急联动机构;消防车组" />
<rdfs:range rdf:resource="&应急联动机构;消防车" />
<owl:cardinality>1</owl:cardinality>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含综合调度员">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含调度员"/>
<rdfs:domain rdf:resource="&应急联动机构;应急联动中心"/>
<rdfs:range rdf:resource="&应急联动机构;综合调度员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含综合调度机">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含调度机"/>
<rdfs:domain rdf:resource="&应急联动机构;应急联动中心"/>
<rdfs:range rdf:resource="&应急联动机构;综合调度机"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含接警员">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含人员"/>
<rdfs:domain rdf:resource="&应急联动机构;应急联动中心"/>
<rdfs:range rdf:resource="&应急联动机构;接警员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含接警机">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含设备"/>
<rdfs:domain rdf:resource="&应急联动机构;应急联动中心"/>
<rdfs:range rdf:resource="&应急联动机构;接警机"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含指挥员">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含人员"/>
<rdfs:domain rdf:resource="&应急联动机构;抉择指挥中心"/>
<rdfs:range rdf:resource="&应急联动机构;决策指挥员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含指挥机">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含设备"/>
<rdfs:domain rdf:resource="&应急联动机构;抉择指挥中心"/>
<rdfs:range rdf:resource="&应急联动机构;决策指挥机"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含消防调度员">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含调度员"/>
<rdfs:domain rdf:resource="&应急联动机构;消防指挥调度中心"/>
<rdfs:range rdf:resource="&应急联动机构;消防调度员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含消防调度机">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含调度机"/>
<rdfs:domain rdf:resource="&应急联动机构; 消防指挥调度中心"/>
<rdfs:range rdf:resource="&应急联动机构; 消防调度机"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含班长">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含人员"/>
<rdfs:domain rdf:resource="&应急联动机构;消防指挥调度中心"/>
<rdfs:range rdf:resource="&应急联动机构;值班班长"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含电话员">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含人员"/>
<rdfs:domain rdf:resource="&应急联动机构;消防中队"/>
<rdfs:range rdf:resource="&应急联动机构;电话员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;包含通讯员">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;包含人员"/>
<rdfs:domain rdf:resource="&应急联动机构;消防车组"/>
<rdfs:range rdf:resource="&应急联动机构;通讯员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;报警">
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;装置报警">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;报警"/>
<rdfs:domain rdf:resource="&应急联动机构;报警装置"/>
<rdfs:range rdf:resource="&应急联动机构;接警员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;人员报警">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;报警"/>
<rdfs:domain rdf:resource="&应急联动机构;报警人"/>
<rdfs:range rdf:resource="&应急联动机构;接警员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;设备报警">
<rdfs:subPropertyOf rdf:resource="&应急联动机构;报警"/>
<rdfs:domain rdf:resource="&应急联动机构;报警机"/>
<rdfs:range rdf:resource="&应急联动机构;接警员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;使用">
<rdfs:domain rdf:resource="&应急联动机构;报警员"/>
<rdfs:range rdf:resource="&应急联动机构;消防调度员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;电话指令下达">
<rdfs:domain rdf:resource="&应急联动机构;消防调度员"/>
<rdfs:range rdf:resource="&应急联动机构;电话员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;指挥通讯员">
<rdfs:domain rdf:resource="&应急联动机构;消防调度员"/>
<rdfs:range rdf:resource="&应急联动机构;通讯员 "/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;调度现场情况汇报">
<rdfs:domain rdf:resource="&应急联动机构;通讯员"/>
<rdfs:range rdf:resource="&应急联动机构; 消防调度员 "/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;填写调度情况">
<rdfs:domain rdf:resource="&应急联动机构;消防调度员"/>
<rdfs:range rdf:resource="&应急联动机构;消防调度单"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;出动命令">
<rdfs:domain rdf:resource="&应急联动机构;电话员"/>
<rdfs:range rdf:resource="&应急联动机构;通讯员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;指挥中队">
<rdfs:domain rdf:resource="&应急联动机构;消防指挥调度中心"/>
<rdfs:range rdf:resource="&应急联动机构;消防车组"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;填写报警情况">
<rdfs:domain rdf:resource="&应急联动机构;报警员"/>
<rdfs:range rdf:resource="&应急联动机构;报警单"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;指挥编组">
<rdfs:domain rdf:resource="&应急联动机构;联动单位调度中心"/>
<rdfs:range rdf:resource="&应急联动机构;处置力量编组"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;处置指令下达">
<rdfs:domain rdf:resource="&应急联动机构;联动单位调度员"/>
<rdfs:range rdf:resource="&应急联动机构;处置部门调度员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;出动命令">
<rdfs:domain rdf:resource="&应急联动机构;联动单位调度员"/>
<rdfs:range rdf:resource="&应急联动机构;调度单"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;指挥信息员">
<rdfs:domain rdf:resource="&应急联动机构;联动单位调度员"/>
<rdfs:range rdf:resource="&应急联动机构;编组信息员"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="&应急联动机构;编组现场情况汇报">
<rdfs:domain rdf:resource="&应急联动机构;编组信息员"/>
<rdfs:range rdf:resource="&应急联动机构;联动单位调度员 "/>
</owl:ObjectProperty>
</rdf:RDF>
Jena——基于w3c的RDF、DAML/OIL进行语义网建模的Java API
简介——几个RDF建模的实例
给出下面的RDF有向图:
其中,椭圆中的URI给出了一个resource,有向边给出了该resource的一个property:FN(Full Name)。vcard是一个命名空间的前缀。该property的值在方框中给出,是一个literral类型的“John Smith”。
Jena一组能够用来创建和操纵诸如此种类型的有向图的Java API。Jena用对象类来表示图、resource、property和literal,用于表达后三者的接口分别叫做Resource、Property和Literal,而图被表示为一个model。用于创建上面的图的代码如下:
// some definitions
static String personURI = "http://somewhere/JohnSmith";
static String fullName = "John Smith";
// create an empty graph
Model model = new ModelMem();
// create the resource
Resource johnSmith = model.createResource(personURI);
// add the property
johnSmith.addProperty(VCARD.FN, fullName);
ModelMem是实现了接口Model的类。Jena还包括了其他用于实现Model的类,它们可以被存储在Berklay的DB数据库以及关系数据库中。VCARD是一个常数类,里面定义了所有VCARD Schema的常数。Jena还提供了其他常数类,如RDF、RDF Schema、Dublin Core 和DAML。其中,创建resource和添加property的两条语句可以被压缩为下面的一句:
Resource johnSmith =
model.createResource(personURI)
.addProperty(VCARD.FN, fullName);
下面给出了在例一的基础上得到的一个相对复杂的有向图: ![enter description here][4]
与上面不同的是,vcard:N属性以一个resource作为它的值,而该resource没有名字,称作一个空结点(blank Node)。 下面是Jena的创建代码:
// some definitions
String personURI = "http://somewhere/JohnSmith";
String givenName = "John";
String familyName = "Smith";
String fullName = givenName + " " + familyName;
// create an empty graph
Model model = new ModelMem();
// create the resource
// and add the properties cascading style
Resource johnSmith
= model.createResource(personURI)
.addProperty(VCARD.FN, fullName)
.addProperty(VCARD.N,
model.createResource()
.addProperty(VCARD.Given, givenName)
.addProperty(VCARD.Family, familyName));
Jena与整个建模流程
陈述(statement)
如上面的两个例子所示,RDF有向图中的每条边就是一个陈述,它肯定了resource的一个事实。一个陈述包含三个部分:
- subject,即有向边离开的resource;
- predicate,即带标记的有向边;
- object,有向边指向的resource或者literal。
所以陈述又叫做三元组。 一个RDF有向图包含了一系列的陈述(statement),他是陈述的集合,所以重复的陈述可以被加进一个图中。Jena的model接口提供了一个listStatements()方法用于得到一个在这个集合上的迭代器,它的返回类型为Statement。Statement接口提供了用于访问该陈述的subject、predicate和object的方法。一个例子如下:
// list the statements in the graph
StmtIterator iter = model.listStatements();
// print out the predicate, subject and object of each statement
while (iter.hasNext()) {
Statement stmt = iter.next(); // get next statement
Resource subject = stmt.getSubject(); // get the subject
Property predicate = stmt.getPredicate(); // get the predicate
RDFNode object = stmt.getObject(); // get the object
System.out.print(subject.toString());
System.out.print(" " + predicate.toString() + " ");
if (object instanceof Resource) {
System.out.print(object.toString());
} else {
// object is a literal
System.out.print(" \"" + object.toString() + "\");
}
System.out.println(" .");
}
由于object可以为一个resource或者一个literal,所以getObject()方法返回一个类型为RDFNode的对象,该类是resource和literal的公共超类。
书写RDF
Jena提供了用XML格式读写RDF的方法,这就使得我们能够将一个RDF model存为一个文件并在以后将它读出来。
下面的代码片断给出了如何将一个model存入文件的方法:
// now write the model in XML form to a file
model.write(new PrintWriter(System.out));
即调用model的write方法通过一个PrintWriter写入文件中。
对于上面的例子,调用这样的输入语句可能得到下面的输出结果:
<rdf:RDF
xmlns: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:FN>John Smith</vcard:FN>
<vcard:N rdf:resource='#A0'/>
</rdf:Description>
<rdf:Description rdf:about='#A0'>
<vcard:Given>John</vcard:Given>
<vcard:Family>Smith</vcard:Family>
</rdf:Description>
</rdf:RDF>
不过该表达并不完全与我们上面给出的例子相符。在XML表达中不能描述一个空的节点,在原图中的空结点被赋予了一个URI。
Jena还提供了扩展接口用于支持可插入的新的writer来序列化RDF。上面使用的是标准的“dumb”writer,Jena还支持一个更为成熟的RDF/XML writer:
// now write the model in XML form to a file
model.write(new PrintWriter(System.out), "RDF/XML-ABBREV");
这个writer也叫做PrettyWriter,它能够使用RDF/XML feature的缩写语法更为紧凑的将一张图输出到文件。它同时也支持空结点。但是对于很大的图则不太适用,因为这样做的性能不能接收。要想输出很大的文件并且维持空结点,则使用N-Triples格式:
// now write the model in XML form to a file
model.write(new PrintWriter(System.out), "N-TRIPLE");
读取RDF
下面的代码给出了用于读取一个RDF文件并且将它另外写回的方法:
// create an empty model
Model model = new ModelMem();
// use the class loader to find the input file
InputStream in = Tutorial05.class
.getClassLoader()
.getResourceAsStream(inputFileName);
if (in == null) {
throw new IllegalArgumentException(
"File: " + inputFileName + " not found");
}
// read the RDF/XML file
model.read(new InputStreamReader(in), "");
// write it to standard out
model.write(new PrintWriter(System.out));
其中,read方法的第二个参数应该是相对的URI,因为这里没有引用相对URI,所以可以为空。
关于Jena的RDF包
- 语义网应用开发人员使用Jena时的最重要的包是com.hp.hpl.mesa.rdf.jena.model。这个包包含了用于表达model、resource、property、literal、statements以及其他RDF的关键的接口;
- com.hp.hpl.mesa.rdf.jena.tutorial包包含了与Jena一同发布的指南中所使用的例子的源代码;
- com.hp.hpl.mesa.rdf.jena.mem包包含了用于将整个模型状态装入内存的Jena API的实现。凡是创建基于内存的模型(最典型的是创建ModelMem类的实例)的实现都在本包中;
- com.hp.hpl.mesa.rdf.jena.common包包含了对于诸多实现通用的实现类。例如,它定义了类ResourceImpl, PropertyImpl, LiteralImpl。开发者一般不要直接使用这里的方法,例如不直接使用ResourceImpl,而使用createResource方法。这是为了保证在实现发生优化后不需要进行类型转换;
- com.hp.hpl.jena.rdf为RDF包。
在RDF有向图中的导航
给出一个resource的URL,可以使用Model.getResource(String uri)方法从图中得到该资源所对应的对象。如果对应的resource存在,则返回该resource的对象,否则将创建一个新的对象。例如:
// retrieve the John Smith vcard resource from the model
Resource vcard = model.getResource(johnSmithURI);
Resource接口定义了一系列方法用于访问一个Resource的Property。Resource.getProperty(Property p)方法用于访问一个resource的一个property。同以往的Java API不同的是该方法返回的是整个Statement对象,然后通过该对象的访问方法来得到Property的值。例如想得到vcard:N这个property的值所对应的resource,代码如下:
// retrieve the value of the N property
Resource name = (Resource) vcard.getProperty(VCARD.N)
.getObject();
由于property的值可能为resource或者literal,而我们已经知道上面得到的值为resource,所以进行了强制类型转换。Jena也提供了特定类型的访问方法,从而不需要在编译时进行类型转换。所以上面的代码也可以写成:
// retrieve the value of the FN property
Resource name = vcard.getProperty(VCARD.N)
.getResource();
类似,如果property的值为literal,则可以写成:
// retrieve the given name property
String fullName = vcard.getProperty(VCARD.FN)
.getString();
上面的property VCARD.FN只有一个,但RDF允许一个resource有重复的property。例如Adam可能有多于一个的nickname:
// add two nick name properties to vcard
vcard.addProperty(VCARD.NICKNAME, "Smithy")
.addProperty(VCARD.NICKNAME, "Adman");
当调用getProperty方法时,Jena并没有定义要返回哪一个property,所以vcard.getProperty(VCARD.NICKNAME)的结果是不确定的。Jena只是返回其中任意一个,但并不保证连续两条调用都有可能返回同一个值。
这样,当proeprty连续出现时,可以使用Resource.listProperties(Property p)方法来得到一个迭代器从而列举出它们。例如下面的代码能够列举出上面添加的nickname:
// set up the output
System.out.println("The nicknames of \""
+ fullName + "\" are:");
// list the nicknames
StmtIterator iter = vcard.listProperties(VCARD.NICKNAME);
while (iter.hasNext()) {
System.out.println(" " + iter.next()
.getObject()
.toString());
}
该代码的输出结果是:
The nicknames of "John Smith" are:
Smithy
Adman
关于图的查询
Jena核心只是提供了有限的查询元语。另外对RDF还有更为强大的RDQL查询语言。 Model.listStatements()方法用于列举一个model中的所有statement,可能是最为原始的对一个model的查询。该查询不适于在很大的图上面做查询。Model.listSubjects()方法类似,只是返回在所有有property的resource上的迭代器。Model.listSubjectsWithProperty(Property p, RDFNode o)则返回所有在property p上有值o的resource的迭代器。例如:
// retrieve all resource of type Vcard.
ResIterator iter = model.listSubjectsWithProperty(RDF.type, VCARD.Vcard);
如果我们使用的vcard schema并没有为vcard定义一个类型,那我们可以假定只有类型为vcard的resource有property vcard:FN,而且在我们的数据中,所有这样的resource都有一个这样的property,那我们可以这样进行查询:
// list vcards
ResIterator iter = model.listSubjectsWithProperty(VCARD.FN);
while (iter.hasNext()) {
Resource r = iter.next();
...
}
所有上面的查询都基于这样一个查询元语:model.listStatements(Selector s)。该方法返回建立在经过s选择得到的statement上的迭代器。Selector被定义为可扩展的,目前只有一个实现:com.hp.hpl.mesa.rdf.jena.common包中的SelectorImpl类。SelectorImpl构造函数有三个参数:
Selector selector = new SelectorImpl(subject, predicate, object)
显然它返回匹配参数给出的三元组的statement。如果在这三个参数的位置上任意一个为null,则认为匹配所有。所以
Selector selector = new SelectorImpl(null, null, null);
返回一张图中的所有statement。
Selector selector = new SelectorImpl(null, VCARD.FN, null);
返回满足predicate为VCARD.FN的statement而不论其他两个参数的值为什么。以下的代码列出了数据库中所有vcard的full name:
// select all the resources with a VCARD.FN property
ResIterator iter = model.listSubjectsWithProperty(VCARD.FN);
if (iter.hasNext()) {
System.out.println("The database contains vcards for:");
while (iter.hasNext()) {
System.out.println(" " + iter.next()
.getProperty(VCARD.FN)
.getString());
}
} else {
System.out.println("No vcards were found in the database");
}
输出结果可以是:
The database contains vcards for:
Sarah Jones
John Smith
Matt Jones
Becky Smith
下面的例子是采用SelectorImpl来实现查询的例子:
// select all the resources with a VCARD.FN property
// whose value ends with "Smith"
StmtIterator iter = model.listStatements(
new
SelectorImpl(null, VCARD.FN, (RDFNode) null) {
public boolean selects(Statement s) {
try {
return s.getString()
.endsWith("Smith");
} catch (RDFException e) {
throw new RDFError(e);
}
}
});
以上的代码使用了Java的内置代理方法定义技术。其中select方法确保full name以“Smith”结束,而该过滤只是对subject起作用。
以下的两段代码可被认为是有着相同的功能:
【1】
// do all filtering in the selects method
StmtIterator iter = model.listStatements(
new
SelectorImpl(null, null, (RDFNode) null) {
public boolean selects(Statement s) {
try {
return (subject == null || s.getSubject().equals(subject))
&& (predicate == null || s.getPredicate().equals(predicate))
&& (object == null || s.getObject().equals(object))
} catch (RDFException e) {
throw new RDFError(e);
}
}
});
【2】
StmtIterator iter =
model.listStatements(new SelectorImpl(subject, predicate, object)
前者列出图中所有的statement而后依次测试之,而后者允许使用应用实现本身维护的索引来提高性能。
对图的操作
Jena提供了3种针对图这一整体进行的操作——即典型的集合操作:并(union)、叫(intersection)和差(different)。 对两张图取并就是对两张图所包含的statement取并,这是为了支持RDF所给出的一个关键操作,它使得不同数据源的数据能够被合并。给出下面的两张图:
![enter description here][5]
它们可以被合并为:
上面的操作的代码是:
// read the RDF/XML files
model1.read(new InputStreamReader(in1), "");
model2.read(new InputStreamReader(in2), "");
// merge the graphs
Model model = model1.union(model2);
// print the graph as RDF/XML
model.write(new PrintWriter(System.out), "RDF/XML-ABBREV");
生成的RDF为:
<?xml version='1.0'?>
<rdf:RDF
xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
xmlns:RDFNsId1='http://www.w3.org/2001/vcard-rdf/3.0#'>
<rdf:Description rdf:about='http://somewhere/JohnSmith/'>
<RDFNsId1:N
RDFNsId1:Given='John'
RDFNsId1:Family='Smith'/>
<RDFNsId1:FN>John Smith</RDFNsId1:FN>
<RDFNsId1:EMAIL
rdf:value='John@somewhere.com'
rdf:type='http://www.w3.org/2001/vcard-rdf/3.0#internet'/>
</rdf:Description>
</rdf:RDF>
交和差操作与此类似。
相关异常
目前Jena的异常机制不很受欢迎,它将在将来得到改进。由于Jena被设计成具有很高的灵活性并且支持不同的存储系统,所以存储管理器可以在任何时候给出一个非预期的错误。所以几乎所有的Jena方法在结尾都要注明要抛出RDFException异常。经验证明这不是一个好方法,当抛出异常时,通常这些异常都应该被忽略,检查出这些异常没有任何好处。
容器(Containers)
RDF给出了表达事物集合的特殊类型的resource。这些resource叫做容器。容器的成员或者是resource,或者是literal。共有3类容器:
- BAG是一个无序的容器;
- ALT是一个用于表达选择的无序的容器;
- SEQ是一个有序的集合。
下图是一个含有BAG的RDF有向图的示意:
注意BAG的成员标号rdf:_1和rdf:_2的顺序并不重要,它们可以被交换。而ALT的成员标号除了第一个是重要的(它是缺省的选择)外,也是顺序无关的。
Jena提供了明确的类接口和类实现用于表达容器,例如:
// create a bag
Bag smiths = model.createBag();
// select all the resources with a VCARD.FN property
// whose value ends with "Smith"
StmtIterator iter = model.listStatements(
new SelectorImpl(null, VCARD.FN, (RDFNode) null) {
public boolean selects(Statement s) {
try {
return s.getString()
.endsWith("Smith");
} catch (RDFException e) {
throw new RDFError(e);
}
}
});
// add the Smith's to the bag
while (iter.hasNext()) {
smiths.add(iter.next().getSubject());
}
由它得到的RDF为:
<rdf:RDF
xmlns: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='#A3'>
<rdf:type rdf:resource='http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag'/>
<rdf:_1 rdf:resource='http://somewhere/JohnSmith/'/>
<rdf:_2 rdf:resource='http://somewhere/RebeccaSmith/'/>
</rdf:Description>
</rdf:RDF>
容器接口提供了一个迭代器用于列举它的成员:
// print out the members of the bag
NodeIterator iter2 = smiths.iterator();
if (iter2.hasNext()) {
System.out.println("The bag contains:");
while (iter2.hasNext()) {
System.out.println(" " +
(Resource) iter2.next())
.getProperty(VCARD.FN)
.getString());
}
} else {
System.out.println("The bag is empty");
}
上面的输出为:
The bag contains:
John Smith
Becky Smith
Jena类提供的用于操纵容器的方法包括:添加新成员、插入成员到容器的成员中部、删除成员等。
有关Literal和DataType的细节
RDF的literal不是简单的string。它可以包含一个语种标签来说明该literal的语种。语种标签为English的Literal“chat”和语种标签为“French”的Literal “chat”被认为是不同的literal。 进一步说,一共有两类literal:一种是普通的string,一种是一个定义良好的XML片断。例如下面的代码:
// create the resource
Resource r = model.createResource();
// add the property
r.addProperty(RDFS.label, model.createLiteral("chat", "en"))
.addProperty(RDFS.label, model.createLiteral("chat", "fr"))
.addProperty(RDFS.label, model.createLiteral("<em>chat</em>", true));
// write out the graph
model.write(new PrintWriter(System.out));
它产生的RDF为:
<rdf:RDF
xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
xmlns:rdfs='http://www.w3.org/2000/01/rdf-schema#'
>
<rdf:Description rdf:about='#A0'>
<rdfs:label xml:lang='en'>chat</rdfs:label>
<rdfs:label xml:lang='fr'>chat</rdfs:label>
<rdfs:label xml:lang='en' rdf:parseType='Literal'><em>chat</em></rdfs:label>
</rdf:Description>
</rdf:RDF>
两个literal可以被看作相等的条件是:或者都是简单的literal,或者都是XML literal。而且要么都没有语种标签,要么有的话标签相同。