RDF的目标是很简单的。他提供一种以机器可以理解的方式来记录数据的方法,允许更有效和更复杂的数据交换,搜索,编目,导航,分类等等。当然他不是仅仅能够做这些工作。
目前的搜索引擎的问题是搜索出来的结果仅仅是一些内容的罗列。比如一个超级没有意思的例子,如果我们baidu“苹果”,我们可能得到各种各样的信息,包括出售苹果的信息,苹果电脑的信息,制作苹果馅饼的信息,甚至可能有苹果味汽水的信息。发生这种事情的原因是搜索引擎仅仅使用关键字来搜索信息,而没有考虑到被资源的领域以及用户所感兴趣的领域。搜索的依据是蜘蛛程序从Web页面上找到的关键字。
一个好一点的方法是给相关的信息加上领域信息。比如一篇文本是苹果电脑公司的一系列新产品推荐文章中的一个,这个东西的销售信息可以在什么地方找到,关于他的用户评论在什么地方,等等。这些信息就构成了一个更为丰富的视图,并且远远好于原来的一维的关键字搜索。
现在的关键字搜索所缺乏的是关于Web资源的的描述能力,比如作者,标题,文章所述的系列,相关文章,主题等等信息。
很显然关键字搜索不能得到这些信息,至少不能用一种计算机可以比较容易理解的方式得到这些信息。
RDF提供了这种能力,并且由于RDF的中立性,他还支持这种信息的合并。这样以来关心不同应用的程序可以各取所需,更好的为用户服务。
RDF的这种目的让我想起了baidu的搜索联盟和开放搜索协议。或者说,baidu有可能就是受了这种思想的启发才发动了搜索联盟。这是一个不错的想法,尤其是现在的大量网站其实都是通过程序半自动生成的情况。只要修改一下页面生成程序,让他针对每一个页面再生成一个开放搜索XML或者RDF文档,就可以最大化搜索效果。只不过这种应用对于一些个人站点来说有点稍微恐怖了。并且对于很多站点,尤其是IT类站点,很多还是靠美工(他们也只能被称为是美工,而不是UI设计师)用DreamWaver等等软件画出来的,不要说指望他们能RDF了,连HTML 4.01标准他们都不能达到。所以这个东东的实现能力还是有待研究。
RDF使用三元组来记录信息。三元组包含三者部分,分别是主体,属性和值。这更像是很多个陈述句组成的记录,比如这篇文档(主体)的作者(属性)是我(值)。对于RDF来说,可能就是这么记录这样的信息的:
这篇文档(无论你用什么方式表达,比如URI)——作者(这可以是一个Common Sense)——我(可以使用我的电子邮件来表示我,或者我的Blog地址,随应用需要)
恩,看起来很计算机的一种表达方式,不过很有效,也很好理解,不是吗。
对于这篇文档,可能还有很多其他的属性,那就一个一个描述,比如这篇文档的状态是尚未完成(至少我在写他的时候是),这篇文档发布于BlogJava,等等。
不过三元组只是序列化RDF数据的一种方法。标准的表示数据的方法还是一张直观的RDF图。其他的方法还包括N-三元组以及大家都觉得看起来更专业的RDF/XML。不过无论怎么样,记住,RDF其实是图,而用图去理解他,一切就变得很容易了。
另外我很不喜欢这种所谓“序列化”的说法,就好像我很不喜欢“形而上学”这个词一样。序列化给我的感觉更像是在讨论C#或者别的什么,而不是RDF。
RDF核心工作组决定使用RDF图——有向的带有标签的图——作为RDF的默认的描述RDF数据模型的方法。这么做有两个原因:好读而没有歧义,并且有些可以使用RDF图来描述的东西使用RDF/XML是无法描述的。
RDF有向图由一系列由边连接的节点组成,形成一个点-边-点的模式。进一步的,节点有三种类型:uri引用(uriref),空节点(blank nodes)以及文本(literals)。
uri引用节点使用uri来引用一个特定的资源,但是这个资源并不一定非要在网上能找到才可以。事实上,当RDF被广泛使用的时候,这种要求几乎是不可能实现的。当一个资源的uri在构建RDF图的时候还是不可用的,或者这个节点本身并不重要,那么就可以使用空节点。uri引用节点使用椭圆表示,里面写上uri,空节点使用空白的圆表示。有些自动生成的图可能使用一个带有临时uri的圆来表示空节点。文本节点包含三个部分,正文内容以及可选的语言标识和数据类型。文本值只能表示RDF对象,不可以作为主体和属性使用。在RDF图中会使用一个长方形包裹着文本内容。
来自RDF Primer的图片是一个不错的例子。
空节点是有效的RDF,但是很多程序都会生成一个临时uri来表示空节点。在
《RDF和Jena RDF API入门(2)》中就有一个jena输出的例子:
http://somewhere/JohnSmith http://www.w3.org/2001/vcard-rdf/3.0#N anon:14df86:ecc3dee17b:-7fff .
anon:14df86:ecc3dee17b:-7fff http://www.w3.org/2001/vcard-rdf/3.0#Family "Smith" .
anon:14df86:ecc3dee17b:-7fff http://www.w3.org/2001/vcard-rdf/3.0#Given "John" .
http://somewhere/JohnSmith http://www.w3.org/2001/vcard-rdf/3.0#FN "John Smith" .
上面的那些谁也看不懂的数字字母冒号的混合就是空白节点临时uri的例子。
到目前位置RDF似乎都很简单,但是他的复杂性应该是随着应用的复杂而边的复杂的——因为RDF几乎没有什么约束,所以他的可能性应该是无限的。
说到这里不得不提一下,我在这里写的东西更倾向于一种理解,而不是准确的描述,所以并不会很注重细节,而更强调了解。如果需要准确的定义和描述,应该看看W3C的文档。
由于uri节点是RDF的核心,所以关于uri有必要多了解一些。关于uri更详细的内容可以去baidu一下,不过这里有一个很重要的东西,那就是符号“#”。这个东东在做网页的时候经常用到,比如http://www,example.com/AboutUs.htm#Fax表示了页面AboutUs.htm的Fax区段,用在RDF里面也是类似的效果,比如http://www.example.com/ontology.owl#Class1表示example.com的某一个本体的Class1类。
这里书中提到了有趣的东西:URI,URL和URN的区别。URI是Uniform Resource Identifier,可以用来表示一个资源的名字,也可以表示地址。而URL只能表示地址,URN只能表示名字。哎……我怎么连这个都不知道……
RDF说明允许使用绝对URI和相对URI,比如http://www.example.com/index.htm和index.htm。当使用相对URI的时候,如果没有指定Base URI,那么就假设Base URI是当前RDF的地址。怪不得Redland总需要指定一个base_uri参数,而且默认值还是nil,原来如此。
把RDF图序列化,除了可以使用RDF/XML之外,另一种方法是使用N-三元组。使用N-三元组的好处是可以确保序列化和反序列化的结果是相同的(似乎是针对RDF/XML不能处理空白节点的缺点)。而N-三元组是基于另一个标记法:N3。Protege就支持这种形式的导出,支持导入嘛?好像不吧,没注意。
基本的N3三元组是这样的:
subject predicate object .
晕,这不是RDF用来表示数据的三元组表示嘛。好了,一切到这里就没有悬念了,直接给一个例子,事实说明一切。
<http://www.example.com/index.htm> <http://purl.ont/dc/elements/1.1/creator> Tim .
看清楚了哦,这可不是XML或者什么Markup Language,虽然他也有<>。当然为了简单起见,还是可以借鉴一点XML的技术的,比如QNames。并且,如果使用了QNames,那么对于谓词就可以省略<>。
关于QName,我还特意baidu了一下下,结果如下:QName是qualified name的简写,由名字空间(namespace)前缀(prefix)以及冒号(:)组成,还有一个元素名称构成,比如xsl:stylesheet。(靠,啥都不懂)
上面的例子就可以写成:
<exp:index.htm> dc:creator Tim .
对于空白节点则可以使用任何东西来代替他,比如刚刚看到那个例子:
http://somewhere/JohnSmith http://www.w3.org/2001/vcard-rdf/3.0#N anon:14df86:ecc3dee17b:-7fff .
anon:14df86:ecc3dee17b:-7fff http://www.w3.org/2001/vcard-rdf/3.0#Family "Smith" .
anon:14df86:ecc3dee17b:-7fff http://www.w3.org/2001/vcard-rdf/3.0#Given "John" .
http://somewhere/JohnSmith http://www.w3.org/2001/vcard-rdf/3.0#FN "John Smith" .
由于N-三元组是N3的子集,他支持RDF三元组的同样的格式。
Subject predicate object .
以及使用“#”开头的注释,就像ruby一样。记得把一个三元组写在一行上。而且同一行上不能同时有三元组和注释。
当然这里说的十分不详细,如果需要比较具体的规范,还是应该参看W3C的文档。