This notebook provides a quick tour of some of the data on the Open University's Open Linked Data platform.
#Install a library to help us run some SPARQL queries if we haven't already installed it
#http://rdflib.github.io/sparqlwrapper/
#!pip3 install sparqlwrapper
#Import the necessary packages
from SPARQLWrapper import SPARQLWrapper, JSON
/usr/local/lib/python3.4/dist-packages/SPARQLWrapper/Wrapper.py:100: RuntimeWarning: JSON-LD disabled because no suitable support has been found warnings.warn("JSON-LD disabled because no suitable support has been found", RuntimeWarning)
#Declare the Open University open Linked Data endpoint
endpoint="http://data.open.ac.uk/query"
To get the data into a form where it's immediately useable, we can define some helper functions that will parse the result of the query into a pandas dataframe.
Note that some endpoints will return data as a flattened CSV data table anyway that can be dropped directly into a pandas dataframe.
#A helper...
def runQuery(endpoint,prefix,q):
''' Run a SPARQL query with a declared prefix over a specified endpoint '''
sparql = SPARQLWrapper(endpoint)
sparql.setQuery(prefix+q)
sparql.setReturnFormat(JSON)
return sparql.query().convert()
import pandas as pd
#And some more helpers
def dict2df(results):
''' Hack a function to flatten the SPARQL query results and return the column values '''
data=[]
for result in results["results"]["bindings"]:
tmp={}
for el in result:
tmp[el]=result[el]['value']
data.append(tmp)
df = pd.DataFrame(data)
return df
def dfResults(endpoint,prefix,q):
''' Generate a data frame containing the results of running
a SPARQL query with a declared prefix over a specified endpoint '''
return dict2df( runQuery( endpoint, prefix, q ) )
#Sometimes it's convenient to build a default prefix to handle most queries to the endpoint
prefix='''
'''
I always think of constructing SPARQL queries a bit like constructing a dreamcatcher. You have to craft the query in the form of a graph that mathes - and can capture - fragments of the whole Linked Data graph residing at the SPARQL endpoint you're querying over. The form of the query thus has to correspond to the shape, and internal graphical connectedness, of the answers of the question you want to ask.
#Prices (ordered) with currency of OU level 1 courses in Arts and Humanities as available in France.
#via http://data.open.ac.uk/site/queries.html
q='''
#We're looking for some course identifiers along with the value and currency of their price
select ?course ?price ?cur
from <http://data.open.ac.uk/context/course>
where {
#The course must be at level 1
?course <http://data.open.ac.uk/saou/ontology#OUCourseLevel> "1"^^<http://www.w3.org/2001/XMLSchema#string>.
#The course must be in in Arts and Humanities
?course <http://purl.org/dc/terms/subject> <http://data.open.ac.uk/topic/arts_and_humanities>.
#The course must be part of an offering
?off <http://purl.org/goodrelations/v1#includes> ?course.
#And that offering must have a price
?off <http://purl.org/goodrelations/v1#hasPriceSpecification> ?ps.
#The course must be located(?) in France
?course <http://purl.org/net/mlo/location> <http://sws.geonames.org/3017382/>.
#And the offering must be available in France
?off <http://purl.org/goodrelations/v1#availableAtOrFrom> <http://sws.geonames.org/3017382/>.
#The price must have a value
?ps <http://purl.org/goodrelations/v1#hasCurrencyValue> ?price.
#The price must also be in a particular currency
?ps <http://purl.org/goodrelations/v1#hasCurrency> ?cur
} order by ?price
#The ordering ranks the results in increasing price order
'''
#We can now run the query over the endpoint with the desired prefix
#and get the results back as a pandas dataframe
dfResults(endpoint,prefix,q)
course | cur | price | |
---|---|---|---|
0 | http://data.open.ac.uk/course/l161 | GBP | 1316.0 |
1 | http://data.open.ac.uk/course/a105 | GBP | 2632.0 |
2 | http://data.open.ac.uk/course/aa100 | GBP | 2632.0 |
When querying a new graph, we need to find some way of discovering how graphs are structured around particular items. The DESCRIBE
command can be very useful in this respect.
For example, we can have a look at the graph associated with the AA100 module.
q='DESCRIBE <http://data.open.ac.uk/course/aa100>'
ans=runQuery(endpoint,prefix,q)
In this case, the response is an encoded text bytestream - we can get a human readable view by decoding it as UTF-8 and printing the result.
print(ans.decode('utf-8'))
{ "http://data.open.ac.uk/course/aa100" : { "http://courseware.rkbexplorer.com/ontologies/courseware#has-assessment-method" : [ { "type" : "uri" , "value" : "http://data.open.ac.uk/saou/assessment/tma" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/saou/assessment/end-of-course-assessment" } ] , "http://www.w3.org/2000/01/rdf-schema#label" : [ { "type" : "literal" , "value" : "The arts past and present" , "datatype" : "http://www.w3.org/2001/XMLSchema#string" } ] , "http://purl.org/vocab/aiiso/schema#code" : [ { "type" : "literal" , "value" : "AA100" , "datatype" : "http://www.w3.org/2001/XMLSchema#string" } ] , "http://purl.org/net/mlo/location" : [ { "type" : "uri" , "value" : "http://sws.geonames.org/390903/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/6296593/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/458258/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3175395/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2750405/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3144096/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/660013/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2411586/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3077311/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/146670/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2963597/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/732800/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3041565/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3190538/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/6269131/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2264397/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2629691/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/661882/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/146669/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2562770/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2623032/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/597427/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3017382/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2641364/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2782113/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/798544/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2993457/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2510769/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2638360/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3168068/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2634895/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2658434/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2802361/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3164670/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2661886/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2921044/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/719819/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3202326/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/453733/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3057568/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3042225/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/798549/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3042058/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2960313/" } ] , "http://purl.org/net/mlo/start" : [ { "type" : "literal" , "value" : "2008-10" , "datatype" : "http://www.w3.org/2001/XMLSchema#gYearMonth" } ] , "http://data.open.ac.uk/saou/ontology#numberOfTMAEssays" : [ { "type" : "literal" , "value" : "7" , "datatype" : "http://www.w3.org/2001/XMLSchema#integer" } ] , "http://courseware.rkbexplorer.com/ontologies/courseware#taught-at" : [ { "type" : "uri" , "value" : "http://data.open.ac.uk/organization/the_open_university" } ] , "http://rdfs.org/ns/void#inDataset" : [ { "type" : "uri" , "value" : "http://data.open.ac.uk/context/course" } ] , "http://data.open.ac.uk/saou/ontology#isAvailableIn" : [ { "type" : "uri" , "value" : "http://sws.geonames.org/390903/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/6296593/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/458258/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3175395/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2750405/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3144096/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2411586/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/660013/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3077311/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/146670/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2963597/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/732800/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3041565/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3190538/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/6269131/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2264397/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/661882/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2629691/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/146669/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2562770/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2623032/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/597427/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3017382/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2641364/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2782113/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/798544/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2993457/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2510769/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2638360/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3168068/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2634895/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2658434/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2802361/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3164670/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2661886/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/719819/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2921044/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/453733/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3202326/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3057568/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3042225/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/798549/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/3042058/" } , { "type" : "uri" , "value" : "http://sws.geonames.org/2960313/" } ] , "http://data.open.ac.uk/saou/ontology#FHEQLevel" : [ { "type" : "literal" , "value" : "4" , "datatype" : "http://www.w3.org/2001/XMLSchema#integer" } ] , "http://purl.org/dc/terms/title" : [ { "type" : "literal" , "value" : "The arts past and present" , "datatype" : "http://www.w3.org/2001/XMLSchema#string" } ] , "http://purl.org/net/mlo/specifies" : [ { "type" : "uri" , "value" : "http://data.open.ac.uk/course/presentation/aa100-2014j" } ] , "http://purl.org/goodrelations/v1#isSimilarTo" : [ { "type" : "uri" , "value" : "http://data.open.ac.uk/course/ea300" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/course/u214" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/course/a215" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/course/a200" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/course/a230" } ] , "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" : [ { "type" : "uri" , "value" : "http://xcri.org/profiles/catalog/1.2/course" } , { "type" : "uri" , "value" : "http://purl.org/vocab/aiiso/schema#Module" } , { "type" : "uri" , "value" : "http://purl.org/net/mlo/LearningOpportunitySpecification" } , { "type" : "uri" , "value" : "http://courseware.rkbexplorer.com/ontologies/courseware#Course" } ] , "http://data.open.ac.uk/saou/ontology#ou-number-of-credits" : [ { "type" : "literal" , "value" : "60" , "datatype" : "http://www.w3.org/2001/XMLSchema#integer" } ] , "http://data.open.ac.uk/saou/ontology#courseLevel" : [ { "type" : "uri" , "value" : "http://data.open.ac.uk/saou/ontology#undergraduate" } ] , "http://data.open.ac.uk/saou/ontology#hasBook" : [ { "type" : "uri" , "value" : "http://data.open.ac.uk/book/9780571195473" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/book/9780230202085" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/book/9780582817807" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/book/9780571223626" } ] , "http://purl.org/dc/terms/subject" : [ { "type" : "uri" , "value" : "http://data.open.ac.uk/topic/philosophy" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/topic/arts_and_humanities" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/topic/history" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/topic/music" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/topic/history_of_art" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/topic/literature_and_creative_writing" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/topic/classical_studies" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/topic/religious_studies" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/topic/english_language" } ] , "http://courseware.rkbexplorer.com/ontologies/courseware#has-courseware" : [ { "type" : "uri" , "value" : "http://data.open.ac.uk/library/434667" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/432281" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/342408" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/432451" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/447367" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/432283" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/447369" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/432285" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/448812" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/477424" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/430296" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/432287" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/449099" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/422540" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/353473" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/447391" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/447393" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/430285" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/432284" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/432282" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/432450" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/430275" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/432289" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/455775" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/448813" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/432288" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/430292" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/428159" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/353472" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/library/447368" } ] , "http://purl.org/net/mlo/assessment" : [ { "type" : "uri" , "value" : "http://data.open.ac.uk/saou/assessment/tma" } , { "type" : "uri" , "value" : "http://data.open.ac.uk/saou/assessment/end-of-course-assessment" } ] , "http://purl.org/vocab/aiiso/schema#name" : [ { "type" : "literal" , "value" : "The arts past and present" , "datatype" : "http://www.w3.org/2001/XMLSchema#string" } ] , "http://courseware.rkbexplorer.com/ontologies/courseware#has-title" : [ { "type" : "literal" , "value" : "The arts past and present" , "datatype" : "http://www.w3.org/2001/XMLSchema#string" } ] , "http://data.open.ac.uk/saou/ontology#eu-number-of-credits" : [ { "type" : "literal" , "value" : "30.0" , "datatype" : "http://www.w3.org/2001/XMLSchema#float" } ] , "http://purl.org/net/mlo/url" : [ { "type" : "literal" , "value" : "http://www3.open.ac.uk/study/undergraduate/course/aa100.htm" } ] , "http://data.open.ac.uk/saou/ontology#OUCourseLevel" : [ { "type" : "literal" , "value" : "1" , "datatype" : "http://www.w3.org/2001/XMLSchema#string" } ] , "http://xcri.org/profiles/catalog/1.2/end" : [ { "type" : "literal" , "value" : "2019-02" , "datatype" : "http://www.w3.org/2001/XMLSchema#gYearMonth" } ] , "http://data.open.ac.uk/saou/ontology#SCQFLevel" : [ { "type" : "literal" , "value" : "7" , "datatype" : "http://www.w3.org/2001/XMLSchema#integer" } ] , "http://purl.org/dc/terms/description" : [ { "type" : "literal" , "value" : "Study a broad range of arts subject areas (from history to philosophy, music to English) across multiple cultures and historical periods in this university-level introduction." , "datatype" : "http://www.w3.org/2001/XMLSchema#string" } ] , "http://courseware.rkbexplorer.com/ontologies/courseware#is-taught-present" : [ { "type" : "literal" , "value" : "true" , "datatype" : "http://www.w3.org/2001/XMLSchema#boolean" } ] } }
We can use this description to help us construct a query that only pulls out the fields we are interested in. For example, if we read through the description, we can see that we can pull out the title and description of the module:
prefix='''
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX aiiso: <http://purl.org/vocab/aiiso/schema#>
'''
q='''
SELECT ?code ?title ?desc WHERE {
<http://data.open.ac.uk/course/aa100> aiiso:code ?code.
<http://data.open.ac.uk/course/aa100> rdfs:label ?title.
<http://data.open.ac.uk/course/aa100> dcterms:description ?desc.
}
'''
runQuery(endpoint,prefix,q)
{'head': {'vars': ['code', 'title', 'desc']}, 'results': {'bindings': [{'code': {'value': 'AA100', 'type': 'typed-literal', 'datatype': 'http://www.w3.org/2001/XMLSchema#string'}, 'title': {'value': 'The arts past and present', 'type': 'typed-literal', 'datatype': 'http://www.w3.org/2001/XMLSchema#string'}, 'desc': {'value': 'Study a broad range of arts subject areas (from history to philosophy, music to English) across multiple cultures and historical periods in this university-level introduction.', 'type': 'typed-literal', 'datatype': 'http://www.w3.org/2001/XMLSchema#string'}}]}}
def printQuery(endpoint,prefix,q):
''' Print the results from the SPARQL query '''
results=runQuery(endpoint,prefix,q)
for result in results["results"]["bindings"]:
for ans in result:
print('{0}: {1}'.format(ans,result[ans]['value']))
print()
printQuery(endpoint,prefix,q)
code: AA100 title: The arts past and present desc: Study a broad range of arts subject areas (from history to philosophy, music to English) across multiple cultures and historical periods in this university-level introduction.
Repeatedly quoting the resource we are interested in describing feels a bit a redundant and susceptible to error. So instead we might search for a resource that is a module with the desired module code. We note from the result of the query, and the description, that the module code is specified as a string type, so we need to make that clear in our query.
prefix='''
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX aiiso: <http://purl.org/vocab/aiiso/schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
'''
q='''
SELECT ?code ?title ?desc WHERE {
?module aiiso:code 'AA100'^^xsd:string.
?module rdf:type aiiso:Module.
?module aiiso:code ?code.
?module aiiso:code ?code.
?module rdfs:label ?title.
?module dcterms:description ?desc.
}
'''
printQuery(endpoint,prefix,q)
code: AA100 title: The arts past and present desc: Study a broad range of arts subject areas (from history to philosophy, music to English) across multiple cultures and historical periods in this university-level introduction.
We might also look to see what books are associated with the course:
prefix='''
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX aiiso: <http://purl.org/vocab/aiiso/schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX saou: <http://data.open.ac.uk/saou/ontology#>
'''
q='''
SELECT ?code ?book WHERE {
?module aiiso:code 'AA100'^^xsd:string.
?module rdf:type aiiso:Module.
?module aiiso:code ?code.
?module aiiso:code ?code.
?module rdfs:label ?title.
?module dcterms:description ?desc.
?module saou:hasBook ?book.
}
'''
printQuery(endpoint,prefix,q)
code: AA100 book: http://data.open.ac.uk/book/9780571223626 code: AA100 book: http://data.open.ac.uk/book/9780230202085 code: AA100 book: http://data.open.ac.uk/book/9780582817807 code: AA100 book: http://data.open.ac.uk/book/9780571195473
Now we can start to "join" the result with other data elements by extending the graph representation of the answers we want to get back. For example, what might we find out about the books?
q='DESCRIBE <http://data.open.ac.uk/book/9780571195473>'
def printDesc(endpoint,q):
ans=runQuery(endpoint,prefix,q)
print(ans.decode('utf-8'))
printDesc(endpoint,q)
{ "http://data.open.ac.uk/book/9780571195473" : { "http://rdfs.org/ns/void#inDataset" : [ { "type" : "uri" , "value" : "http://data.open.ac.uk/context/course" } ] , "http://purl.org/ontology/bibo/ISBN13" : [ { "type" : "literal" , "value" : "9780571195473" } ] , "http://purl.org/dc/terms/title" : [ { "type" : "literal" , "value" : "The Faber Book of Beasts" } ] , "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" : [ { "type" : "uri" , "value" : "http://purl.org/ontology/bibo/Book" } ] , "http://www.w3.org/2000/01/rdf-schema#label" : [ { "type" : "literal" , "value" : "The Faber Book of Beasts" } ] , "http://purl.org/dc/terms/publisher" : [ { "type" : "literal" , "value" : "Faber and Faber" } ] } }
Let's weave elements of that in to our original query...
prefix='''
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX aiiso: <http://purl.org/vocab/aiiso/schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX saou: <http://data.open.ac.uk/saou/ontology#>
PREFIX bibo: <http://purl.org/ontology/bibo/>
'''
q='''
SELECT ?booktitle ?isbn13 ?publisher WHERE {
?module aiiso:code 'AA100'^^xsd:string.
?module rdf:type aiiso:Module.
?module aiiso:code ?code.
?module aiiso:code ?code.
?module rdfs:label ?title.
?module dcterms:description ?desc.
?module saou:hasBook ?book.
?book dcterms:title ?booktitle.
?book bibo:ISBN13 ?isbn13.
?book dcterms:publisher ?publisher.
}
'''
printQuery(endpoint,prefix,q)
publisher: Faber and Faber booktitle: The Burial at Thebes isbn13: 9780571223626 publisher: Palgrave Macmillan booktitle: A World of Difference: an anthology of short stories from five continents isbn13: 9780230202085 publisher: Longman booktitle: Doctor Faustus the A text isbn13: 9780582817807 publisher: Faber and Faber booktitle: The Faber Book of Beasts isbn13: 9780571195473
For other example queries over the OU open Linked Data, see data.open.ac.uk - Example queries, which includes queries showing how to:
There are several datasets stored on the OU Linked Data Platform, covering: