此为几年前刚开始学本体时查到的资料,目前感觉还是有参考作用
作者未知
《Ontology研究综述》、w3c Ontology研究组文档以及Jena编程应用总结其中代码仅供参考。Jena已为Apache项目,版本已更新
[TOC]
1 关于Ontology
1.1 Ontology的定义
Ontology最早是一个哲学的范畴,后来随着人工智能的发展,被人工智能界给予了新的定义。然后最初人们对Ontology的理解并不完善,这些定义也出在不断的发展变化中,比较有代表性的定义列表如下:
范畴 | 提出时间/提出人 | 定义 |
---|---|---|
哲学 | 客观存在的一个系统的解释和说明,客观现实的一个抽象本质 | |
计算机 | 1991/Neches等 | 给出构成相关领域词汇的基本术语和关系,以及利用这些术语和关系构成的规定这些词汇外延的规则的定义 |
1993/Gruber | 概念模型的明确的规范说明 | |
1997/Borst | 共享概念模型的形式化规范说明 | |
1998/Studer | 共享概念模型的明确的形式化规范说明 |
关于最后一个定义的说明体现了Ontology的四层含义:
- 概念模型(cerptualization)
通过抽象出客观世界中一些现象(Phenomenon)的相关概念而得到的模型,其表示的含义独立于具体的环境状态
- 明确(explicit)
所使用的概念及使用这些概念的约束都有明确的定义
- 形式化(formal)
Ontology是计算机可读的。
- 共享(share)
Ontology中体现的是共同认可的知识,反映的是相关领域中公认的概念集,它所针对的是团体而不是个体。
Ontology的目标是捕获相关的领域的知识,提供对该领域知识的共同理解,确定该领域内共同认可的词汇,并从不同层次的形式化模式上给出这些词汇(术语)和词汇之间相互关系的明确定义。
1.2 Ontology的建模元语
Perez等人用分类法组织了Ontology,归纳出5个基本的建模元语(Modeling Primitives):
类(classes)或概念(concepts)指任何事务,如工作描述、功能、行为、策略和推理过程。从语义上讲,它表示的是对象的集合,其定义一般采用框架(frame)结构,包括概念的名称,与其他概念之间的关系的集合,以及用自然语言对概念的描述。
关系(relations)在领域中概念之间的交互作用,形式上定义为n维笛卡儿积的子集:R:C1×C2×…×Cn。如子类关系(subclass-of)。在语义上关系对应于对象元组的集合。
函数(functions)一类特殊的关系。该关系的前n-1个元素可以唯一决定第n个元素。形式化的定义为F:C1×C2×…×Cn-1→Cn。如Mother-of就是一个函数,mother-of(x,y)表示y是x的母亲。
公理(axioms)代表永真断言,如概念乙属于概念甲的范围。
实例(instances)代表元素。从语义上讲实例表示的就是对象。
另外,从语义上讲,基本的关系共有4种:
关系名 | 关系描述 |
---|---|
part-of | 表达概念之间部分与整体的关系。 |
kind-of | 表达概念之间的继承关系,类似于面向对象中的父类与子类之间的关系。 |
instance-of | 表达概念的实例与概念之间的关系,类似于面向对象中的对象和类之间的关系。 |
attribute-of | 表达某个概念是另一个概念的属性。如“价格”是桌子的一个属性。 |
在实际建模过程中,概念之间的关系不限于上面列出的4种基本关系,可以根据领域的具体情况定义相应的关系。
1.3 Ontology和语义网络
Ontology和语义网络的联系和区别列表如下:
- 联系:它们都是知识表示的形式,均可以通过带标记的有向图来表示,适合于逻辑推理。
- 区别
比较方面 | Ontology | 语义网络 |
---|---|---|
描述的对象和范围 | 是对共享概念模型的规范说明,即其概念在某个特定领域是公认的,是面向特定领域的概念模型。 | 从数学上讲是一种带有标记的有向图,最初用于表示命题信息,现广泛用于专家系统表示知识。其节点表示物理实体、概念或状态,边用于表示关系,但是对节点和边都没有特殊规定,所以描述的范围比Ontology广。 |
表示的深度上 | 有5个要素“元语,类,关系,函数,公理和实例”,它通过这5个要素来严格、正确地刻画所描述的对象。 | 深度上不如Ontology,对建模没有特殊要求。 |
建模条件 | 建立必须有专家的参与,相对更加严格和困难,这也是Ontology目前的主要缺点之一。 | 不必有专家的参与。 |
【例子】:语义网络中可以表达“我的汽车是红色的”,而Ontology则适合表达如“团体组织的内部构成”等整体内容。
1.4 Ontology的描述语言
目前在具体应用中Ontology的表示方式主要有4类:
- 非形式化语言
- 半非形式化语言
- 半形式化语言
- 形式化语言
可以用自然语言来描述Ontology,也可以用框架、语义网络或逻辑语言来描述。
目前普遍使用的方法列表如下:
名称 | 描述 | 特点 |
---|---|---|
Ontolingua | 一种基于KIF(knowledge interchange format)的提供统一的规范格式来构建Ontology的语言。 | ü 为构造和维护Ontology提供了统一的、计算机可读的方式;ü 由其构造的Ontology可以方便地转换到各种知识表示和推理系统(Prolog、CORBA的IDL、CLIPS、LOOM、Epikit、Algernon和KIF),从而将Ontology的维护与使用它的目标系统隔开;ü 主要用于Ontology服务器。 |
CycL | Cyc系统的描述语言,一种体系庞大而非常灵活的知识描述语言。 | ü 在一阶谓词演算的基础上扩充了等价推理、缺省推理等功能;ü 具备一些二阶谓词演算的能力;ü 其语言环境中配有功能很强的可进行推理的推理机。 |
Loom | Ontosaurus的描述语言,一种基于一阶谓词逻辑的高级编程语言,属于描述逻辑体系。后来发展为PowrLoom语言(采用前后链规则(backward and forward chainer)作为推理机制)。 | ü 提供表达能力强、声明性的规范说明语言;ü 提供强大的演绎推理能力;ü 提供多种编程风格和知识库服务。 |
1.5 已有的Ontology及其分类
目前广泛使用的Ontology列表如下:
名称 | 描述 |
---|---|
Wordnet | 基于心理语言规则的英文词典,以synsets(在特定的上下文环境中可互换的同义词的集合)为单位组织信息。 |
Framenet | 英文词典,采用称为Frame Semantics的描述框架,提供很强的语义分析能力,目前发展为FramenetII。 |
GUM | 面向自然语言处理,支持多语种处理,包括基本概念及独立于各种具体语言的概念组织方式。 |
SENSUS | 面向自然语言处理,为机器翻译提供概念结构,包括7万多概念。 |
Mikrokmos | 面向自然语言处理,支持多语种处理,采用一种语言中间的中间语言TMR表示知识。 |
Guarino提出以详细程度和领域依赖度两个维度对Ontology进行划分。具体说明如下:
维度 | 说明 | 分类级别 |
---|---|---|
详细程度 | 描述或刻画建模对象的程度 | 高的称作参考(Reference)Ontologies |
低的称作共享(share)Ontologies | ||
领域依赖程度 | - | 顶级(top-level)Ontologies描述的是最普遍的概念及概念之间的关系,如空间、时间、事件、行为等,与具体的应用无关,其他Ontologies均为其特例。 |
领域(domain)Ontologies描述的是特定领域中的概念和概念之间的关系。 | ||
任务(task)Ontologies描述的是特定任务或行为中的概念及概念之间的关系。 | ||
应用(application)Ontologies描述的是依赖于特定领域和任务的概念和概念之间的关系。 |
1999年Perez和Benjamins归纳出了10种Ontologies:
- 知识表示Ontologies
- 普通Ontologies
- 顶级Ontologies
- 元(核心)Ontologies
- 领域Ontologies
- 语言Ontologies
- 任务Ontologies
- 领域-任务Ontologies
- 方法Ontologies
- 应用Ontologies
但它们之间有交叉,层次不够清晰。
1.6 构造Ontology的规则
出于对各自问题域和具体工程的考虑,构造Ontology的过程各不相同。目前没有一个标准的Ontology的构造方法。最有影响的是Gruber在1995年提出的5条规则:
- 明确性和客观性:Ontology应该用自然语言对所定义的术语给出明确、客观的语义定义。
- 完全性:所给出的定义是完整的,完全能表达所描述的术语的含义。
- 一致性:由术语得出的推论与术语本身的含义是相容的,不会产生矛盾。
- 最大单调可扩展性:向Ontology中添加通用或专用的术语时,不需要修改已有的内容。
- 最小承诺:对待建模对象给出尽可能少的约束。
目前大家公认在构造特定领域的Ontology的过程中需要领域专家的参与。
2 Ontology的研究和应用
Ontology的研究和应用主要包括以下3方面:
- 理论上的研究,主要研究概念及其分类,Ontology上的代数;
- 信息系统中的应用,主要包括处理信息组织、信息检索和异构信息系统互操作问题;
- Ontology作为一种能在知识层提供知识共享和重用的工具在语义Web中的应用。
2.1 Ontology的理论研究
Ontology的理论研究包括概念和概念分类、Ontology上的代数。最有代表性的是Guarino等人对概念的分类所做的深入和细致的研究,他们从一般的意义上分析了什么是概念、概念的特性、概念之间的关系以及概念的分类,提出了一套用于指导概念分类的可行理论。基于这个理论,他又提出了Ontology驱动的建模方法,在理论上为建模提供了一个通用的模式。
Guarino认为概念之间的差别不仅体现在概念的定义上,同时也体现在概念的某些特性上。从这些特性出发,归纳出概念的元特性(最基本的特性),从而用公式给出元特性的严格的形式定义。在此基础上,他们又讨论了元特性之间的关系和约束,最终把研究结果作为概念分类的基本理论工具并提出一套完成的概念分类体系结构。
Guarino的理论可以归纳如下:
概念分类理论的基础是概念的元特性。以概念的元特性为出发点,按照一定的规则,把具有相同元特性组合的概念归为一类,进而给出一般意义上的概念分类体系。概念的基本元特性包括:持久特性、非持久特性、反持久特性、半持久特性、载体标识特性、支持标识特性、外部依赖特性等。
以下是对各种特性的说明:
名称 | 描述 | 举例 |
---|---|---|
持久特性 | 严格定义为:。代表某个概念,代表x是的一个实例,表示其后的断言永远为真。 | Person具有持久性,而Student不具有持久性。 |
非持久特性 | 对某个概念而言,存在某些实例不会永远属于该概念。 | Student具有非持久性。 |
反持久特性 | 对概念的任何一个实例,这个实例不会永远属于该概念。 | Youth具有反持久性。 |
半持久特性 | 非持久性和反持久性的差集。 | —— |
载体标识特性 | —— | 如Student具有载体标识特性,因为学生之间的区别不是靠学生,而是作为人来区分的。 |
支持标识特性 | 每个实例相互之间是可以区分的。 | Person具有支持标识特性,人和人之间可由标识(人的指纹)来区分。 |
外部依赖特性 | 一个概念对另外一个概念的某种依赖关系。概念A对概念B的外在依赖关系表现为概念A中的任何一个实例a必蕴涵属于概念B的实例b,而b不是a的一部分。 | Parent外在依赖于Child,某人的父母蕴涵他(她)有小孩,而他的小孩当然不是他身体的一部分。 |
2.2 Ontology在信息系统中的应用
目前信息检索技术的分类和对他们的描述列举如下:
分类 | 特点 | 缺点 |
---|---|---|
全文(Text retrieval) | 把用户的查询请求和全文中的每一个词进行比较,不考虑查询请求和文件语义上的匹配。 | 虽然可以保证查全率,但是查准率大大降低。 |
数据(Data retrieval) | 查询要求和信息系统中的数据都遵循一定的格式,具有一定的结构,允许对特定字段检索。需要有标识字段的方法。 | 性能取决于所使用的字段标识方法和用户对方法的理解,具有很大的局限性,支持语义匹配的能力较差。 |
知识(Knowledge retrieval) | 基于知识的、语义上的匹配,在查准率和查全率上有更好的保证。是信息检索的重点,特别是面向Web信息的知识检索的重点。 | —— |
Ontology具有良好的概念层次结构和对逻辑推理的支持,在知识检索中有广泛应用。基于Ontology的信息检索的基本思想有:
- 在领域专家的帮助下,建立相关领域的Ontology;
- 收集信息源中的数据,并参照已建立的Ontology把收集来的数据按规定格式存储在元数据库(RDB,KDB等)中;
- 对用户检索界面获取的查询请求,查询转换器按照Ontology把查询请求转换成规定的格式,在Ontology的帮助下从元数据库中匹配出符合条件的数据集合;
- 检索的结果经过定制处理返回给用户。
关于Ontology的表达,主要分为两种情况进行处理:
- 检索系统如不需要太强的推理能力,Ontology可用概念图的形式表示并存储,数据可以保存在一般的关系数据库中,采用图匹配技术完成检索;
- 如要求较强的推理能力,一般需要一种描述语言(Loom等)表示Ontology,数据保存在知识库中,采用描述语言的逻辑推理能力完成检索。
目前Ontology用于信息检索的项目列举如下:
项目名称 | 说明 |
---|---|
(Onto)2Agent | 为了帮助用户检索所需要的WWW上已有的Ontology,主要采用参照Ontology,即以WWW上已有的Ontology为对象建立起来的Ontology,保存各类Ontology的元数据。 |
Ontobroker | 面向WWW上的网页资源,目的是帮助用户检索所需的网页,这些网页含有用户关心的内容。 |
SKC | 解决信息系统语义异构的问题,实现异构的自治系统间的互操作。希望通过在Ontology上的一个代数系统来实现Ontology之间的互操作,从而实现异构系统之间的互操作。 |
2.3 Ontology和语义Web
提高Web信息检索的质量包括两方面的内容:
- 如何在现有的资源上面设计更好的检索技术;
- 如何为Web上的资源附加上计算机可以理解的内容,便于计算机处理,即给出一种计算机能够理解的表示资源的手段。
基于后一种考虑,Berners-Lee在2000-12-18的XML2000的会议上提出了语义Web。语义Web的目标是使得Web上的信息具有计算机可以理解的语义,满足智能软件代理(Agent)对WWW上异构和分布信息的有效访问和检索。下面是Berners-Lee为未来Web发展提出的基于语义的体系结构-语义Web体系结构
层数 | 名称 | 描述 | |
---|---|---|---|
第一层 | UNICODE和URI | 整个语义网络的基础,Unicode处理资源的编码,URI负责标识资源。 | |
第二层 | XML+NS+xmlschema | 用于表示数据的内容和结构。 | |
第三层 | RDF+rdfschema | 用于描述Web上的资源及其类型。 | |
第四层 | Ontology vocabulary | 用于描述各种资源之间的联系。 | |
第五层 | Logic | 在下面四层的基础上进行的逻辑推理操作。 | |
第六层 | Proof | ||
第七层 | Trust |
* 核心层,用于表示Web信息的语义。
? XML和RDF都能为所表述的资源提供一定的语义。但是XML中的标签(tags)和RDF中的属性(properties)集都没有任何限制。一个例子是:XML可以用“<Author>TOM</Author>
”表示TOM是教师。而“<rdf:Description about=http://www.w3.org/Home/Lassila><s:Creator>Ora Lassila</s:Creator></rdf:Description>
”这个RDF片断描述了Web页的创建者问题。而上面的Author和Creator完全可以用Writer来代替。另一个例子是:某医院和某大学的Web页上都有<Doctor>
,但是不知道它代表医生还是博士。综上,XML和RDF在处理语义上存在的问题是:
- 同一概念有多种词汇表示(多词同义);
- 同一个词汇有多种概念(含义)(一词多义)。
Ontology通过对概念的严格定义和概念之间的关系来确定概念精确含义,表示共同认可的、可共享的知识,从而解决上面的问题。因此在语义Web中,Ontology具有非常重要的地位,是解决语义层次上Web信息共享和交换的基础。
为了便于Web上应用程序使用方便,需要有一个通用的标准语言来表示Ontology,就像XML作为标准的数据交换语言一样。目前正在开发中的语言有:SHOE、OML、XOL、Riboweb、RDFS和OIL。下面将就w3c提出的OWL(Web Ontology Language)做进一步的分析。
目前语义Web是一个新兴的研究方向,Ontology在其中的应用刚刚起步。
3 Web Ontology Language (OWL)概述
3.1 OWL简介
OWL(Web Ontology Language)适用于这样的应用,在这些应用中,不仅仅需要提供给用户可读的文档内容,而且希望处理文档内容信息。OWL能够被用于清晰地表达词汇表中的词条(term)的含义以及这些词条之间的关系。而这种对词条和它们之间的关系的表达就称作Ontology。OWL相对XML、RDF和RDFSchema拥有更多的机制来表达语义,从而OWL超越了XML、RDF和RDFSchema仅仅能够表达网上机器可读的文档内容的能力。
3.2 OWL在语义网中的地位
语义网是对未来网络的一个设想,在这样的网络中,信息都被赋予了明确的含义,机器能够自动地处理和集成网上可用的信息。语义网使用XML来定义定制的标签格式以及用RDF的灵活性来表达数据,下一步需要的就是一种Ontology的网络语言(比如OWL)来描述网络文档中的术语的明确含义和它们之间的关系。
OWL是w3c推荐的语义网络“栈”中的一部分,这个“栈”被表达如下:
名称 | 描述 |
---|---|
XML | 结构化文档的表层语法,对文档没有任何语义约束。 |
XML Schema | 定义XML文档的结构约束的语言。 |
RDF | 对象(或者资源)以及它们之间关系的数据模型,为数据模型提供了简单的语义,这些数据模型能够用XML语法进行表达。 |
RDF Schema | 描述RDF资源的的属性和类型的词汇表,提供了对这些属性和类型的普遍层次的语义。 |
OWL | 添加了更多的用于描述属性和类型的词汇,例如类型之间的不相交性(disjointness),基数(cardinality),等价性,属性的更丰富的类型,属性特征(例如对称性,symmetry),以及枚举类型(enumerated classes)。 |
下图给出了w3c的Ontology语言栈描述:
W3C2002年7月31日透露了发行OWL Web 本体论语言(OWL Web Ontology Language) 工作草案的细节,其目的是为了更好地开发语义网(Semantic Web)。
W3C 发言人Ian Jacobs说,开发语义网的目的是能够在互联网上进行更结构化的智能处理,例如,当一个人确定要参加某个城市的会议后,就可以自动查找有关航班和酒店的信息。
W3C称,W3C Web 本体论工作小组正在对OWL Web本体论语言进行设计,OWL是本体论Web 语言(Ontology Web Language)的字母缩写。设计的最终目的是为了提供一种可以用于各种应用的语言,这些应用需要理解内容,从而代替只是采用人类易读的形式来表达内容。作为语义网的一部分,XML、RDF和RDF-S支持通过提供针对术语描述的词汇表,共同推进了机器的可靠性。
W3C发行的三种工作草案名为《特色大纲》(Web Ontology Language (OWL) Guide Version 1_0)、《抽象句法》(OWL Web Ontology Language 1_0 Abstract Syntax)和《语言参考》。
W3C本周还发行了其Web 服务架构使用方案集合的工作草案,目的是为下一代的Web服务提供使用案例和方案。
W3C Web服务架构工作小组特别发行的方案包括诸如旅行社使用案例和类似电子数据交换的采购等情形。Jacobs说:“W3C官员正在制定有关Web服务架构范围的文件。”
3.3 OWL的三个子语言——OWL Lite、OWL DL、OWL Full
3.3.1 子语言描述
OWL的三个子语言描述列表如下:
子语言 | 描述 | 例子 |
---|---|---|
OWL Lite | 用于提供给那些只需要一个分类层次和简单的属性约束的用户。 | 支持基数(cardinality),只允许基数为0或1。 |
OWL DL | 支持那些需要在推理系统上进行最大程度表达的用户,这里的推理系统能够保证计算完全性(computational completeness,即所有地结论都能够保证被计算出来)和可决定性(decidability,即所有的计算都在有限的时间内完成)。它包括了OWL语言的所有约束,但是可以被仅仅置于特定的约束下。 | 当一个类可以是多个类的一个子类时,它被约束不能是另外一个类的实例。 |
OWL Full | 支持那些需要在没有计算保证的语法自由的RDF上进行最大程度表达的用户。它允许在一个Ontology在预定义的(RDF、OWL)词汇表上增加词汇,从而任何推理软件均不能支持OWL FULL的所有feature。 | 一个类可以被同时表达为许多个体的一个集合以及这个集合中的一个个体。 |
3.3.2 子语言间以及子语言和RDF的关系
这三种子语言之间的关系是:
- 每个合法的OWL Lite都是一个合法的OWL DL;
每个合法的OWL DL都是一个合法的OWL Full;
每个有效的OWL Lite结论都是一个有效的OWL DL结论;
每个有效的OWL DL结论都是一个有效的OWL Full结论。
用户在选择使用哪种语言时的主要考虑是:
选择OWL Lite还是OWL DL主要取决于用户需要整个语言在多大程度上给出了约束的可表达性;
选择OWL DL还是OWL Full主要取决于用户在多大程度上需要RDF的元模型机制(如定义类型的类型以及为类型赋予属性);
在使用OWL Full而不是OWL DL时,推理的支持不可预测,因为目前还没有完全的OWL Full的实现。
这三种子语言与RDF的关系是:
OWL Full可以看成是RDF的扩展;
OWL Lite和OWL Full可以看成是一个约束化的RDF的扩展;
- 所有的OWL文档(Lite,DL,Full)都是一个RDF文档;
- 所有的RDF文档都是一个OWL Full文档;
只有一些RDF文档是一个合法的OWL Lite和OWL DL文档。
3.4 OWL语言大纲
【说明】:以下用斜体标出的为OWL中的词条(term),rdf:和rdfs:前缀表示这些词条已经在RDF和RDF Schema中出现。
3.4.1 OWL Lite语言大纲
分类 | 词条 |
---|---|
RDF Schema Features | · Class · rdf:Property · rdfs:subClassOf · rdfs:subPropertyOf · rdfs:domain · rdfs:range · Individual |
(In)Equality | · equivalentClass · equivalentProperty · sameIndividualAs · differentFrom · allDifferent |
Property Characteristics | · inverseOf · TransitiveProperty · SymmetricProperty · FunctionalProperty · InverseFunctionalProperty |
Property Type Restrictions | · allValuesFrom · someValuesFrom |
Restricted Cardinality | · minCardinality (only 0 or 1) · maxCardinality (only 0 or 1) · cardinality (only 0 or 1) |
Header Information | · imports · versionInfo · priorVersion · backwardCompatibleWith · incompatibleWith |
Class Intersection | · intersectionOf |
Datatypes |
3.4.2 OWL DL和OWL Full大纲
下面给出了在OWL Lite基础上添加的OWL DL和OWL Full语言架构
分类 | 词条 |
---|---|
Class Axioms | · oneOf · disjointWith · equivalentClass (applied to class expressions) · rdfs:subClassOf (applied to class expressions) |
Boolean Combinations of Class Expressions | · unionOf · intersectionOf · complementOf |
Arbitrary Cardinality | · minCardinality · maxCardinality · cardinality |
Filler Information | · hasValue |
3.5 OWL Lite语言描述
和OWL DL和OWL Full相比,OWL Lite只是使用了OWL语言的一些feature,并且做了限制。
Class只能根据命名了的superclass(它不能是任意的逻辑表达式)进行定义,而且只能使用特定类型的class restriction。
类之间的Equivalence以及子类关系只能在命名了的class上做声明,不能应用于任意的类型表达式。
OWL Lite只允许属性限制应用于命名类型。
OWL Lite对cardinality的概念也有限制——它的取值范围只能是0和1。
以下列出了OWL Lite大纲中各类feature的描述。
3.5.1 OWL Lite RDF Schema Features
名称 | 描述 | 实例 |
---|---|---|
Class | 定义了一组共享了某些相同属性的individual。Class能够通过subClassOf定义出一个特定的类层次。有一个内置的公共类Thing,它是所有individual的Class,也是所有Class的superclass。 | Deborah 和Frank都是Person这个Class的成员。 |
rdfs:subClassOf | 类层次可以通过给出诸如一个类是另一个或多个类的子类这样的声明来创建。 | Person可以被定义为是Mammal的一个subclass,这样我们就能够推断:如果X是一个Person,那么X一定也是一个Mammal。 |
Rdfs:Property | 表达了individual之间的关系。 | 例如hasChild,hasRelative,,hasSibling,和hasAge都是Property的例子。前三个例子用于表达Person之间的关系,最后一个把一个Person和一个Datatype Integer关联起来。 |
rdfs:subPropertyOf | 属性层次可以通过给出诸如一个属性是另一个或多个属性的子属性这样的声明来创建。 | hasSibling是hasRelative的子属性。通过这一点我们就可以推理出:如果X和Y通过hasSibling进行了关联,那么它们一定也通过hasRelative进行了关联。 |
rdfs:domain | 一个property的domain是能够应用该property的individual的集合。如果property P把class X和class Y关联起来,P的domain是class Z,那么X一定是Z的一个实例。Domain是一个全局约束,因为它就property而言,但是当它与一个特定的class关联时也不只是就property而言。 | Property hasChild可以被说拥有domain Mammal,从这一点我们就能够推理出如果Frank hasChild Anna,那么Frank一定是一个Mammal。 |
rdfs:range | 一个property的range是该property所必须有的值的individual的集合。如果proerty P将class X和class Y关联,P的range是class Z,那么Y一定是Z的一个实例。 | Property hasChild可以被说拥有range Mammal,从这一点我们就能够推理出如果Louise hasChild Deborah,那么Deborah一定是一个Mammal。 |
Individual | Class的实例,property可以被用来把一个individual和另一个individual关联起来。 | 一个名叫Deborah的individual可以被描述为是Person这个class的实例,而property hasEmployer可以把individual Deborah和individual StanfordUniversity关联起来。 |
3.5.2 OWL Lite Equality 和Inequality
名称 | 描述 | 实例 |
---|---|---|
equivalentClass | 两个类可以被声明为相同,即它们拥有不同的名字但是却拥有相同的individual的集合。它被用来创建同义类。 | Car可以被说成是Automobile的equivalentClass。从这一点我们能推理得到任何Car的实例都是Automobile的实例,反之也一样。 |
equivalentProperty | 两个类也可以被声明为相同。它可以被用来创建同义属性。 | HasLeader可以被说成是hasHead的equivalentProperty。从这一点我们能够推理得到:如果X通过HasLeader与Y关联,那么X也通过hasHead与Y关联。我们也能够推理得到:HasLeader是hasHead的子属性,同时hasHead也是HasLeader的子属性。 |
sameIndividualAs | 两个individual也可以被声明为相同。它可以被用来创建一系列指向同一个individual的名字。 | Deborah被说成与DeborahMcGuinness是同一个individual。 |
differentFrom | 一个individual可被声明为与其他一些individual不同,这在使用如OWL(RDF)等语言时表达individual有而且只有一个名字时非常重要。 | l Frank可被说成与Deborah以及Jim是不同的individual,这样当Frank和Deborah都被说成是一个functional(最多只有一个值)的property的值时,就会出现矛盾;l 没有特别指出的话,我们不能推理说Deborah和Frank指的是不同的individual。 |
allDifferent | 在一个allDifferent声明中,我们可以指出一定数量的individual两两不同。这在表达一个不同对象的集合而建模者侧重于强调这些对象的唯一的名字时尤其有用。 | 可以在一个allDifferent声明中说明Frank、Deborah、Jim两两不同。 |
3.5.3 OWL Lite Property Characteristics
名称 | 描述 | 实例 |
---|---|---|
inverseOf | 一个属性可以被声明为另一个属性的翻转属性。如果P1被声明为P2的翻转属性,那么如果X通过P1关联到Y,那么Y通过P1关联到X。 | 如果hasChild是hasParent的翻转属性,Deborah hasParent Louise,那么我们就能够推理出Louise hasChild Deborah。**** |
TransitiveProperty | 属性可以被声明为传递的。如果(x,y)是传递属性P的一个实例,(y,z)也是传递属性P的一个实例,那么(x,z)是传递属性P的一个实例。OWL Lite给出了关于传递属性的一个边界条件:传递属性和它的superproperty不能有maxCardinality为1的限制,否则OWL Lite和OWL DL都将成为不确定语言。 | 如果ancestor被声明为传递的,(Sara,Louise)是它的一个实例,(Louise,Deborah)也是他的一个实例,那我们就能够推理出(Sara,Deborah)是他的一个实例。 |
SymmetricProperty | 属性可以被声明为是对称的。如果(x,y)是对称属性P的一个实例,那么(y,x)也是它的一个实例。被声明为对称的属性不能有任意的domain和range。 | Friend可以被说成是一个对称属性,如果Frank 是 Deborah的Friend,那我们可以推断出Deborah 是Frank的Friend。 |
FunctionalProperty | 属性可以被声明为只有一个值。即一个individual如果被声明为FunctionalProperty,那么对于这样的一个实例它最多只有一个值。这可以被方便的用来说明一个属性的cardinality最小为0,最大为1。 | l Frank可被说成与Deborah以及Jim是不同的individual,这样当Frank和Deborah都被说成是一个functional(最多只有一个值)的property的值时,就会出现矛盾;l 没有特别指出的话,我们不能推理说Deborah和Frank指的是不同的individual。 |
InverseFunctionalProperty | 如果一个属性被声明为inverse functional,则意味着它的翻转属性是functional的,也就是说该属性的翻转属性的每个individual最多只有一个值。 | HasUSSocialSecurityNumber(SecurityNumber是美国居民的唯一标识符)可以被声明为inverse functional。该属性的翻转属性isTheSocialSecurityNumberFor在社会保险号这个class中任何一个individual至多只有一个值。由此我们可以推断出任何两个Person的实例都不能有相同的SecurityNumber。还可以推断出:如果两个Person的实例有相同的SecurityNumber,那么他们一定是表示同一个individual。 |
3.5.4 OWL Lite Property Type Restriction
该约束针对某个属性,属于局部约束。
名称 | 描述 | 实例 |
---|---|---|
allValuesFrom | 该约束将一个属性的取值和一个class相关。也就是说,如果一个class的实例通过这个属性和另外一个individual相关,那么后一个individual则能够被认为是改约束类的一个实例。 | Class Person有一个属性hasOffspring,该属性被约束在allValuesFrom上取值为Person类。这就是说如果Person的一个实例Louise通过属性hasOffspring和另一个individual Deborah相关,从这一点我们能推断出 Deborah是Person的一个实例。这种约束允许hasOffspring属性被其他class使用,例如被class Cat使用,从而做出相应的约束。 |
someValuesFrom | 和上面类似,该约束也将一个属性的取值和一个class相关。只不过此时要求该属性的取值至少有一个是该class类型的。 | Class SemanticWebPaper在property hasKeyword上的someValuesFrom 约束值SemanticWebTopic说明hasKeyword存在某个取值应该是class SemanticWebTopic的一个实例。但是我们不能就此推断说hasKeyword的所有取值都是SemanticWebTopic的实例。 |
3.5.5 OWL Lite Restricted Cardinality
同上,该约束也是局部约束,而且OWL Lite在Cardinality上的局部约束只允许Cardinality的取值为0和1(这不同于其他两类OWL允许任意数目的Cardinality)。
名称 | 描述 | 实例 |
---|---|---|
minCardinality | Cardinality是依据一个特定的class在一个property上做的声明。如果就一个class而言某个property的minCardinality为1,则该class的任何一个实例都通过该property至少和一个individual相关。这也是一种用来表达某property必须在某class的任何一个实例中有一个值的办法。在OWL Lite中,minCardinality的值只能为0或者1。0表示的意思是对于某个class而言这个proerty是可选的。 | l Class Person在property hasOffspring并没有minCardinality约束,因为不是所有的Person都有Offspring的。l Class Parent则在property hasOffspring上有minCardinality为1。l Class Person在property hasOffspring上的minCardinality值可以为0。根据上面的前两条信息我们可以推断出,如果Louise是一个Person,我们并不能得到任何有关他后代的信息;但是一旦发现他是一个Parent,则Louise通过property hasOffspring至少和一个individual相关。但是我们不能得到他最多和几个individual相关。 |
maxCardinality | 如果就一个class而言某个property的maxCardinality为1,则该class的任何一个实例都通过该property至多和一个individual相关。MaxCardinality值为1的约束property有时也叫做functional或者unique property。通过它我们不能得到有关minCardinality的任何信息,但是这对于我们表达某些class在某些property上没有值是很重要的。 | l Class UnitedStatesCitizens上的property hasRegisteredVotingState的MaxCardinality值为1(因为一个公民只能在一个州投票)。l Class UnmarriedPerson实例不能通过property hasSpouse和任何individual相关,这时只要把hasSpouse的maxCardinality设为0就可以了。 |
cardinality | 它用于方便表达在一个class上的property同时拥有约束minCardinality 0 和 maxCardinality 0 或者 minCardinality 1 和 maxCardinality 1。 | Class person在property hasBirthMother上只有一个值,可以设定该property的Cardinality。 |
3.5.6 OWL Lite Class Intersection
名称 | 描述 | 实例 |
---|---|---|
intersectionOf: | OWL Lite允许在class和约束之间存在交集。 | Class EmployedPerson可以被定义为intersectionOf class Person和EmployedThings(后者可以被定义为拥有hasEmployer属性并在该属性上的minCardinality为1)。 |
3.5.7 Datatypes
OWL 使用了RDF的datatype schema,而后者又参考了XML Schema的datatype。这些datatype能够通过URI被识别。每当有一个datatype的实例出现时,必须有一个RDF属性rdf:datatype,它的值为URI引用的XML Schema datatype。
3.5.8 OWL Lite Header Information
OWL支持ontology引用、包含以及元信息描述。上面提到的三个层次的OWL都包含了用于指定导入的ontology、ontology版本信息和前版本信息、可向后兼容的ontology信息以及不兼容的ontology信息等一系列信息的方法。
3.6 增量语言OWL DL和OWL Full描述
尽管OWL DL添加了一些约束,它和OWL Lite实际上共享了词汇表。总的来讲,OWL DL引入了类型分割(一个class不能是一个property或者一个individual,一个property也不能是一个class或者individual);它要求property或者是ObjectProperties,或者是DatatypeProperties。后者RDF literal、XML Datatype以及class实例之间的关系。前者是两个class实例之间的关系。下面继续列出了OWL DL和OWL Full的扩展词汇
名称 | 描述 | 实例 |
---|---|---|
One of(枚举类型) | Class可以通过枚举构成该class的individual来描述。 | Class daysOfTheWeek可以简单地通过枚举Sunday、Monday、Tuesday、Wednesday,、Thursday、Friday、 Saturday这7个individual来表达。我们可以由此推断出任何拥有allValuesFrom约束于daysOfTheWeek的property的maxcardinality为7。 |
HasValue(属性值) | 一个property可以被要求拥有一个特定的individual作为它的值。 | Class dutchCitizens的实例可以在property nationality上以theNetherlands最为它的值。 |
disjointWith | OWL Full允许在class定义不相交性。 | Man和Woman可以被定义为是不相交的,这样我们就能够推断出如果已知A为Man,那么A一定不是Woman。 |
unionOf, complementOf, intersectionOf(布尔连接) | OWL Full允许class之间任意的布尔连接。 | l 通过unionOf,我们能够声明或者是USCitizens或者是DutchCitizens的事物;l 通过complementOf,我们能够声明children不是SeniorCitizens。 |
minCardinality, maxCardinality, cardinality(全cradinality) | OWL Full允许取值为任意非负整数的cardinality。 | Class DINKs(Dual Income)在property hasIncome上的mincardinality约束为2 |
complex classes | 由于OWL Full引入了上面的词条,实际上它已经支持了复杂类。它还包括了一个底层class名为Nothing,它没有任何实例。OWL允许class被用作实例(另两种不可以)。 |
4 OWL文档结构举例
4.1 命名空间
这是使用OWL的一系列词条的前提,我们必须准确说明正在使用的特定的词汇表。一个Ontology的标准的初始模块是包含在rdf:RDF标签中的一系列命名空间(namespace)的声明。这些声明用以准确解释文档中的标识符,从而使得Ontology的其他部分具有可读性。以下是一个典型的命名空间声明的例子:
<rdf:RDF
xmlns ="http://www.example.org/wine#"
xmlns:vin ="http://www.example.org/wine#"
xmlns:food="http://www.example.org/food#"
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#"
xmlns:dte ="http://www.example.org/wine-dt#">
命名标识符 | 描述 |
---|---|
xmlns ="http://www.example.org/wine#" | 说明了缺省的命名空间,也就是当文档中出现没有前缀的标签时所引用的命名空间。 |
xmlns:vin ="http://www.example.org/wine#" | 说明了和当前的Ontology相关的具有前缀vin的命名空间。 |
xmlns:food="http://www.example.org/food#" | 指出了支持表达本Ontology的food这一Ontology的命名空间,它们以前缀food出现。 |
xmlns:owl ="http://www.w3.org/2002/07/owl#" | 说明了出现owl前缀的词条应该寻找的命名空间。这是通常的OWL声明,用以在文档中加入OWL词汇表。 |
xmlns:rdf ="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | 说明了在文档中出现的以rdf为前缀的词条的命名空间,这是为了引入RDF定义的词汇。 |
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" | 说明了在文档中出现的以rdfs为前缀的词条的命名空间,这是为了引入RDF Schema定义的词汇。 |
xmlns:xsd ="http://www.w3.org/2000/10/XMLSchema#" | 说明了在文档中出现的以xsd为前缀的词条的命名空间,这是为了引入XML Schema定义的词汇。 |
xmlns:dte ="http://www.example.org/wine-dt#" > | 说明了在文档中出现的以dte为前缀的词条的命名空间,这是为了引入包含XML Schema Datatype定义的词汇。 |
我们也可以在Ontology定义之前在文档类型定义DocType一节中通过定义一些实体来给出命名空间的说明。例如:
<!DOCTYPE owl [
<!ENTITY vin "http://www.example.org/wine#" >
<!ENTITY food "http://www.example.org/food#" > ]>
? 另外,命名空间只是对标签的说明,对属性没有约束。但是在OWL文档中我们又经常要用到和命名空间相关的词条,这时就必须写清楚整个URI。例如http://www.example.org/owl/wine#merlot。但是如果有了类似上面的实体定义,我们也可以简写成“&vin;merlot”。
4.2 Ontology头
完成了命名空间的定义,我们必须以下面的断言来开始一个OWL Ontology:
<owl:Ontology rdf:about="http://www.example.org/wine">
接下来可以以一些标签标明注释、版本控制、以及对其他Ontology的引入等信息。例如:
<owl:Ontology rdf:about="http://www.example.org/wine">
<rdfs:comment>An example OWL ontology</rdfs:comment>
<owl:versionInfo>
$Id: Overview.html,v 1.2 2002/11/08 16:42:25 connolly Exp $
</owl:versionInfo>
<owl:imports rdf:resource="http://www.w3.org/TR/2002/WD-owl-guide-20021104/food.owl"/>
标签 | 说明 |
---|---|
给出了本Ontology的主要功能。 | |
标准标签,给出了供版本控制系统挂钩用的信息,OWL本身并没有什么结构上的约束。 | |
提供了引入机制,只给出了一个参数rdf:resource。 |
其中引入另外一个Ontology将会将它的整个定义的集合加入到知识库中来。需要注意的是,这个标签只是说明了引入一个Ontology的意图,但不总是成功的。在语义网上对网上资源的访问不总是成功的,这需要依照工具实现的情况而定。
最后,给出相应的Ontology头的结束标签:
</owl:Ontology>
4.3 基本定义
4.3.1 简单的Classe和Individual
所有用户定义的class都缺省是owl:Thing的subclass。而领域相关的根class的定义只要给出一个命名的类声明就可以了。例如在制酒业的三个根class定义如下:
<owl:Class rdf:ID="Winery"/>
<owl:Class rdf:ID="Region"/>
<owl:Class rdf:ID="ConsumableThing"/>
这时我们只是用ID为类起了名字,并没有指定有关类的其他任何信息,例如该类的成员等等。rdf:ID
属性类似于XML中的ID属性,这样我们能够通过类似“documentURI#Region”
在其他的Ontology中引用region这一class。也可以采用类似“rdf:about="#x”
的方法引用。
? Class的基本的分类构造器是subclassof。例如:
<owl:Class rdf:ID="PotableLiquid">
<rdfs:subClassOf rdf:resource="#ConsumableThing" />
...
</owl:Class>
这里我们定义了PotableLiquid是ConsumableThing的subclass。
? 类定义除了包括命名和引用以外,还包括限制。上面的subclassof就是一个限制。下面给出了Wine这个class的简单定义:
<owl:Class rdf:ID="Wine">
<rdfs:subClassOf rdf:resource="#PotableLiquid"/>
<rdfs:label xml:lang="en">wine</rdfs:label>
<rdfs:label xml:lang="fr">vin</rdfs:label>
...
</owl:Class>
rdfs:label
标签给出了人们可读的类名。属性lang表示支持多语言表达。
一个Individual可以通过声明它是某个类的成员得以表达。例如:
<Region rdf:ID="CentralCoastRegion" />
下面的表达是等价的:
<owl:Thing rdf:ID="CentralCoastRegion" />
<owl:Thing rdf:about="#CentralCoastRegion">
<rdf:type rdf:resource="#Region"/>
</owl:Thing>
type这个RDF词条将一个Individual和一个class的成员绑定起来。
下面的例子给出了一个grape分类,并用一个individual表达了Cabernet Sauvignon品种的grape:
<owl:Class rdf:ID="Grape">
<owl:Class rdf:ID="WineGrape">
<rdfs:subClassOf rdf:resource="#Grape"/>
</owl:Class>
<WineGrape rdf:ID="CabernetSauvignonGrape" />
4.3.2 简单的Property
property可以被用来说明class的共同特征以及某些individual的专有特征。一个property是一个二元关系。有两类property:
datatype property:class元素和XML datatype之间的关系;
object property:两个类元素之间的关系。
可以通过指定property的domain和range以及定义subproperty来约束一个property。下面是一个例子:
<owl:ObjectProperty rdf:ID="madeFromGrape">
<rdfs:domain rdf:resource="#Wine"/>
<rdfs:range rdf:resource="#WineGrape"/>
</owl:ObjectProperty>
通过上面的定义property madeFromGrape给出了class Wine的元素和WineGrape的元素之间的关系。下面的例子给出了property的层次定义:
<owl:ObjectProperty rdf:ID="WineDescriptor" />
<owl:Class rdf:ID="WineColor">
<rdfs:subClassOf rdf:resource="#WineDescriptor" />
...
</owl:Class>
<owl:ObjectProperty rdf:ID="hasWineDescriptor">
<rdfs:domain rdf:resource="#Wine" />
<rdfs:range rdf:resource="#WineDescriptor" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="hasColor">
<rdfs:subPropertyOf rdf:resource="#hasWineDescriptor" />
<rdfs:range rdf:resource="#WineColor" />
</owl:ObjectProperty>
? 下面是locatedIn property的定义:
<owl:ObjectProperty rdf:ID="locatedIn">
...
<rdfs:domain rdf:resource="http://www.w3.org/2002/07/owl#Thing" />
<rdfs:range rdf:resource="#Region" />
</owl:ObjectProperty>
该定义允许locatedIn的domain为任何一个thing。
? 下面是Vintage这个class的定义:
<owl:Class rdf:ID="Vintage">
<rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#vintageOf"/>
<owl:minCardinality>1</owl:minCardinality>
</owl:Restriction>
</rdfs:subClassOf>
</Class>
property vintageOf
将Vintage关联到wine。
? Datatype利用XML Schema datatype定义的简单类型完成定义。如果我们想把vintage的年限约束到1700以后,我们需要在其他文件中创建几个XML Schema datatype定义:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.example.org/wine-dt.xsd">
<xsd:simpleType name="year">
<!-- year is an XMLS datatype based on integer -->
<xsd:restriction base="xsd:decimal"/>
</xsd:simpleType>
<xsd:simpleType name="wineYear">
<!-- wineYear is an XMLS datatype based on year -->
<!-- with the added restriction that values must be GEQ 1700 -->
<xsd:restriction base="year">
<xsd:minInclusive value="1700"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
而后我们再给出WineYear这个class的定义:
<owl:Class rdf:ID="WineYear" />
<owl:DataTypeProperty rdf:ID="yearValue">
<rdfs:domain rdf:resource="#WineYear" />
<rdfs:range rdf:resource="&dt;wineYear"/>
</owl:DataTypeProperty>
关于individual的property定义,一个例子如下:
<CaliforniaRegion rdf:ID="SantaCruzMountainsRegion" />
<Winery rdf:ID="SantaCruzMountainVineyard" />
<CabernetSauvignon rdf:ID="SantaCruzMountainVineyardCabernetSauvignon" >
<locatedIn rdf:resource="#SantaCruzMountainsRegion"/>
<hasMaker rdf:resource="#SantaCruzMountainVineyard" />
</CabernetSauvignon>
下面创建了一个WineYear的实例并将它和一个特殊的datatype dte:wineYear关联起来:
<WineYear rdf:ID="Year1998">
<yearValue rdf:datatype="&dte;wineYear">1998</yearValue>
</WineYear>
4.3.3 Property特征
下面给出了用于扩展定义property的各类特征。
- TransitiveProperty
被标记为Transitive的property P满足下面的公理:
P(x,y) and P(y,z) -> P(x,z)
例如:
<owl:ObjectProperty rdf:ID="locatedIn">
<rdf:type rdf:resource="&owl;TransitiveProperty" />
<rdfs:domain rdf:resource="&owl;Thing" />
<rdfs:range rdf:resource="#Region" />
</owl:ObjectProperty>
<Region rdf:ID="SantaCruzMountainsRegion">
<locatedIn rdf:resource="#CaliforniaRegion" />
</Region>
<Region rdf:ID="CaliforniaRegion">
<locatedIn rdf:resource="#UsRegion" />
</Region>
其中locatedIn就是Transitive的。
- SymmetricProperty
被标记为symmetric的property P满足下面的公理:
P(x,y) iff P(y,x)
例如:
<owl:ObjectProperty rdf:ID="adjacentRegion">
<rdf:type rdf:resource="&owl;SymmetricProperty" />
<rdfs:domain rdf:resource="#Region" />
<rdfs:range rdf:resource="#Region" />
</owl:ObjectProperty>
<Region rdf:ID="MendocinoRegion">
<locatedIn rdf:resource="#CaliforniaRegion" />
<adjacentRegion rdf:resource="#SonomaRegion" />
</Region>
adjacentRegion就是symmetric的。
- Functional Property
被标记为functional的property P满足下面的公理:
P(x,y) and P(x,z) -> y = z
例如:
<owl:Class rdf:ID="WineYear" />
<owl:ObjectProperty rdf:ID="hasVintageYear">
<rdf:type rdf:resource="&owl;FunctionalProperty" />
<rdfs:domain rdf:resource="#Vintage" />
<rdfs:range rdf:resource="#WineYear" />
</owl:ObjectProperty>
hasVintageYear就是functional的,因为每种wine只有一个VintageYear。
- inverseOf
一个property P1被标记为inverseof 一个property P2,满足下面的公理:
P1(x,y) iff P2(y,x)
例如:
<owl:ObjectProperty rdf:ID="hasMaker">
<rdf:type rdf:resource="&owl;FunctionalProperty" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="producesWine">
<owl:inverseOf rdf:resource="#hasMaker" />
</owl:ObjectProperty>
- InverseFunctionalProperty
一个被标记为InverseFunctional的property P满足下面的公理:
P(y,x) and P(z,x) -> y = z
例如:
<owl:ObjectProperty rdf:ID="hasMaker" />
<owl:ObjectProperty rdf:ID="producesWine">
<rdf:type rdf:resource="&owl;InverseFunctionalProperty" />
<owl:inverseOf rdf:resource="#hasMaker" />
</owl:ObjectProperty>
? producesWine就是InverseFunctional的。
4.3.4 Property 约束
还可以进一步通过约束来规定property的range在某些范围内。
- allValuesFrom, someValuesFrom
上面已经给出的property都是全局的属性约束。而这两个约束相对包含它们的类定义而言是局部的。例如:
<owl:Class rdf:ID="Wine">
<rdfs:subClassOf rdf:resource="&food;PotableLiquid" />
...
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#hasMaker" />
<owl:allValuesFrom rdf:resource="#Winery" />
</owl:Restriction>
</rdfs:subClassOf>
...
</owl:Class>
其中在hasMaker这个property上的allValuesFrom约束只是对wine这个class有意义。上面的allValuesFrom可以被替换为someValuesFrom,约束范围也是类似的。
- Cardinality
我们可以通过Cardinality直接指定于一个class相关的class的数目,例如:
<owl:Class rdf:ID="Vintage">
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#hasVintageYear"/>
<owl:cardinality>1</owl:cardinality>
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>
在OWL Lite中只能指定Cardinality为0或者1,而在OWL Full中,可以使用owl:maxCardinality来指定一个上界。
- hasValue [OWL DL]
hasValue允许我们定义基于特定property的值存在的class。一个individual要成为一个类的成员,它在这个property上的取值必须满足hasValue的规定。例如:
<owl:Class rdf:ID="Burgundy">
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#hasSugar" />
<owl:hasValue rdf:resource="#Dry" />
</owl:Restriction>
</rdfs:subClassOf>
...
</owl:Class>
4.4 Ontology映射
我们需要在Ontology上定义映射关系来重用已有的Ontology的class和property。
- sameClassAs, samePropertyAs
下面是重用类的一个例子:
<owl:Class rdf:ID="Wine">
<owl:sameClassAs rdf:resource="&vin;Wine"/>
</owl:Class>
下面是重用一个类并在其基础上进行约束的例子:
<owl:Class rdf:ID="TexasThings">
<owl:sameClassAs>
<owl:Restriction>
<owl:onProperty rdf:resource="#locatedIn" />
<owl:allValuesFrom rdf:resource="#TexasRegion" />
</owl:Restriction>
</owl:sameClassAs>
</owl:Class>
- sameIndividualAs
它的定义和class类似,说明了两个individual是同一的,例如:
- differentIndividualFrom
该定义与sameIndividualAs的效果正好相反
4.5 复杂的Class【OWL DL】
OWL通过下面的机制给出了定义类表达式的基本方法,从而能够通过嵌套定义给出一个复杂的class。
4.5.1 集合操作符
- Intersection [OWL DL]
下面给出了操作符intersectionOf的用法:
<owl:Class rdf:ID="WhiteWine">
<owl:intersectionOf rdf:parseType="Collection">
<owl:Class rdf:about="#Wine" />
<owl:Restriction>
<owl:onProperty rdf:resource="#hasColor" />
<owl:hasValue rdf:resource="#White" />
</owl:Restriction>
</owl:intersectionOf>
</owl:Class>
注意类操作符是封闭的。
下面是一个通过两次嵌套定义的例子:
<owl:Class rdf:about="#Burgundy">
<owl:intersectionOf rdf:parseType="Collection">
<owl:Class rdf:about="#Wine" />
<owl:Restriction>
<owl:onProperty rdf:resource="#locatedIn" />
<owl:hasValue rdf:resource="#BourgogneRegion" />
</owl:Restriction>
</owl:intersectionOf>
</owl:Class>
<owl:Class rdf:ID="WhiteBurgundy">
<owl:intersectionOf rdf:parseType="Collection">
<owl:Class rdf:about="#Burgundy" />
<owl:Class rdf:about="#WhiteWine" />
</owl:intersectionOf>
</owl:Class>
- Union [OWL DL]
下面是一个使用UnionOf的例子:
<owl:Class rdf:ID="Fruit">
<owl:unionOf rdf:parseType="Collection">
<owl:Class rdf:about="#SweetFruit" />
<owl:Class rdf:about="#NonSweetFruit" />
</owl:unionOf>
</owl:Class>
可以将它和下面的定义作比较:
<owl:Class rdf:ID="Fruit">
<rdfs:subClassOf rdf:resource="#SweetFruit" />
<rdfs:subClassOf rdf:resource="#NonSweetFruit" />
</owl:Class>
- Complement [OWL DL]
下面是一个使用complementOf的例子:
<owl:Class rdf:ID="ConsumableThing" />
<owl:Class rdf:ID="NonConsumableThing">
<owl:complementOf rdf:resource="#ConsumableThing" />
</owl:Class>
下面是一个混和使用了各种集合操作符的例子:
<owl:Class rdf:ID="NonFrenchWine">
<owl:intersectionOf rdf:parseType="Collection">
<owl:Class rdf:about="#Wine"/>
<owl:Class>
<owl:complementOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#locatedIn" />
<owl:hasValue rdf:resource="#FrenchRegion" />
</owl:Restriction>
</owl:complementOf>
</owl:Class>
</owl:intersectionOf>
</owl:Class>
4.5.2 枚举Class
- oneOf [OWL DL]
OWL通过one of操作符给出了枚举一个class的成员的基本方法,例如下面的例子定义了WineColor这个class拥有3个成员:
<owl:Class rdf:ID="WineColor">
<rdfs:subClassOf rdf:resource="#WineDescriptor"/>
<owl:oneOf rdf:parseType="Collection">
<owl:Thing rdf:about="#White"/>
<owl:Thing rdf:about="#Rose"/>
<owl:Thing rdf:about="#Red"/>
</owl:oneOf>
</owl:Class>
? 我们也可以通过直接指定每个成员的类型进行定义:
<owl:Class rdf:ID="WineColor">
<rdfs:subClassOf rdf:resource="#WineDescriptor"/>
<owl:oneOf> rdf:parseType="Collection">
<WineColor rdf:about="#White" />
<WineColor rdf:about="#Rose" />
<WineColor rdf:about="#Red" />
</owl:oneOf>
</owl:Class>
4.5.3 不交的Class
- disjointWith [OWL DL]
它用于表达一个individual是一个class的成员,同时不能是另外一个class的成员。
例如:
<owl:Class rdf:ID="Pasta">
<rdfs:subClassOf rdf:resource="#EdibleThing"/>
<owl:disjointWith rdf:resource="#Meat"/>
<owl:disjointWith rdf:resource="#Fowl"/>
<owl:disjointWith rdf:resource="#Seafood"/>
<owl:disjointWith rdf:resource="#Dessert"/>
<owl:disjointWith rdf:resource="#Fruit"/>
</owl:Class>
定义一个class是几个不交的subclass的union的例子如下:
<owl:Class rdf:ID="SweetFruit">
<rdfs:subClassOf rdf:resource="#EdibleThing" />
</owl:Class>
xml <owl:Class rdf:ID="NonSweetFruit"> <rdfs:subClassOf rdf:resource="#EdibleThing" /> <owl:disjointWith rdf:resource="#SweetFruit" /> </owl:Class>
xml <owl:Class rdf:ID="Fruit"> <owl:unionOf rdf:parseType="Collection"> <owl:Class rdf:about="#SweetFruit" /> <owl:Class rdf:about="#NonSweetFruit" /> </owl:unionOf> </owl:Class>
定义的规模随着不相交类的数目(n)的增长是n2级的。
5 一个完整的制酒行业的Ontology的OWL建模
这个例子是w3c的Guus Schrieber开发的关于制酒行业的更为精细的Ontology。
5.1 相关背景
对于制酒业而言,“产品地域”(production area)是一个非常重要的feature。根据生产地域的谷类的大小酒的类型存在很大的变化,从一个国家到一个特定的葡萄园。我们可以给出四种不同的产品地域:
国家(country),例如France,Italy
区域(region),例如Bordeaux,Medoc,Tuscany
城镇(town),例如Margaux, Montalcino, Montepulciano
葡萄园(vineyard),例如Chateau Margaux,Avignonesi
而且我们必须为不同产品地域之间的关系建模:
区域是国家的一部分:Tuscany在Italy
区域有子区域:Medoc是Bordeaux的子区域
城镇在某区域中:Montalcino在Tuscany
葡萄园在城镇中:Chateau Margaux在Margaux,Avignonesi在Montepulciano
5.2 建模决策
我们决定去掉“town”,将它们都看作region。这样做简化了模型,并且这附和实际中town作为一个产品地域在城镇周边,比城镇面积稍大或稍小的事实。
5.3 模型
5.3.1 Class
```xml
<owl:Class rdf:ID="&vin;ProductionArea"/ >
<owl:Class rdf:ID="&vin;Country:">
<owl:Class rdf:ID="&vin;Vineyard:">
用三元组可以表示为:
vin:ProductionArea rdf:type rdfs:Class.
vin:Country rdfs:subClassOf vin:ProductionArea.
vin:Region rdfs:subClassOf vin:ProductionArea.
vin:Vineyard rdfs:subClassOf vin:ProductionArea.
5.3.2 Property
```xml
<owl:ObjectProperty rdf:ID="&vin;hasSubArea">
<owl:ObjectProperty rdf:ID="&vin;subAreaOf">
<owl:ObjectProperty rdf:ID="&vin;hasRegion">
<owl:ObjectProperty rdf:ID="&vin;regionOf">
<owl:ObjectProperty rdf:ID="&vin;hasSubRegion">
<owl:ObjectProperty rdf:ID="&vin;subRegionOf">
<owl:ObjectProperty rdf:ID="&vin;hasVineyard">
<owl:ObjectProperty rdf:ID="&vin;vineyardRegion">
用三元组表示为:
vin:hasSubArea rdf:type rdfs:Property.
vin:hasSubArea rdf:type owl:TransitiveProperty.
vin:subAreaOf owl:inverseOf vin:hasSubArea.
vin:hasRegion rdfs:subPropertyOf vin:hasSubArea.
vin:hasRegion owl:allValuesFrom vin:Region.
vin:regionOf owl:inverseOf vin:hasRegion.
vin:regionOf owl:allValuesFrom vin:Country.
vin:regionOf owl:cardinality 1.
vin:hasSubRegion rdfs:subPropertyOf vin:hasSubArea.
vin:hasSubRegion owl:allValuesFrom vin:Region.
vin:subRegionOf owl:inverseOf vin:hasSubRegion.
vin:subRegionOf owl:allValuesFrom vin:Region.
vin:subRegionOf owl:cardinality 1.
vin:hasVineyard rdfs:subPropertyOf vin:hasSubArea.
vin:hasVineyard owl:allValuesFrom vin:Vineyard.
vin:vineyardRegion owl:inverseOf vin:hasVineyard..
vin:vineyardRegion owl:allValuesFrom vin:Region.
vin:vineyardRegion owl:cardinality 1.
5.3.3 UML注释
6 紧急联动的一个简单建模
6.1 UML模型(应急联动机构)
6.2 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>
7 一个比较复杂的应急联动的建模
略
8 Jena—语义网建模的Java API
8.1 简介——几个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);
【例二】:下面给出了在例一的基础上得到的一个相对复杂的有向图:
与上面不同的是,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));
8.2 Jena与整个建模流程
8.2.1 陈述(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的公共超类。
8.2.2 书写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:
model.write(new PrintWriter(System.out), "RDF/XML-ABBREV");// now write the model in XML form to a file
这个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");
8.2.3 读取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,所以可以为空。
8.2.4 关于Jena的RDF包
最新版本已不再使用使用
com.hp.hpl.mesa
命名空间
l 语义网应用开发人员使用Jena时的最重要的包是com.hp.hpl.mesa.rdf.jena.model
。这个包包含了用于表达model、resource、property、literal、statements以及其他RDF的关键的接口;
l com.hp.hpl.mesa.rdf.jena.tutorial
包包含了与Jena一同发布的指南中所使用的例子的源代码;
l com.hp.hpl.mesa.rdf.jena.mem
包包含了用于将整个模型状态装入内存的Jena API的实现。凡是创建基于内存的模型(最典型的是创建ModelMem类的实例)的实现都在本包中;
l com.hp.hpl.mesa.rdf.jena.common
包包含了对于诸多实现通用的实现类。例如,它定义了类ResourceImpl, PropertyImpl, LiteralImpl。开发者一般不要直接使用这里的方法,例如不直接使用ResourceImpl,而使用createResource方法。这是为了保证在实现发生优化后不需要进行类型转换;
l com.hp.hpl.jena.rdf
为RDF包。
8.2.5 在RDF有向图中的导航
给出一个resource的URL,可以使用Model.getResource(String uri)方法从图中得到该资源所对应的对象。如果对应的resource存在,则返回该resource的对象,否则将创建一个新的对象。例如:
Resource vcard = model.getResource(johnSmithURI);// retrieve the John Smith vcard resource from the model
? Resource接口定义了一系列方法用于访问一个Resource的Property。Resource.getProperty(Property p)方法用于访问一个resource的一个property。同以往的Java API不同的是该方法返回的是整个Statement对象,然后通过该对象的访问方法来得到Property的值。例如想得到vcard:N这个property的值所对应的resource,代码如下:
Resource name = (Resource) vcard.getProperty(VCARD.N).getObject();// retrieve the value of the N property
? 由于property的值可能为resource或者literal,而我们已经知道上面得到的值为resource,所以进行了强制类型转换。Jena也提供了特定类型的访问方法,从而不需要在编译时进行类型转换。所以上面的代码也可以写成:
Resource name = vcard.getProperty(VCARD.N).getResource();// retrieve the value of the FN property
类似,如果property的值为literal,则可以写成:
String fullName = vcard.getProperty(VCARD.FN) .getString();// retrieve the given name property
? 上面的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
8.2.6 关于图的查询
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而后依次测试之,而后者允许使用应用实现本身维护的索引来提高性能。
8.2.7 对图的操作
Jena提供了3种针对图这一整体进行的操作——即典型的集合操作:并(union)、叫(intersection)和差(different)。
对两张图取并就是对两张图所包含的statement取并,这是为了支持RDF所给出的一个关键操作,它使得不同数据源的数据能够被合并。给出下面的两张图:
它们可以被合并为:
上面的操作的代码是:
// 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>
交和差操作与此类似。
8.2.8 相关异常
目前Jena的异常机制不很受欢迎,它将在将来得到改进。由于Jena被设计成具有很高的灵活性并且支持不同的存储系统,所以存储管理器可以在任何时候给出一个非预期的错误。所以几乎所有的Jena方法在结尾都要注明要抛出RDFException异常。经验证明这不是一个好方法,当抛出异常时,通常这些异常都应该被忽略,检查出这些异常没有任何好处。
8.2.9 容器(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类提供的用于操纵容器的方法包括:添加新成员、插入成员到容器的成员中部、删除成员等。
8.2.10 有关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。而且要么都没有语种标签,要么有的话标签相同。