原文(original):
Primer: Getting into RDF & Semantic Web using N3
http://www.w3c.org/2000/10/swap/Primer.html
译文(translation):
入门教程:使用 N3 初探 RDF 和 Semantic Web
http://www-staff.it.uts.edu.au/~cwang/2006/05/Primer.zh-CN.html
译者(translator):
王超 (Wang, Chao)
说明(notes):
本文档的英文版是唯一的正式版本。译注的内容是非正式的,如有出入,请参考原文。 虽然译者尽力使译文精准,不足之处仍难免存在,欢迎指正。

W3C | Semantic Web| Advanced Development | SWAP | Tutorial | Primer

入门教程:使用 N3 初探 RDF 和 Semantic Web

[其他语言版本]

从其根基上讲,基于RDF的semantic web的世界,其实是很简单的。这篇文章教你如何开始。本文会使用一种简化的教学语言即 Notation 3,或者叫 N3。 这种语言基本上等同于使用XML语义的RDF,但是对初学者来说,它相对容易编写。

主语,动词以及宾语

在 RDF 中,信息简单地讲就是一组语句,每个语句包括主语,动词,宾语,仅此而已。 在 N3 中,你可以像下面那样书写一个 RDF 三元组,并在末尾附上一个句号:

<#pat> <#knows> <#jo> .

任何东西,主语,动词,或者宾语也好,都是通过统一资源标识符(Uniform Resource Identifier,URI)来标识的, 就像这样:<http://www.w3.org/> 或者 <http://www.w3.org/2000/10/swap/test/s1.n3#includes>, 但当 "#" 之前的所有东西 被省略掉后,它就把 <#pat> 标识在当前文档中,不管这个“它”是什么。

有一个例外,宾语(仅宾语)可以是一个字面常量,比如字符串(string), 或者整数(integer):

<#pat> <#knows> <#jo> .
<#pat> <#age> 24 .

动词 "knows" 在RDF中被称为“属性(property)”,并且被认为是用来表达两者之间 一种关系的名词。事实上,你可以这样写:

<#pat> <#child> <#al> .

你也可以选择像下面那样书写,使其更易阅读

<#pat> has <#child> <#al> .

或者

<#al> is <#child> of <#pat> .

当对一个相同的主语你有若干个语句时,可以有这么两个快捷方式: 用一个分号 ";" 引入相同主语的其他属性;用一个逗号引入相同主语及谓语的其他宾语。

<#pat> <#child>  <#al>, <#chaz>, <#mo> ;
       <#age>    24 ;
       <#eyecolor> "blue" .

这样,举例来说,对于下面表格中的数据

age eyecolor
pat 24 blue
al 3 green
jo 5 green

可以写成这样:

  <#pat>   <#age> 24;  <#eyecolor> "blue" .
  <#al>    <#age>  3;  <#eyecolor> "green" .
  <#jo>    <#age>  5;  <#eyecolor> "green" .

有时会出现这样情况,你有一个语句但不想费劲给它一个标识符 -- 你知道有这么个东西存在, 但你只是想描述它的属性。你可以用方括号(其中包含要描述的属性)来表示它。

<#pat> <#child> [ <#age> 4 ] , [ <#age> 3 ].

这个可以读成这样: #pat 有一个 #child,它的 #age 是 "4" ,另有一个 #child,它的 #age 是 "3" 。有两点很重要需记住。

