XQuery/DBpedia 使用 SPARQL 和 Simile 时间线 - 专辑年表
在本例中,SIMILE 项目的 时间线 JavaScript 用于显示所选艺术家或乐队发布的专辑年表。与之前示例中的足球队一样,数据通过 SPARQL 查询从 DBpedia 提取。
本例包含三个组件
- 一个 XQuery 脚本,用于创建 HTML 页面,链接到时间线 JavaScript
- 一个 XQuery 脚本,用于查询 DBpedia 获取所选乐队的专辑,为每个专辑分配发行年份,并生成时间线脚本预期的事件集。
- 一个 XQuery 脚本,用于提供给定类别中的乐队索引
该脚本接受一个参数,即艺术家或乐队的名称。用于自定义时间线的 JavaScript 在 CDATA 部分中定义为内联。onLoad 函数接受两个参数,即艺术家的姓名和日期,用于为时间线提供初始焦点。事件流由对 XQuery 脚本 group2tl.xq 的调用提供,传递组名。
这里的 JavaScript 接口非常简单。
declare option exist:serialize "method=xhtml media-type=text/html";
let $group:= request:get-parameter("group","Eagles")
return
<html>
<head>
<script src="http://simile.mit.edu/timeline/api/timeline-api.js" type="text/javascript"></script>
<script type="text/javascript">
<![CDATA[
function onLoad(group,start) {
var theme = Timeline.ClassicTheme.create();
theme.event.label.width = 400; // px
theme.event.bubble.width = 300;
theme.event.bubble.height = 300;
var eventSource1 = new Timeline.DefaultEventSource();
var bandInfo = [
Timeline.createBandInfo({
eventSource: eventSource1,
theme: theme,
date: start,
width: "100%",
intervalUnit: Timeline.DateTime.YEAR,
intervalPixels: 45
}),
];
Timeline.create(document.getElementById("my-timeline"), bandInfo);
Timeline.loadXML("group2tl.xq?group="+group, function(xml, url) { eventSource1.loadXML(xml, url); });
}
]]>
</script>
</head>
<body onload="onLoad('{$group}',1980);">
<h1>{$group} Albums</h1>
<div id="my-timeline" style="height: 700px; border: 1px solid #aaa"></div>
</body>
</html>
此脚本与足球队脚本的结构类似。一个原型 SPARQL 查询被编辑以更改默认名称为提供的名称,查询发送到 DBpedia SPARQL 服务,并将生成的 SPARQL XML 结果转换为 XML 元组。
注意 - 乐队名称需要额外的编码,因为 SPARQL 要求 URI 进行 uri 编码,而乐队名称可能包含诸如 ( 和 ) 之类的字符,这些字符需要编码。因此,Queen_(band) 必须以 Queen_%28band%29 的形式出现在 SPARQL 中的 URI 中。此外,整个查询被 uri 编码,这允许在整个查询被 SPARQL 服务解码时恢复这种编码。(真厉害!)
与足球俱乐部一样,同一张专辑可能有多个元组,并且需要从这些元组中提取最佳数据(目前只是第一个非空数据)。发行年份从可能出现的多种日期格式中提取出来,并且每个专辑以时间线期望的格式表示,弹出内容被序列化。这仅限于可用的专辑封面以及指向 DBpedia 和维基百科的链接。
declare namespace r = "http://www.w3.org/2005/sparql-results#";
declare variable $query := "
PREFIX p: <http://dbpedia.org/property/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT * WHERE {
?album p:artist <http://dbpedia.org/resource/The_Allman_Brothers_Band>.
?album rdf:type <http://dbpedia.org/class/yago/Album106591815>.
OPTIONAL {?album p:cover ?cover}.
OPTIONAL {?album p:name ?name}.
OPTIONAL {?album p:released ?dateofrelease}.
}
";
declare function local:execute-sparql($query as xs:string) {
let $sparql := concat("http://dbpedia.org/sparql?format=xml&default-graph-uri=http://dbpedia.org&query=",
encode-for-uri($query)
)
return doc($sparql)
};
declare function local:sparql-to-tuples($rdfxml ) {
for $result in $rdfxml//r:result
return
<tuple>
{ for $binding in $result/r:binding
return
if ($binding/r:uri)
then element {$binding/@name} {
attribute type {"uri"} ,
string($binding/r:uri)
}
else element {$binding/@name} {
attribute type {$binding/@datatype},
string($binding/r:literal)
}
}
</tuple>
};
declare function local:clean($text) {
let $text:= util:unescape-uri($text,"UTF-8")
let $text := replace($text,"http://dbpedia.org/resource/","")
let $text := replace($text,"\(.*\)","")
let $text := replace($text,"_"," ")
return $text
};
declare function local:year-from-date($d) {
let $d := replace($d,"[^0-9\-]","")
let $dp := tokenize($d,"-")
let $year := $dp[1]
return
if ($year castable as xs:integer and string-length($year)=4)
then $year
else ()
};
let $group := request:get-parameter ("group","The_Allman_Brothers_Band")
let $groupx := replace($group," ","_")
let $queryx := replace($query,"The_Allman_Brothers_Band",encode-for-uri($group))
let $result := local:execute-sparql($queryx)
let $tuples := local:sparql-to-tuples($result)
return
<data>
{for $album in distinct-values($tuples/album)
let $rows := $tuples[album=$album]
let $name := local:clean($album)
let $year := local:year-from-date(($rows/dateofrelease)[1])
let $cover := ($rows/cover)[1]
where exists($year)
return
<event start="{$year}" title="{$name}">
{util:serialize(
<div>
{if (starts-with($cover,"http://")) then <img src="{$cover}" height="200" alt=""/> else () }
<p><a href="{$album}">DBpedia</a> <a href="{replace($album,"dbpedia.org/resource","en.wikipedia.org/wiki")}">Wikipedia</a></p>
</div>
, "method=xhtml")
}
</event>
}
</data>
此脚本查询 DBpedia 以获取属于指定类别的资源,例如 Rock_and_Roll_Hall_of_Fame_inductees。按字母顺序排列的乐队名称表提供指向使用上述脚本的时间线视图的链接,以及指向唱片目录的 HTML 表格视图的链接。
declare namespace r = "http://www.w3.org/2005/sparql-results#";
declare option exist:serialize "method=xhtml media-type=text/html";
declare variable $query := "
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX p: <http://dbpedia.org/property/>
SELECT * WHERE {
?group skos:subject <http://dbpedia.org/resource/Category:Rock_and_Roll_Hall_of_Fame_inductees>.
}
";
declare function local:execute-sparql($query as xs:string) {
let $sparql := concat("http://dbpedia.org/sparql?format=xml&default-graph-uri=http://dbpedia.org&query=",
escape-uri($query,true())
)
return doc($sparql)
};
declare function local:clean($text) {
let $text:= util:unescape-uri($text,"UTF-8")
let $text := replace($text,"\(.*\)","")
let $text := replace($text,"_"," ")
return $text
};
let $category := request:get-parameter("category","Rock_and_Roll_Hall_of_Fame_inductees")
let $queryx := replace($query,"Rock_and_Roll_Hall_of_Fame_inductees",$category)
let $result := local:execute-sparql($queryx)
return
<html>
<body>
<h1>{local:clean($category)}</h1>
<table border="1">
{$result}
{ for $group in $result//r:result/r:binding[@name="group"]/r:uri
let $name := substring-after($group,"resource/")
let $namex := local:clean($name)
order by $name
return
<tr>
<td>{$namex}</td>
<td><a href="group2html.xq?group={$name}">HTML</a></td>
<td><a href="groupTimeline.xq?group={$name}">Timeline</a></td>
</tr>
}
</table>
</body>
</html>