Package SPARQL
[hide private]
[frames] | no frames]

Source Code for Package SPARQL

  1  #!/d/Bin/Python/python.exe 
  2  # -*- coding: utf-8 -*- 
  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