1
2
3
4 """
5
6 This is a wrapper around a SPARQL service. It helps in creating the query URI and,
7 possibly, convert the result into a more managable format.
8
9 The following packages are used:
10
11 - for JSON, the U{simplejson<http://cheeseshop.python.org/pypi/simplejson>} package: C{http://cheeseshop.python.org/pypi/simplejson}
12 - for XML, the U{PyXML<http://pyxml.sourceforge.net/>}: C{http://pyxml.sourceforge.net/}
13 - for RDF/XML, the U{RDFLib<http://rdflib.net>}: C{http://rdflib.net}
14
15 These packages are imported in a lazy fashion, ie, only when needed. Ie, if the user never intends to use the
16 JSON format, the C{simplejson} package is not imported and the user does not have to install it.
17
18 The package can be downloaded in C{zip} and C{.tar.gz} formats from
19 U{http://www.ivan-herman.net/Misc/PythonStuff/SPARQL/<http://www.ivan-herman.net/Misc/PythonStuff/SPARQL/>}. It is also
20 available from U{Sourceforge<https://sourceforge.net/projects/sparql-wrapper/>} under the project named "C{sparql-wrapper}".
21 Documentation is included in the distribution.
22
23
24 Basic QUERY Usage
25 =================
26
27 Simple query
28 ------------
29
30 The simplest usage of this module looks as follows (using the default, ie, U{XML return format<http://www.w3.org/TR/rdf-sparql-XMLres/>}, and special URI for the
31 SPARQL Service)::
32
33 from SPARQL import SPARQLWrapper
34 queryString = "SELECT * WHERE { ?s ?p ?o. }"
35 sparql = SPARQLWrapper("http://localhost:2020/sparql")
36 # add a default graph, though that can also be part of the query string
37 sparql.addDefaultGraph("http://www.example.com/data.rdf")
38 sparql.setQuery(queryString)
39 try :
40 ret = sparql.query()
41 # ret is a stream with the results in XML, see <http://www.w3.org/TR/rdf-sparql-XMLres/>
42 except :
43 deal_with_the_exception()
44
45 If C{SPARQLWrapper("http://localhost:2020/sparql",returnFormat=SPARQL.JSON)} was used, the result would be in
46 U{JSON format<http://www.w3.org/TR/rdf-sparql-json-res/>} instead of XML (provided the sparql
47 processor can return JSON).
48
49 Automatic conversion of the results
50 -----------------------------------
51
52 To make processing somewhat easier, the package can do some conversions automatically from the return result. These are:
53
54 - for XML, the U{PyXML<http://pyxml.sourceforge.net/>} (C{http://pyxml.sourceforge.net/}) is
55 used to convert the result stream into a Python representation of a DOM tree
56 - for JSON, the U{simplejson<http://cheeseshop.python.org/pypi/simplejson>} package (C{http://cheeseshop.python.org/pypi/simplejson}) to generate a Python dictionary
57
58 There are two ways to generate this conversion:
59
60 - use C{ret.convert()} in the return result from C{sparql.query()} in the code above
61 - use C{sparql.queryAndConvert()} to get the converted result right away if the intermediate stream is not used
62
63 For example, in the code below::
64 try :
65 sparql.setReturnFormat(SPARQL.JSON)
66 ret = sparql.query()
67 dict = ret.convert()
68 except:
69 deal_with_the_exception()
70 the value of C{dict} is a Python dictionary of the query result, based on the U{JSON format<http://www.w3.org/TR/rdf-sparql-json-res/>}.
71
72 The L{SPARQLWrapper} class can be subclassed by overriding the conversion routines if the user wants to use something else.
73
74 Partial interpretation of the results
75 -------------------------------------
76
77 A further help is to offer an extra, partial interpretation of the results, again to cover
78 most of the practical use cases.
79 Based on the U{JSON format<http://www.w3.org/TR/rdf-sparql-json-res/>}, the L{SmartWrapper.Bindings} class
80 can perform some simple steps in decoding the JSON return results. If L{SPARQLWrapper2}
81 is used instead of L{SPARQLWrapper}, this result format is generated. Note that this relies on a JSON format only,
82 ie, it has to be checked whether the SPARQL service can return JSON or not.
83
84 Here is a simple code that makes use of this feature::
85
86 from SPARQL import SPARQLWrapper2
87 queryString = "SELECT ?subj ?prop WHERE { ?subj ?prop ?o. }"
88 sparql = SPARQLWrapper2("http://localhost:2020/sparql")
89 # add a default graph, though that can also be in the query string
90 sparql.addDefaultGraph("http://www.example.com/data.rdf")
91 sparql.setQuery(queryString)
92 try :
93 ret = sparql.query()
94 print ret.variables # this is an array consisting of "subj" and "prop"
95 for binding in ret.bindings :
96 # each binding is a dictionary. Let us just print the results
97 print "%s: %s (of type %s)" % ("s",binding[u"subj"].value,binding[u"subj"].type)
98 print "%s: %s (of type %s)" % ("p",binding[u"prop"].value,binding[u"prop"].type)
99 except:
100 deal_with_the_exception()
101
102 To make this type of code even easier to realize, the C{[]} and C{in} operators are also implemented
103 on the result of L{SmartWrapper.Bindings}. This can be used to check and find a particular binding (ie, particular row
104 in the return value). This features becomes particularly useful when the C{OPTIONAL} feature of SPARQL is used. For example::
105
106 from SPARQL import SPARQLWrapper2
107 queryString = "SELECT ?subj ?o ?opt WHERE { ?subj <http://a.b.c> ?o. OPTIONAL { ?subj <http://d.e.f> ?opt }}"
108 sparql = SPARQLWrapper2("http://localhost:2020/sparql")
109 # add a default graph, though that can also be in the query string
110 sparql.addDefaultGraph("http://www.example.com/data.rdf")
111 sparql.setQuery(queryString)
112 try :
113 ret = sparql.query()
114 print ret.variables # this is an array consisting of "subj", "o", "opt"
115 if (u"subj",u"prop",u"opt") in ret :
116 # there is at least one binding covering the optional "opt", too
117 bindings = ret[u"subj",u"o",u"opt"]
118 # bindings is an array of dictionaries with the full bindings
119 for b in bindings :
120 subj = b[u"subj"].value
121 o = b[u"o"].value
122 opt = b[u"opt"].value
123 # do something nice with subj, o, and opt
124 # another way of accessing to values for a single variable:
125 # take all the bindings of the "subj"
126 subjbind = ret.getValues(u"subj") # an array of Value instances
127 ...
128 except:
129 deal_with_the_exception()
130
131
132 CONSTRUCT, ASK, DESCRIBE
133 ========================
134
135 All the examples so far were based on the SELECT queries. If the query includes, eg, the C{CONSTRUCT} keyword then the accepted
136 return formats should be different: eg, C{SPARQL.XML} means C{RDF/XML} and most of the SPARQL engines can also return the results
137 in C{Turtle}. The package, though it does not contain a full SPARQL parser,
138 makes an attempt to determine the query type when the query is set. This should work in most of the cases (but there is a possibility
139 to set this manually, in case something goes wrong).
140
141 For RDF/XML, the U{RDFLib<http://rdflib.net>} (C{http://rdflib.net}) package is used to convert the result into a C{Graph} instance.
142
143 GET or POST
144 ===========
145
146 By default, all SPARQL services are invoked using HTTP GET. However, POST might be useful if the size of the query
147 extends a reasonable size; this can be set in the query instance.
148
149 Note that some combination may not work yet with all SPARQL processors
150 (eg, there are implementations where POST+JSON return does not work). Hopefully, this problem will eventually disappear.
151
152 Acknowledgement
153 ===============
154
155 The package was greatly inspired by U{Lee Feigenbaum's similar package for Javascript<http://thefigtrees.net/lee/blog/2006/04/sparql_calendar_demo_a_sparql.html>}.
156
157 @summary: Python interface to SPARQL services
158 @see: U{SPARQL Specification<http://www.w3.org/TR/rdf-sparql-query/>}
159 @authors: U{Ivan Herman<http://www.ivan-herman.net">}, U{Sergio Fernández<http://www.wikier.org>}, U{Carlos Tejo Alonso<http://www.dayures.net>}
160 @organization: U{World Wide Web Consortium<http://www.w3.org>} and U{Foundation CTIC<http://www.fundacionctic.org/>}.
161 @license: U{W3C® SOFTWARE NOTICE AND LICENSE<href="http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231">}
162 @requires: U{simplejson<http://cheeseshop.python.org/pypi/simplejson>} package.
163 @requires: U{PyXML<http://pyxml.sourceforge.net/>} package.
164 @requires: U{RDFLib<http://rdflib.net>} package.
165 """
166
167 __version__ = "1.0"
168 __authors__ = u"Ivan Herman, Sergio Fernández, Carlos Tejo Alonso"
169 __license__ = u'W3C® SOFTWARE NOTICE AND LICENSE, http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231'
170 __contact__ = 'Ivan Herman, ivan_herman@users.sourceforge.net'
171 __date__ = "2008-02-14"
172
173 from Wrapper import SPARQLWrapper, XML, JSON, TURTLE, N3, GET, POST, SELECT, CONSTRUCT, ASK, DESCRIBE
174 from SmartWrapper import SPARQLWrapper2
175