Skip to content

Instantly share code, notes, and snippets.

@ljos
Created December 2, 2011 22:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ljos/1425113 to your computer and use it in GitHub Desktop.
Save ljos/1425113 to your computer and use it in GitHub Desktop.
Using Timeplot to create a graph to show sparql results.

A small project using timeplot, joseki and xslt to create graphs over time. The rdfs used in the searches here are ones created in a xslt you can find as another gist. The code is meant to run on as a part of a joseki sparql endpoint. At least that is where we sent the queries.

Code released under GPLv3.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sparql="http://www.w3.org/2005/sparql-results#">
<xsl:template match="/sparql:sparql/sparql:results">
<data>
<xsl:for-each select="sparql:result">
<event>
<xsl:attribute name="isDuration">true </xsl:attribute>
<xsl:attribute name="start">
<xsl:value-of
select="sparql:binding[@name='start']/sparql:literal"/>
</xsl:attribute>
<xsl:attribute name="end">
<xsl:value-of
select="sparql:binding[@name='end']/sparql:literal"/>
</xsl:attribute>
<xsl:attribute name="image">
<xsl:value-of
select="sparql:binding[@name='main_image_url']/sparql:literal"/>
</xsl:attribute>
<xsl:attribute name="link">
<xsl:value-of select="sparql:binding/sparql:uri"/>
</xsl:attribute>
<xsl:value-of select="sparql:binding[@name='description']/sparql:literal"/>
</event>
</xsl:for-each>
</data>
</xsl:template>
</xsl:stylesheet>
<html>
<head>
<script src="http://api.simile-widgets.org/timeplot/1.1/timeplot-api.js" type="text/javascript"></script>
<script type="text/javascript">
var xsl_url = "/ctt.xsl";
Timeplot.DefaultEventSource.prototype.loadXML = function(inxml, url) {
var xhttp=new XMLHttpRequest();
xhttp.open("GET", xsl_url,false);
xhttp.send("");
var xsl = xhttp.responseXML;
xsltProcessor=new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);
var xml = xsltProcessor.transformToDocument(inxml);
var base = this._getBaseURL(url);
var wikiURL = xml.documentElement.getAttribute("wiki-url");
var wikiSection = xml.documentElement.getAttribute("wiki-section");
var dateTimeFormat = xml.documentElement.getAttribute("date-time-format");
var parseDateTimeFunction = this._events.getUnit().getParser(dateTimeFormat);
var node = xml.documentElement.firstChild;
var added = false;
while (node != null) {
if (node.nodeType == 1) {
var description = "";
if (node.firstChild != null && node.firstChild.nodeType == 3) {
description = node.firstChild.nodeValue;
}
// instant event: default is true. Or use values from isDuration or durationEvent
var instant = (node.getAttribute("isDuration") === null &&
node.getAttribute("durationEvent") === null) ||
node.getAttribute("isDuration") == "false" ||
node.getAttribute("durationEvent") == "false";
var evt = new Timeline.DefaultEventSource.Event( {
id: node.getAttribute("id"),
start: parseDateTimeFunction(node.getAttribute("start")),
end: parseDateTimeFunction(node.getAttribute("end")),
latestStart: parseDateTimeFunction(node.getAttribute("latestStart")),
earliestEnd: parseDateTimeFunction(node.getAttribute("earliestEnd")),
instant: instant,
text: node.getAttribute("title"),
description: description,
image: this._resolveRelativeURL(node.getAttribute("image"), base),
link: this._resolveRelativeURL(node.getAttribute("link") , base),
icon: this._resolveRelativeURL(node.getAttribute("icon") , base),
color: node.getAttribute("color"),
textColor: node.getAttribute("textColor"),
hoverText: node.getAttribute("hoverText"),
classname: node.getAttribute("classname"),
tapeImage: node.getAttribute("tapeImage"),
tapeRepeat: node.getAttribute("tapeRepeat"),
caption: node.getAttribute("caption"),
eventID: node.getAttribute("eventID"),
trackNum: node.getAttribute("trackNum")
});
evt._node = node;
evt.getProperty = function(name) {
return this._node.getAttribute(name);
};
evt.setWikiInfo(wikiURL, wikiSection);
this._events.add(evt);
added = true;
}
node = node.nextSibling;
}
if (added) {
this._fire("onAddMany", []);
}
}
var timeplot;
var plotInfo = [];
var n = 1;
var plotl = "";
var query_url = "/books?query=";
var timeGeometry = new Timeplot.DefaultTimeGeometry({});
var valueGeometry = new Timeplot.DefaultValueGeometry({});
function loadNow() {
var red = "#B9121B";
var eventSource3 = new Timeplot.DefaultEventSource();
plotInfo[0] =
Timeplot.createPlotInfo({
id: "Events",
eventSource: eventSource3,
timeGeometry: timeGeometry,
lineColor: red
});
var query = "SELECT+%3Fstart+%3Fend+%3Fdescription%0D%0AWHERE+%7B+%3F_++%3Chttp%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23type%3E+%3Chttp%3A%2F%2Fdbpedia.org%2Fontology%2FEvent%3E%3B+%3Chttp%3A%2F%2Fdbpedia.org%2Fontology%2Fplace%3E+%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FNorway%3E+%3B+%3Chttp%3A%2F%2Fdbpedia.org%2Fontology%2FstartDate%3E++%3Fstart+%3B+%3Chttp%3A%2F%2Fdbpedia.org%2Fontology%2FendDate%3E+++%3Fend+%3B+%3Chttp%3A%2F%2Fdbpedia.org%2Fontology%2Fabstract%3E+%3Fdescription%7D+ORDER+BY+ASC%28%3Fdate%29";
var options="&output=xml";
timeplot = Timeplot.create(document.getElementById("timeplot1"), plotInfo);
timeplot.loadXML(query_url.concat(query, options), eventSource3);
// document.getElementById("timeline").innerHTML ="Timeline: Norway from 1929 to current.";
}
var resizeTimerID = null;
function onResize() {
if (resizeTimerID == null) {
resizeTimerID = window.setTimeout(function() {
resizeTimerID = null;
timeplot.repaint();
}, 100);
}
}
function plot() {
var query = encodeURIComponent(document.getElementById('query').value);
var textq = document.getElementById('query').value.replace(/(\r\n|\n|\r)+/g,"").replace(/\s+/g, " ");
var pattern = /#\w+>.*?<.*?\w+>;/g;
var patt = /#([\w\-\u00A1-\uFFFF]+)>.*?<.*?#([\w\-_\u00A1-\uFFFF]+)>;/;
var m = textq.match(pattern);
var out = "";
for(var i=0; i < m.length; ++i) {
out += m[i].replace(patt, "$1 =&gt; $2; ");
}
out = out.replace(/_/g, " ");
if (document.getElementById("plotl").innerHTML.indexOf(out) == -1) {
var colour="#"+((1<<24)*Math.random()|0).toString(16);
document.getElementById("plotl").innerHTML += "<li id='plots_".concat(n, "' ",
"style='color:",
colour,
"'><div style='color: black'><button type='button' onclick='deletePlot(", n,")'>x</button>",
out,"<div></li>");
var es = new Timeplot.DefaultEventSource();
plotInfo.push(
Timeplot.createPlotInfo({
id: "plot".concat(n),
dataSource: new Timeplot.ColumnSource(es,1),
timeGeometry: timeGeometry,
valueGeometry: valueGeometry,
lineColor: colour,
showValues: true
}));
timeplot = Timeplot.create(document.getElementById("timeplot1"), plotInfo);
var options = "&stylesheet=%2Fxml-to-html.xsl&output=csv&force-accept=text%2Fplain";
timeplot.loadText(query_url.concat(query,options), ",", es);
n+=1;
}
timeplot.repaint();
}
function xml() {
var red = "#B9121B";
var eventSource3 = new Timeplot.DefaultEventSource();
plotInfo[0] =
Timeplot.createPlotInfo({
id: "Events",
eventSource: eventSource3,
timeGeometry: timeGeometry,
lineColor: red
});
var query = encodeURIComponent(document.getElementById('query').value);
var options = "&output=xml";
timeplot = Timeplot.create(document.getElementById("timeplot1"), plotInfo);
timeplot.loadXML(query_url.concat(query, options), eventSource3);
}
function changetoplot() {
document.getElementById("addplot").onclick = plot;
document.getElementById("addplot").value = "add plot";
document.getElementById("cxml").style.color = "#000000";
document.getElementById("cplot").style.color = "#0000FF";
}
function changetoxml() {
document.getElementById("addplot").onclick = xml;
document.getElementById("addplot").value = "add line";
document.getElementById("cxml").style.color = "#0000FF";
document.getElementById("cplot").style.color = "#000000";
}
function deletePlot(st){
document.getElementById("plots_".concat(st)).outerHTML="";
for (var i=1; i<plotInfo.length ; i++){
if(plotInfo[i].id == "plot".concat(st)){
plotInfo.splice(i,1);
}
}
timeplot = Timeplot.create(document.getElementById("timeplot1"), plotInfo);
timeplot.repaint();
}
function showQuery() {
document.getElementById("formtitle").innerHTML="Query";
document.getElementById("form2").innerHTML ="";
document.getElementById("form").innerHTML= "<input id='cplot' style='color: #0000FF;' onclick='changetoplot()' name='plotquery' type='button' value='timeplot'/> <input id='cxml' style='color: #000000;' onclick='changetoxml()' name='xmlquery' type='button' value='timeline'/> <br/> <textarea id='query' name='txt1' rows='12' cols='65'></textarea> <br/> <input id='addplot' onclick='plot()' type='button' value='add plot'/>";
}
function showSelect() {
var options = "";
var select_query ="SELECT+%3Fregion%0D%0AWHERE+%7B+%3F_++%3Chttp%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23type%3E+%3Chttp%3A%2F%2Flocalhost%2Fssbont.owl%23region%3E%3B%0D%0A++++++++++++%3Chttp%3A%2F%2Fpurl.org%2Fdc%2Felements%2F1.1%2Ftitle%3E+%3Fregion+%7D%0D%0AORDER+BY+%28%3Fregion%29&output=csv&force-accept=text%2Fplain";
var xhttp=new XMLHttpRequest();
xhttp.open("GET", query_url+select_query,false);
xhttp.send("");
var opts = xhttp.responseText.split("\n");
opts.shift();
opts.pop();
for(var i=0; i < opts.length; i++) {
options+= "<option value=" + opts[i].replace(/^\s\s*/, '').replace(/\s\s*$/, '').replace(/\s/g, "_") + ">" + opts[i] +"</option>";
}
document.getElementById("formtitle").innerHTML="Select";
document.getElementById("form").innerHTML = "<input id='query' type='hidden'/><select id='http://localhost/ssbont.owl#in_region' onchange='showContents()'><option value=''>Choose region</option>" + options + "</select><select id='http://localhost/ssbont.owl#in_contents' onchange='showRest();'><option>Choose content</option></select>";
}
function showContents() {
document.getElementById("form2").innerHTML = "";
var options = "";
var e = document.getElementById("http://localhost/ssbont.owl#in_region");
var sel = e.options[e.selectedIndex].value;
var select_query ="SELECT+DISTINCT+%3Fcontent%0D%0AWHERE+%7B+%3F_++%3Chttp%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23type%3E+%3Chttp%3A%2F%2Flocalhost%2Fssbont.owl%23observation%3E%3B%0D%0A++++++++++++%3Chttp%3A%2F%2Flocalhost%2Fssbont.owl%23in_region%3E+%3Chttp%3A%2F%2Flocalhost%2Fssbont.owl%23"+ sel +"%3E%3B%0D%0A++++++++++++%3Chttp%3A%2F%2Flocalhost%2Fssbont.owl%23in_contents%3E+%3Fc+.%0D%0A++%3Fc+%3Chttp%3A%2F%2Fpurl.org%2Fdc%2Felements%2F1.1%2Ftitle%3E+%3Fcontent%7D%0D%0AORDER+BY+%28%3Fcontent%29%0D%0A&output=csv&force-accept=text%2Fplain";
var xhttp=new XMLHttpRequest();
xhttp.open("GET", query_url+select_query,false);
xhttp.send("");
var opts = xhttp.responseText.split('\n');
opts.shift();
opts.pop();
for(var i=0; i < opts.length; i++) {
options+= "<option value=" + opts[i].replace(/^\s\s*/, '').replace(/\s\s*$/, '').replace(/\s/g, "_") + ">" + opts[i] +"</option>";
}
document.getElementById("http://localhost/ssbont.owl#in_contents").innerHTML="<option value=''>Choose content</option>" + options;
}
function showRest() {
document.getElementById("form2").innerHTML = "";
var e1 = document.getElementById("http://localhost/ssbont.owl#in_region");
var region = e1.options[e1.selectedIndex].value;
var e2 = document.getElementById("http://localhost/ssbont.owl#in_contents");
var contents = e2.options[e2.selectedIndex].value;
var options = "";
var select_query ="SELECT+DISTINCT+%3Frest+WHERE+%7B+%3Fa++%3Chttp%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23type%3E+%3Chttp%3A%2F%2Flocalhost%2Fssbont.owl%23observation%3E%3B+%3Chttp%3A%2F%2Flocalhost%2Fssbont.owl%23in_region%3E+%3Chttp%3A%2F%2Flocalhost%2Fssbont.owl%23"+region+"%3E%3B+%3Chttp%3A%2F%2Flocalhost%2Fssbont.owl%23in_contents%3E+%3Chttp%3A%2F%2Flocalhost%2Fssbont.owl%23"+contents+"%3E%3B+%3Frest+%3Fother.+NOT+EXISTS+%7B+%3Fother+%3Chttp%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23type%3E+%3Chttp%3A%2F%2Flocalhost%2Fssbont.owl%23region%3E%7D+NOT+EXISTS+%7B+%3Fother+%3Chttp%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23type%3E+%3Chttp%3A%2F%2Flocalhost%2Fssbont.owl%23contents%3E%7D+NOT+EXISTS+%7B+%3Fother+%3Chttp%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23type%3E+%3Chttp%3A%2F%2Flocalhost%2Fssbont.owl%23observation%3E%7D+NOT+EXISTS+%7B%3Fa+%3Chttp%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23type%3E+%3Fother%7D+NOT+EXISTS+%7B+%3Fa+%3Chttp%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23value%3E+%3Fother%7D+NOT+EXISTS+%7B+%3Fa+%3Chttp%3A%2F%2Fpurl.org%2Fdc%2Felements%2F1.1%2Fdate%3E+%3Fother%7D%7D+ORDER+BY+%28%3Frest%29&output=csv&force-accept=text%2Fplain";
var xhttp=new XMLHttpRequest();
xhttp.open("GET", query_url+select_query,false);
xhttp.send("");
var opts = xhttp.responseText.split("\n");
opts.shift();
opts.pop();
for(var i=0; i < opts.length; i++) {
var options2 = "";
var select_query2 ="SELECT+DISTINCT+%3Frest+WHERE+%7B+%3Fa+%3Chttp%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23type%3E+%3Chttp%3A%2F%2Flocalhost%2Fssbont.owl%23observation%3E%3B+%3C"+encodeURIComponent(opts[i].replace(/^\s\s*/, '').replace(/\s\s*$/, ''))+"%3E+%3Fage.+%3Fage+%3Chttp%3A%2F%2Fpurl.org%2Fdc%2Felements%2F1.1%2Ftitle%3E+%3Frest%7D+ORDER+BY%28%3Frest%29&output=csv&force-accept=text%2Fplain";
var xhtt2p=new XMLHttpRequest();
xhttp.open("GET", query_url+select_query2,false);
xhttp.send("");
var opts2 = xhttp.responseText.split("\n");
opts2.shift();
opts2.pop();
for(var j=0; j < opts2.length; j++) {
options2+= "<option value=" + opts2[j].replace(/^\s\s*/, '').replace(/\s\s*$/, '').replace(/\s/g, "_") + ">" + opts2[j] +"</option>";
}
document.getElementById("form2").innerHTML+="<select id='"+opts[i]+"'>"+options2+"</select>";
}
document.getElementById("form2").innerHTML+="<button id='sendbutton' onclick='sendplot()'>plot</button>";
}
function sendplot() {
var selects = document.getElementsByTagName("select");
var query = "SELECT ?date ?value WHERE {?_ <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://localhost/ssbont.owl#observation>; ";
for(var i=0; i < selects.length; i++) {
var type = selects[i].id;
var sel = selects[i].options[selects[i].selectedIndex].value;
query+="<"+type.replace(/^\s\s*/, '').replace(/\s\s*$/, '')+"> <http://localhost/ssbont.owl#"+sel.replace(/^\s\s*/, '').replace(/\s\s*$/, '')+">; ";
}
query+="<http://www.w3.org/1999/02/22-rdf-syntax-ns#value> ?value; <http://purl.org/dc/elements/1.1/date> ?date} ORDER BY ASC(?date)";
document.getElementById("query").value=query;
plot();
}
</script>
</head>
<body onload="loadNow();" onresize="onResize();">
<div id="header">
<h1>SPARQL-Plot</h1>
<h2>Plots SPARQL queries over time.</h2>
</div>
<div style="margin: 2em 0;">
<div id="timeplot1" style="height: 300px" class="timeplot"></div>
<div id="timeline" style="font-size: 90%"></div>
</div>
<button onclick="showQuery()">query</button>
<button onclick="showSelect()">select</button>
<table class="spaced-table">
<tr>
<td width="600" valign="top">
<h3 id="formtitle">Query</h3>
<div id="form" name="form">
<input id="cplot" style="color: #0000FF;" onclick="changetoplot()" name="plotquery" type="button" value="timeplot"/>
<input id="cxml" style="color: #000000;" onclick="changetoxml()" name="xmlquery" type="button" value="timeline"/> <br/>
<textarea id="query" name="txt1" rows="12" cols="65"></textarea> <br/>
<input id="addplot" onclick="plot()" type="button" value="add plot"/>
</div>
<div id="form2"></div>
</td>
<td width="500" valign="top">
<h3>Plots</h3>
<ul id="plotl"></ul>
</td>
</tr>
</table>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment