如果我们对该模型运行这一查询,我们将得到一列资源(因为 rdf:type 语句的对象是资源)。如果我们正在使用一个可以有文字和资源对象的谓词,结果将是一列文字和资源。要使用 4Suite 测试它(有关 4Suite 的详细信息,请参阅以前的专栏文章),可以将清单 1 复制到文件 issues.rdf,然后在命令行中执行用红色突出显示的命令:
$4versa --rdf-file=issues.rdf "all() - rdf:type - *"::: Using cDomletteExecuting Query:all() - rdf:type - *With nsMapping of:vtrav -- http://rdfinference.org/versa/0/2/traverse/xml -- http://www.w3.org/XML/1998/namespacevsort -- http://rdfinference.org/versa/0/2/sort/rdfs -- http://www.w3.org/2000/01/rdf-schema#rit -- http://rdfinference.org/schemata/issue-tracker/it -- http://rdfinference.org/schemata/issue-tracker/rdf -- http://www.w3.org/1999/02/22-rdf-syntax-ns#foaf -- http://xmlns.com/foaf/0.1/versa -- http://rdfinference.org/versa/0/2/None -- http://rdfinference.org/schemata/issue-tracker/daml -- http://www.daml.org/2001/03/daml+oil#List Resourcehttp://rdfinference.org/schemata/issue-tracker/Issue/Resource Resourcehttp://rdfinference.org/schemata/issue-tracker/Issue/Resource/List(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/webkaifa/)
以简单 XML 形式表示的产生的资源列表是用粗体显示的。该命令的其它输出只是为您提供一些信息。它回显正在被执行的 Versa 查询,并显示引擎知道的名称空间声明。为了方便用户,4versa 自动抓取源文件根元素内的所有名称空间声明。
细述遍历
通常,遍历表达式的格式如下:
list-expression - list-expression - boolean-expression
列表表达式是返回一列资源或可以被转换成一列资源的结果的任何表达式。因此,任何返回单个资源( rdf:type )的表达式都会被转换成具有单个输入项的列表类型。您已经看到过缩写成如 rdf:type 的形式和称为限定名称(或 QNames )形式的 RDF URI。通过将第一部分扩展成 URI 库(例如 rdf 变成 http://www.w3.org/1999/02/22-rdf-syntax-ns# )然后同第二部分连接,将它们转换成完整的 URI。这样, rdf:type 就变成了 http://www.w3.org/1999/02/22-rdf-syntax-ns#type 。Versa 也允许您以完整、冗长和详细地方式拼写出 URI,这意味着您可以直接编写 @"http://www.w3.org/1999/02/22-rdf-syntax-ns#type" 。例如:
all() - @"http://www.w3.org/1999/02/22-rdf-syntax-ns#type" - *
遍历表达式的第三部分是布尔表达式。我已经向您演示了如何使用 * 选择所有对象。您也可以对结果做更多的选择。例如,要获取模型中资源的所有日期特性,您可以使用:
all() - dc:date - *
它产生:
List String2001-03-04/String String2001-04-20/String/List
要选择特定日期,您可以编写:
all() - dc:date - eq("2001-04-20")
eq 函数将参数同上下文比较,如果它们相同,就返回 true。Versa 中上下文的思想类似于 XPath 中上下文的思想,但是更简单。在 Versa 中,上下文是一个在对表达式求值时考虑的单一值。可以使用点符号直接访问上下文。也可以使用 eq 函数比较两个显式参数,因此上面的内容可以按如下编写:
all() - dc:date - eq(., "2001-04-20")
在遍历表达式的第三部分中,上下文是第一和第二部分的部分结果之一。例如,在上面,将每个对象都同2001-04-20比较,最后的结果是比较值为 true 的对象列表,在这个示例中:
List String2001-04-20/String/List
图 2 演示了遍历表达式的某些工作。
图 2. 遍历表达式的工作演示
这一看起来明显的查询在确定某个特定值是否是模型时十分有用。例如,如果您在上面的示例中用2001-03-15替换2002-04-20,那么结果将是一个空列表。当然您可以使用遍历表达式做更多的事情。例如,要检索三月份所有日期的资源,您可以编写:
all() - dc:date - contains("-03-")
它产生:
List String2001-03-04/String/List
向后遍历
获得具有特定日期的 资源 可能更有用。要做到这一点,您需要向后操作,从 dc:date 圆弧所对应的日期到主题资源。Versa 以向后遍历的形式提供这一操作。例如:
"2001-03-04" - dc:date - *
返回所有日期为2001-03-04的资源:
List Resourcehttp://rdfinference.org/ril/issue-tracker/i2001030423/Resource/List
向后遍历的形式是:
list-expression - list-expression - boolean-expression
其工作方式与向前遍历十分类似。这两种遍历都可以链接,这样就可以获取日期为2001-03-04的所有资源的标题:
("2001-03-04" - dc:date - *) - dc:title - *
它产生:
List StringUnnecessary abbreviation/String/List
分配财富
到目前为止,所有查询都返回单一值。通常,您可能希望一次返回多个值。Versa 使用列表操作实现这一点,列表操作运行在遍历表达式的结果之上。处理列表的一个常用函数是 distribute ,它对列表中的每项使用一个或多个表达式。结果是列表的一个列表。可以使用如 list(rit:i2001030423, rit:i2001042003) 这样的表达式在 Versa 中直接表达列表,该表达式是两个资源的列表。下面的表达式获得这些问题中每个问题的标题和日期:
distribute(list(rit:i2001030423, rit:i2001042003), ".-dc:title-*", ".-dc:date-*")
它产生列表的列表:
List List List StringUnnecessary abbreviation/String /List List String2001-03-04/String /List /List List List StringInconsistent versioning/String /List List String2001-04-20/String /List /List/List
distribute 函数的第一个参数是一个列表。依次获取列表中的每一项。第二个和后续的参数为字符串,它们被当作子查询。使用上下文的当前列表项对它们进行动态求值(如同前面所讨论的一样,通过使用点来引用)。图 3 演示了该查询是如何工作的。
图 3. distribute 的工作演示
可以对遍历表达式的结果(它们是列表)使用该技术。再举最后一个例子,我将解释如何使用 Versa 中的一个特殊快捷函数。 type 函数检索给定 RDF 类型(就象用 rdf:type 谓词表达那样)的所有资源。要获取所有已经提交问题的人的标识和姓名,可以编写:
distribute(type(it:Issue)-dc:creator-*, ".", ".-foaf:name-*")
请注意,您可以在子表达式中直接使用上下文,而无须使之成为另一个表达式的一部分。结果是:
List List Resourcemailto:Nicolas.Chauvat@logilab.fr/Resource List StringNicolas Chauvat/String /List /List List Resourcemailto:Alexandre.Fayolle@logilab.fr/Resource List StringAlexandre Fayolle/String /List /List/List(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/webkaifa/)
这里有一个棘手的细节。 .-foaf:name-* 子表达式产生的字符串在列表中,但由 . 子表达式产生的资源却不在其中。这是因为遍历操作符总返回列表,即使结果中只有一个或没有项时也是如此。由于我们知道在我们的模型中,我们仅仅期望每个人的资源只有一个单一名称,所以我们无论如何总是忽略列表的最低一级。Versa 提供数据转换函数,其中之一是 string 函数,它将其参数转换成字符串。通过获取列表的第一(或唯一的)项的字符串值来转换列表。因此,
distribute(type(it:Issue)-dc:creator-*, ".", "string(.-foaf:name-*)")
消除了遍历子表达式周围的无关列表并产生以下结果:
List List Resourcemailto:Nicolas.Chauvat@logilab.fr/Resource StringNicolas Chauvat/String /List List Resourcemailto:Alexandre.Fayolle@logilab.fr/Resource StringAlexandre Fayolle/String /List/List
结束语
在本文中,我解释了 Versa 的基础知识。如果您掌握了它,那么您立即可以使用它来高效地工作。Versa 有多得多的功能,但是它们大部分是以专门的函数的形式出现,通过使用它们,您将迅速获得经验。参考资料一节列举了更多关于 Versa 的参考资料。在下一篇专栏文章里,我将解释如何使 Versa 满足到目前为止在本系列中讨论的所有查询需要。