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>