如果我们确实想使用名字(name), 我们可以将前面提到的表格写成这样:

  [ <#name> "Pat"; <#age> 24;  <#eyecolor> "blue"  ].
  [ <#name> "Al" ; <#age>  3;  <#eyecolor> "green" ].
  [ <#name> "Jo" ; <#age>  5;  <#eyecolor> "green" ].

对于如何组合方括号,可以有很多方法 -- 你今后可以根据例子自己揣摩出。 关于使用 N3 来表现数据,我们剩下要学的已经不多了,让我们继续。

共享概念(concepts)

Semantic web 无法在一个文档里把某某东西是什么定义完,你在英语这个语言里面可以这么做(或许有时在数学里也可以这样),但当我们真正在用一个概念,例如“标题”,进行沟通交流时(比如在一个国会图书馆的目录卡上,或者在一个网页上),我们依赖于一个关于“标题”的共享概念。在 semantic web 上,对于一个概念,我们通过使用一个完全相同的统一资源标识符(URI)来精确地共享它。

我想通过下面的方式来给一个 N3 文档起个标题

<> <#title>  "N3 的一个简单示例".

(以上的 <> 作为一个空的 URI 引用,总是引用当前正在书写的文档。) 而 <#title> 引用了这个文档自身所定义的 #title 概念。 这对读者来说没有多大意义。但是,有一伙人创作了一组属性叫做 Dublin Core,在这组属性里,其中就有标题(title),并且他们赋予了标识符给它。

<http://purl.org/dc/elements/1.1/title>. 于是,我们就可以像下面那样定义一个更好的语句

<> <http://purl.org/dc/elements/1.1/title>
 "入门教程 - 使用 N3 初探 semantic web 和 RDF".

显然,那样做会比较繁琐 -- 试想一下对于以上提到的 #age 及 #eyecolor 或任何其他东西都要用这么长的标识符。 于是 N3 允许你创建一个快捷前缀代表那长的一部分 -- 这部分我们称为 名字空间 (namespace) . 你用 "@prefix" 来设置它,就像这样:

@prefix dc:  <http://purl.org/dc/elements/1.1/> .
<> dc:title
  "入门教程 - 使用 N3 初探 semantic web 和 RDF".

请注意,当你使用前缀时,你在 dc 和 title 之间使用的应该是冒号(:),而不是井字符(#)。并且,你不需在整个上使用 <尖括号>。 这样就会很快。这个就会是你在 N3 中看到的,并且也会是你所写的几乎所有谓语的样子。一旦设置好,一个前缀可在文件的随后部分任意使用。

你会有越来越多的 RDF 词汇可以引用 -- 查看一下 RDF 的主页 以及它所给的连接 -- 另外,你也可以很容易地为你的应用程序创建你自己的词汇。

接下来,我们会使用一些常见的名字空间,并且为了节省空间,我将假设如下的前缀

@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl:  <http://www.w3.org/2002/07/owl#> .

它们分别是 RDF, RDF schema, 以及 OWL 的名字空间。它们为我们提高了核心的词汇(术语),使我们可以很快地进入 semantic web 。我还将假设空前缀表示我们当前正在写的文档,这在 N3 里表示如下

@prefix : <#> .

这意味着我们可以将前面的例子表示成如下

:pat :child [ :age 4 ] , [ :age 3 ].

这样可以少打一些字符。现在你明白了怎样用 N3 来书写数据,那你可以开始创建你自己的词汇了,因为词汇它们本身也就是数据。

制作词汇集

前面提到的像 dc:title 这样的东西叫做 RDF 属性(Properties). 当你想定义一个新的词汇集,你需要定义一些新的类和新的属性。当你想要表达某个东西是什么类别时,你需要一个它所属的类(Class)

用来告诉你某个东西属于什么类别的属性叫 rdf:type,这个属性在 N3 里可以简写成 a。这样,我们可以定义这个人物(person)类:

:Person a rdfs:Class.

在同一个文档里,我们可以引入一个实际人物:

:Pat a :Person.

类告诉你某个东西的归属。一个东西可以属于很多类。[类与类]之间并不一定要有层次关系 -- 试想一下如下的类:Person, AnimateObject, Animal, TallPerson, Friend 等等[它们之间并不一定要有什么关系]。[当然,]如果两个类之间有某种关系,你可以表示出来 - 请参考 RDF Schema 以及 OWL 词汇集中的(类的)诸多属性。

:Woman a rdfs:Class; rdfs:subClassOf :Person .

属性(property)是用来声明两个东西之间的某种关系。

:sister a rdf:Property.

有时当某种关系存在于两个东西之间,你可以很快了解它们的一些情况,你还可以将它们用类(class)的形式表达出来。 当任一属性的主语[主体](subject)必须属于某个类时,这个类便是这个属性的 定义域(domain)。当其宾语[客体](object)必须属于某个类时,这个类称为这个属性的 值域(range)。一个属性可以有很多定义域和值域,但一般总是[定义域和值域]一一对应的。

:sister rdfs:domain :Person; 
        rdfs:range :Woman.

需要注意的是,类标识符的首字母是大写的,而属性标识符的首字母是小写的。这不是一个规定,但这是一个很好的约定值得遵守。另外需要注意的是,因为 rdfs:range 及 rdfs:domain 本身的定义域就是 rdf:Property (即属性),所以 :sister 便是一个 rdf:Property,而不需要明确说明了。

等同性(Equivalence)

在你定义一个词汇集时,不管你刚开始时有没有意识到,其中通常会有一个或多个词实际上就等同于另外一个词汇集里某个词。这种情况,对于处理信息的人或机器来说很有用!两个词之间这种等同的属性是如此的有用和重要,以致 N3 专门为此提供了一个简写符:“=”。

:Woman = foo:FemaleAdult .
:Title a rdf:Property; = dc:title .

提示:如果可以,就[尽量]使用其他人的词汇集 - 这样有助于数据的交换。当你定义你自己的词汇集,且词汇集包含同义词时,请尽量记录等同性,因为这样也有助于当前和今后的处理程序能有效地处理你和他人的数据。

选一个名字空间发表你的词汇集

好的词汇集的在线文档有助于人们读写 RDF 数据。撰写者需要知道一个词该怎么用;阅读者需要知道它代表什么意思。使用这些词的软件开发者特别需要详细知道每个 URI 所代表的含义。

如果你使用 RDF Schema 以及 OWL 词汇集来制作你自己的词汇集,你的文档将在很多种有趣且有用的情况下是机器可读的。这就像前面我们所提及的那样,这在词汇集文档(Vocabulary Documentation) 中有很详细的讨论。 这种RDF中的RDF文档有时叫做 “schema” 或者 “本体(ontology)”

让人们能很容易地找到你的文档的最简单的方法是:让你制作的那些做为词汇的 URI 能够被万维网浏览器所接受。如果你能够照着我们这儿的命名约定,即词汇定义文档的 URI 做成像 http://example.com/terms 这样,且它像 <#Woman> 这样引用其中的词,那么你的文档就可以自动地被浏览器所接受。根据前面给出的 @prefix 的声明,这样就会得到 http://example.com/terms#Woman 这样的 URI,于是,任何浏览器都可以显示这样的定义文档。

理想情况下,你要发布你的文档到万维网上去,就得使用一个服务器以及一部分的 URI 空间,最好是它们属于一个组织,这个组织愿意一直很好地去维护它们。那样地话,许多年过去之后,那些使用了你的词汇的 RDF 数据还将被很好地记录着,且还可能被[人们/机器]理解。[另外],把当前的年份放入 URI 的约定做法会有助于稳定性;某天人们也许会想重新使用 http://example.com/food-vocabulary, 但当他们真的想升级文档时,也许只是更新一下http://example.com/2003/food-vocabulary。在某些场合下,通过使用一个特别的域名(它得不会因为可能的机构重命名而改变,也没有商标问题), 你也可以达到提高稳定性的目的。

当然,如果你只是想玩玩,你可以使用一个文件(比如mydb.n3),把它跟其他你的文件放在同一个目录里。当你那样做的话,你可以简单地使用 <mydb.n3#> 作为你的名字空间标识符,因为在 N3 中(就像在 HTML 中),URI 可以用相对当前位置的方式来表示。

更多

现在,你了解了所有你需要知道的,可以开始创建你自己的词汇集或者本体(ontologies), 且你有一些指示链接,从那儿可以找到定义它们[词汇集等]的更多的方法。[其实]你不必走那么远深入进去,因为你现在所了解的[已经]可以允许你建立新的应用,创建新的 schemas ,数据文件,以及那些可以交换和处理语义万维网数据的软件程序。

到此,你该停下来,自己写点东西了。不过为了让你有点主意,这儿有一个 更长的列表,包含了更复杂和多样的例子。这些例子的指导性解释要少些。

或者,你可以继续看另外一个教程,它会深入讨论这个语言的更多特性,会解释如何处理你的数据以及万维网上的其他数据。你想那样的话,接下来要看的便是关于: “近路”和“远路”(Shortcuts and long cuts)


参考资料

Tim BL, with his director hat off
$Id: Primer.zh-CN.html,v 1.3 2006/05/26 05:41:43 cwang Exp $