├── README ├── composer.json ├── examples ├── alive.php ├── basic.php ├── capabilities.php ├── loadtest.rdf ├── object.php ├── quick.php ├── sparqllib.php └── types.php ├── index.php └── sparqllib.php /README: -------------------------------------------------------------------------------- 1 | PHP SPARQL Lib 2 | Copyright 2010,2011,2012 Christopher Gutteridge & University of Southampton 3 | Licensed as LGPL 4 | 5 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cgutteridge/sparqllib" 3 | } 4 | -------------------------------------------------------------------------------- /examples/alive.php: -------------------------------------------------------------------------------- 1 | "Real endpoint", 6 | "http://"=>"Bad URL", 7 | "http://graphite.ecs.soton.ac.uk/not-real"=>"404 URL", 8 | "http://graphite.ecs.soton.ac.uk/sparqllib/examples/not-an-endpoint.txt"=>"Valid URL, but not an endpoint" ); 9 | foreach( $endpoints as $endpoint=>$desc) 10 | { 11 | $db = sparql_connect( $endpoint ); 12 | if( !$db ) { print sparql_errno() . ": " . sparql_error(). "\n"; exit; } 13 | 14 | print "

$desc

"; 15 | print "

$endpoint

"; 16 | if( $db->alive() ) 17 | { 18 | print "

OK

"; 19 | } 20 | else 21 | { 22 | print "

Not alive: ".$db->error()."

"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/basic.php: -------------------------------------------------------------------------------- 1 | Number of rows: ".sparql_num_rows( $result )." results.

"; 15 | print ""; 16 | print ""; 17 | foreach( $fields as $field ) 18 | { 19 | print ""; 20 | } 21 | print ""; 22 | while( $row = sparql_fetch_array( $result ) ) 23 | { 24 | print ""; 25 | foreach( $fields as $field ) 26 | { 27 | print ""; 28 | } 29 | print ""; 30 | } 31 | print "
$field
$row[$field]
"; 32 | 33 | 34 | -------------------------------------------------------------------------------- /examples/capabilities.php: -------------------------------------------------------------------------------- 1 | 6 | These are tests against PUBLIC endpoints. They may support LOAD when credentials are supplied.

"; 9 | print "

A cache file is used to save the results for a week, as they will be very unlikely to change.

"; 10 | print "

ARC2

"; 11 | capability_table( "http://programme.ecs.soton.ac.uk/glastonbury/2011/sparql" ); 12 | print "

4store

"; 13 | capability_table( "http://sparql.data.southampton.ac.uk/" ); 14 | # print "

joseki 3

"; 15 | # capability_table( "http://jena.hpl.hp.com:3040/backstage" ); 16 | print "

Virtuoso

"; 17 | capability_table( "http://data.semanticweb.org/sparql" ); 18 | print "

Bigfoot

"; 19 | capability_table( "http://services.data.gov.uk/reference/sparql" ); 20 | print "

Fuseki

"; 21 | capability_table( "http://worldbank.270a.info/sparql" ); 22 | function capability_table($endpoint) 23 | { 24 | $db = sparql_connect( $endpoint ); 25 | $db->capabilityCache( "/usr/local/apache/sites/ecs.soton.ac.uk/graphite/htdocs/sparqllib/cache/caps.db" ); 26 | 27 | if( !$db ) { print $db->errno() . ": " . $db->error(). "\n"; exit; } 28 | 29 | print ""; 30 | foreach( $db->capabilityCodes() as $code ) 31 | { 32 | $can = $db->supports( $code ); 33 | print ""; 34 | print ""; 35 | print ""; 36 | print ""; 37 | print ""; 38 | } 39 | print "
".($can?"OK":"Fail")."".$db->capabilityDescription($code)."($code)
"; 40 | } 41 | -------------------------------------------------------------------------------- /examples/loadtest.rdf: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | Marvin Fenderson 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/object.php: -------------------------------------------------------------------------------- 1 | errno() . ": " . $db->error(). "\n"; exit; } 6 | $db->ns( "foaf","http://xmlns.com/foaf/0.1/" ); 7 | 8 | $sparql = "SELECT * WHERE { ?person a foaf:Person . ?person foaf:name ?name } LIMIT 5"; 9 | $result = $db->query( $sparql ); 10 | if( !$result ) { print $db->errno() . ": " . $db->error(). "\n"; exit; } 11 | 12 | $fields = $result->field_array( $result ); 13 | 14 | print "

Number of rows: ".$result->num_rows( $result )." results.

"; 15 | print ""; 16 | print ""; 17 | foreach( $fields as $field ) 18 | { 19 | print ""; 20 | } 21 | print ""; 22 | while( $row = $result->fetch_array() ) 23 | { 24 | print ""; 25 | foreach( $fields as $field ) 26 | { 27 | print ""; 28 | } 29 | print ""; 30 | } 31 | print "
$field
$row[$field]
"; 32 | 33 | 34 | -------------------------------------------------------------------------------- /examples/quick.php: -------------------------------------------------------------------------------- 1 | 8 | SELECT * WHERE { ?person a foaf:Person . ?person foaf:name ?name } LIMIT 5 9 | " ); 10 | if( !isset($data) ) 11 | { 12 | print "

Error: ".sparql_errno().": ".sparql_error()."

"; 13 | } 14 | 15 | print ""; 16 | print ""; 17 | foreach( $data->fields() as $field ) 18 | { 19 | print ""; 20 | } 21 | print ""; 22 | foreach( $data as $row ) 23 | { 24 | print ""; 25 | foreach( $data->fields() as $field ) 26 | { 27 | print ""; 28 | } 29 | print ""; 30 | } 31 | print "
$field
$row[$field]
"; 32 | 33 | 34 | -------------------------------------------------------------------------------- /examples/sparqllib.php: -------------------------------------------------------------------------------- 1 | ../sparqllib.php -------------------------------------------------------------------------------- /examples/types.php: -------------------------------------------------------------------------------- 1 | 8 | SELECT * WHERE { ?person a foaf:Person . ?person foaf:name ?name } LIMIT 5 9 | " ); 10 | if( !isset($data) ) 11 | { 12 | print "

Error: ".sparql_errno().": ".sparql_error()."

"; 13 | } 14 | 15 | print ""; 16 | print ""; 17 | foreach( $data->fields() as $field ) 18 | { 19 | print ""; 20 | print ""; 21 | print ""; 22 | print ""; 23 | } 24 | print ""; 25 | foreach( $data as $row ) 26 | { 27 | print ""; 28 | foreach( $data->fields() as $field ) 29 | { 30 | print ""; 31 | print ""; 32 | print ""; 33 | print ""; 34 | } 35 | print ""; 36 | } 37 | print "
$field$field.type$field.datatype$field.language
$row[$field]".$row["$field.type"]."".@$row["$field.datatype"]."".@$row["$field.language"]."
"; 38 | 39 | 40 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 10 | 12 | 13 | 14 | SPARQL RDF Library for PHP 15 | 16 | 17 | 53 | 54 | 55 |
56 |
57 |

sparqllib.php

58 |

Simple library to query SPARQL from PHP.

59 |

©2010-12 Christopher Gutteridge, University of Southampton.

60 |
61 |
62 |
63 |
64 | 65 | 66 |

Intro

67 |

This is a very simple RDF library to query SPARQL from PHP. It currently ignores language and datatype information to make it feel as similar as possible to the normal PHP SQL libraries.

68 | 71 |

If you want to get started really quickly, the following command line will install sparqllib.php. You should run it in the same directory as where your PHP code resides.

72 |
73 | curl -s http://graphite.ecs.soton.ac.uk/download.php/sparqllib.php -o sparqllib.php 74 |
75 |

Or get the latest version from Github.

76 |

Also hosted on this site is Graphite, a simple PHP library for querying RDF data.

77 | 78 | Really Quick Interface 80 | #

If you just want to get the damn data, use this style.

81 | #render_example( "examples/quick.php" ); 82 | ?> 83 |

Classic mysql_query style

84 |

The library provides functions very similar to mysql_* for comfort.

85 | 88 | 89 |

Object style

90 |

The object-based interface is a bit tidier than the sparql_ style methods.

91 | 94 | 95 |

Quick and dirty

96 |

The quickest way to get at some data.

97 | 100 | 101 |

Rows, Values and Datatypes

102 |

All the interfaces end up giving you an array of values, one per field. They also define the type of each value and, if available, the datatype or language of a literal value.

103 | 104 | 105 | 106 | 107 | 108 |
$row["myfield"]The value of the field in this row of results.
$row["myfield.type"]The type of the value. Either 'uri','bnode' or 'literal'.
$row["myfield.datatype"]This may be set for literal values.
$row["myfield.language"]This may be set for literal values.
109 | 112 |

Endpoint Capabilities Tests

113 | 114 |

This allows you to test if an endpoint supports and allows certain SPARQL features. It doesn't currently cache, so every test results in a query. I have been trying to write software which runs against multiple endpoints and it's really frustrating not knowing what an endpoint can/can't do.

115 |

The first and most simple test is just to see if this looks like a SPARQL endpoint. Just call $db->alive( 3 ); where 3 is the timeout in seconds.

116 | 119 |

I'm very open to suggestions for useful additional tests (with example SPARQL which runs in some endpoints, but not others)

120 | 121 | 124 | 125 |

Contact

126 |

Get in touch with me at cjg@ecs.soton.ac.uk and you could have a look at our web team blog.

127 |
128 | 129 | 141 |
142 | 143 |
144 | 145 | 146 | enable_keyword_links(false); 151 | print "
"; 152 | print "
Code
"; 153 | print "
". $geshi->parse_code()."
"; 154 | print "
Output
"; 155 | print "
"; include $src; print "
"; 156 | print "
"; 157 | } 158 | -------------------------------------------------------------------------------- /sparqllib.php: -------------------------------------------------------------------------------- 1 | ns( $short, $long ); } 16 | function sparql_query( $sparql, $db = null ) { return _sparql_a_connection( $db )->query( $sparql ); } 17 | function sparql_errno( $db = null ) { return _sparql_a_connection( $db )->errno(); } 18 | function sparql_error( $db = null ) { return _sparql_a_connection( $db )->error(); } 19 | 20 | function sparql_fetch_array( $result ) { return $result->fetch_array(); } 21 | function sparql_num_rows( $result ) { return $result->num_rows(); } 22 | function sparql_field_array( $result ) { return $result->field_array(); } 23 | function sparql_field_name( $result, $i ) { return $result->field_name( $i ); } 24 | 25 | function sparql_fetch_all( $result ) { return $result->fetch_all(); } 26 | 27 | function sparql_get( $endpoint, $sparql ) 28 | { 29 | $db = sparql_connect( $endpoint ); 30 | if( !$db ) { return; } 31 | $result = $db->query( $sparql ); 32 | if( !$result ) { return; } 33 | return $result->fetch_all(); 34 | } 35 | 36 | function _sparql_a_connection( $db ) 37 | { 38 | global $sparql_last_connection; 39 | if( !isset( $db ) ) 40 | { 41 | if( !isset( $sparql_last_connection ) ) 42 | { 43 | print( "No currect SPARQL connection (connection) in play!" ); 44 | return; 45 | } 46 | $db = $sparql_last_connection; 47 | } 48 | return $db; 49 | } 50 | 51 | 52 | # $timeout = 20; 53 | # $old = ini_set('default_socket_timeout', $timeout); 54 | # ini_set('default_socket_timeout', $old); 55 | class sparql_connection 56 | { 57 | var $db; 58 | var $debug = false; 59 | var $errno = null; 60 | var $error = null; 61 | var $ns = array(); 62 | var $params = null; 63 | # capabilities are either true, false or null if not yet tested. 64 | 65 | function __construct( $endpoint ) 66 | { 67 | $this->endpoint = $endpoint; 68 | global $sparql_last_connection; 69 | $sparql_last_connection = $this; 70 | } 71 | 72 | function ns( $short, $long ) 73 | { 74 | $this->ns[$short] = $long; 75 | } 76 | 77 | function errno() { return $this->errno; } 78 | function error() { return $this->error; } 79 | 80 | function cgiParams( $params = null ) 81 | { 82 | if( $params === null ) { return $this->params; } 83 | if( $params === "" ) { $this->params = null; return; } 84 | $this->params = $params; 85 | } 86 | 87 | function query( $query, $timeout=null ) 88 | { 89 | $prefixes = ""; 90 | foreach( $this->ns as $k=>$v ) 91 | { 92 | $prefixes .= "PREFIX $k: <$v>\n"; 93 | } 94 | $output = $this->dispatchQuery( $prefixes.$query, $timeout ); 95 | if( $this->errno ) { return; } 96 | $parser = new xx_xml($output, 'contents'); 97 | if( $parser->error() ) 98 | { 99 | $this->errno = -1; # to not clash with CURLOPT return; } 100 | $this->error = $parser->error(); 101 | return; 102 | } 103 | return new sparql_result( $this, $parser->rows, $parser->fields ); 104 | } 105 | 106 | function alive( $timeout=3 ) 107 | { 108 | $result = $this->query( "SELECT * WHERE { ?s ?p ?o } LIMIT 1", $timeout ); 109 | 110 | if( $this->errno ) { return false; } 111 | 112 | return true; 113 | } 114 | 115 | function dispatchQuery( $sparql, $timeout=null ) 116 | { 117 | $url = $this->endpoint."?query=".urlencode( $sparql ); 118 | if( $this->params !== null ) 119 | { 120 | $url .= "&".$this->params; 121 | } 122 | if( $this->debug ) { print "\n"; } 123 | $this->errno = null; 124 | $this->error = null; 125 | $ch = curl_init($url); 126 | #curl_setopt($ch, CURLOPT_HEADER, 1); 127 | if( $timeout !== null ) 128 | { 129 | curl_setopt($ch, CURLOPT_TIMEOUT, $timeout ); 130 | } 131 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 132 | curl_setopt($ch, CURLOPT_HTTPHEADER,array ( 133 | "Accept: application/sparql-results+xml" 134 | )); 135 | 136 | $output = curl_exec($ch); 137 | $info = curl_getinfo($ch); 138 | if(curl_errno($ch)) 139 | { 140 | $this->errno = curl_errno( $ch ); 141 | $this->error = 'Curl error: ' . curl_error($ch); 142 | return; 143 | } 144 | if( $output === '' ) 145 | { 146 | $this->errno = "-1"; 147 | $this->error = 'URL returned no data'; 148 | return; 149 | } 150 | if( $info['http_code'] != 200) 151 | { 152 | $this->errno = $info['http_code']; 153 | $this->error = 'Bad response, '.$info['http_code'].': '.$output; 154 | return; 155 | } 156 | curl_close($ch); 157 | 158 | return $output; 159 | } 160 | 161 | #################################### 162 | # Endpoint Capability Testing 163 | #################################### 164 | 165 | # This section is very limited right now. I plan, in time, to 166 | # caching so it can save results to a cache to save re-doing them 167 | # and many more capability options (suggestions to cjg@ecs.soton.ac.uk) 168 | 169 | var $caps = array(); 170 | var $caps_desc = array( 171 | "select"=>"Basic SELECT", 172 | "constant_as"=>"SELECT (\"foo\" AS ?bar)", 173 | "math_as"=>"SELECT (2+3 AS ?bar)", 174 | "count"=>"SELECT (COUNT(?a) AS ?n) ?b ... GROUP BY ?b", 175 | "max"=>"SELECT (MAX(?a) AS ?n) ?b ... GROUP BY ?b", 176 | "sample"=>"SELECT (SAMPLE(?a) AS ?n) ?b ... GROUP BY ?b", 177 | "load"=>"LOAD <...>", 178 | ); 179 | 180 | var $caps_cache; 181 | var $caps_anysubject; 182 | function capabilityCache( $filename, $dba_type='db4' ) 183 | { 184 | $this->caps_cache = dba_open($filename, "c", $dba_type ); 185 | } 186 | function capabilityCodes() 187 | { 188 | return array_keys( $this->caps_desc ); 189 | } 190 | function capabilityDescription($code) 191 | { 192 | return $this->caps_desc[$code]; 193 | } 194 | 195 | # return true if the endpoint supports a capability 196 | # nb. returns false if connecion isn't authoriased to use the feature, eg LOAD 197 | function supports( $code ) 198 | { 199 | if( isset( $this->caps[$code] ) ) { return $this->caps[$code]; } 200 | $was_cached = false; 201 | if( isset( $this->caps_cache ) ) 202 | { 203 | $CACHE_TIMEOUT_SECONDS = 7*24*60*60; 204 | $db_key = $this->endpoint.";".$code; 205 | $db_val = dba_fetch( $db_key, $this->caps_cache ); 206 | if( $db_val !== false ) 207 | { 208 | list( $result, $when ) = preg_split( '/;/', $db_val ); 209 | if( $when + $CACHE_TIMEOUT_SECONDS > time() ) 210 | { 211 | return $result; 212 | } 213 | $was_cached = true; 214 | } 215 | } 216 | $r = null; 217 | 218 | if( $code == "select" ) { $r = $this->test_select(); } 219 | elseif( $code == "constant_as" ) { $r = $this->test_constant_as(); } 220 | elseif( $code == "math_as" ) { $r = $this->test_math_as(); } 221 | elseif( $code == "count" ) { $r = $this->test_count(); } 222 | elseif( $code == "max" ) { $r = $this->test_max(); } 223 | elseif( $code == "load" ) { $r = $this->test_load(); } 224 | elseif( $code == "sample" ) { $r = $this->test_sample(); } 225 | else { print "

Unknown capability code: '$code'

"; return false; } 226 | $this->caps[$code] = $r; 227 | if( isset( $this->caps_cache ) ) 228 | { 229 | $db_key = $this->endpoint.";".$code; 230 | $db_val = $r.";".time(); 231 | if( $was_cached ) 232 | { 233 | dba_replace( $db_key, $db_val, $this->caps_cache ); 234 | } 235 | else 236 | { 237 | dba_insert( $db_key, $db_val, $this->caps_cache ); 238 | } 239 | } 240 | return $r; 241 | } 242 | 243 | function anySubject() 244 | { 245 | if( !isset( $this->caps_anysubject ) ) 246 | { 247 | $results = $this->query( 248 | "SELECT * WHERE { ?s ?p ?o } LIMIT 1" ); 249 | if( sizeof($results)) 250 | { 251 | $row = $results->fetch_array(); 252 | $this->caps_anysubject = $row["s"]; 253 | } 254 | } 255 | return $this->caps_anysubject; 256 | } 257 | 258 | # return true if the endpoint supports SELECT 259 | function test_select() 260 | { 261 | $output = $this->dispatchQuery( 262 | "SELECT ?s ?p ?o WHERE { ?s ?p ?o } LIMIT 1" ); 263 | return !isset( $this->errno ); 264 | } 265 | 266 | # return true if the endpoint supports AS 267 | function test_math_as() 268 | { 269 | $output = $this->dispatchQuery( 270 | "SELECT (1+2 AS ?bar) WHERE { ?s ?p ?o } LIMIT 1" ); 271 | return !isset( $this->errno ); 272 | } 273 | 274 | # return true if the endpoint supports AS 275 | function test_constant_as() 276 | { 277 | $output = $this->dispatchQuery( 278 | "SELECT (\"foo\" AS ?bar) WHERE { ?s ?p ?o } LIMIT 1" ); 279 | return !isset( $this->errno ); 280 | } 281 | 282 | # return true if the endpoint supports SELECT (COUNT(?x) as ?n) ... GROUP BY 283 | function test_count() 284 | { 285 | # assumes at least one rdf:type predicate 286 | $s = $this->anySubject(); 287 | if( !isset($s) ) { return false; } 288 | $output = $this->dispatchQuery( 289 | "SELECT (COUNT(?p) AS ?n) ?o WHERE { <$s> ?p ?o } GROUP BY ?o" ); 290 | return !isset( $this->errno ); 291 | } 292 | 293 | function test_max() 294 | { 295 | $s = $this->anySubject(); 296 | if( !isset($s) ) { return false; } 297 | $output = $this->dispatchQuery( 298 | "SELECT (MAX(?p) AS ?max) ?o WHERE { <$s> ?p ?o } GROUP BY ?o" ); 299 | return !isset( $this->errno ); 300 | } 301 | 302 | function test_sample() 303 | { 304 | $s = $this->anySubject(); 305 | if( !isset($s) ) { return false; } 306 | $output = $this->dispatchQuery( 307 | "SELECT (SAMPLE(?p) AS ?sam) ?o WHERE { <$s> ?p ?o } GROUP BY ?o" ); 308 | return !isset( $this->errno ); 309 | } 310 | 311 | function test_load() 312 | { 313 | $output = $this->dispatchQuery( 314 | "LOAD " ); 315 | return !isset( $this->errno ); 316 | } 317 | 318 | 319 | } 320 | 321 | class sparql_result 322 | { 323 | var $rows; 324 | var $fields; 325 | var $db; 326 | var $i = 0; 327 | function __construct( $db, $rows, $fields ) 328 | { 329 | $this->rows = $rows; 330 | $this->fields = $fields; 331 | $this->db = $db; 332 | } 333 | 334 | function fetch_array() 335 | { 336 | if( !@$this->rows[$this->i] ) { return; } 337 | $r = array(); 338 | foreach( $this->rows[$this->i++] as $k=>$v ) 339 | { 340 | $r[$k] = $v["value"]; 341 | $r["$k.type"] = $v["type"]; 342 | if( isset( $v["language"] ) ) 343 | { 344 | $r["$k.language"] = $v["language"]; 345 | } 346 | if( isset( $v["datatype"] ) ) 347 | { 348 | $r["$k.datatype"] = $v["datatype"]; 349 | } 350 | } 351 | return $r; 352 | } 353 | 354 | function fetch_all() 355 | { 356 | $r = new sparql_results(); 357 | $r->fields = $this->fields; 358 | foreach( $this->rows as $i=>$row ) 359 | { 360 | $r []= $this->fetch_array(); 361 | } 362 | return $r; 363 | } 364 | 365 | function num_rows() 366 | { 367 | return sizeof( $this->rows ); 368 | } 369 | 370 | function field_array() 371 | { 372 | return $this->fields; 373 | } 374 | 375 | function field_name($i) 376 | { 377 | return $this->fields[$i]; 378 | } 379 | } 380 | 381 | 382 | # class xx_xml adapted code found at http://php.net/manual/en/function.xml-parse.php 383 | # class is cc-by 384 | # hello at rootsy dot co dot uk / 24-May-2008 09:30 385 | class xx_xml { 386 | 387 | // XML parser variables 388 | var $parser; 389 | var $name; 390 | var $attr; 391 | var $data = array(); 392 | var $stack = array(); 393 | var $keys; 394 | var $path; 395 | var $looks_legit = false; 396 | var $error; 397 | 398 | // either you pass url atau contents. 399 | // Use 'url' or 'contents' for the parameter 400 | var $type; 401 | 402 | // function with the default parameter value 403 | function __construct($url='http://www.opocot.com', $type='url') { 404 | $this->type = $type; 405 | $this->url = $url; 406 | $this->parse(); 407 | } 408 | 409 | function error() { return $this->error; } 410 | 411 | // parse XML data 412 | function parse() 413 | { 414 | $this->rows = array(); 415 | $this->fields = array(); 416 | $data = ''; 417 | $this->parser = xml_parser_create ("UTF-8"); 418 | xml_set_object($this->parser, $this); 419 | xml_set_element_handler($this->parser, 'startXML', 'endXML'); 420 | xml_set_character_data_handler($this->parser, 'charXML'); 421 | 422 | xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false); 423 | 424 | if ($this->type == 'url') { 425 | // if use type = 'url' now we open the XML with fopen 426 | 427 | if (!($fp = fopen($this->url, 'rb'))) { 428 | $this->error("Cannot open {$this->url}"); 429 | } 430 | 431 | while (($data = fread($fp, 8192))) { 432 | if (!xml_parse($this->parser, $data, feof($fp))) { 433 | $this->error = sprintf('XML error at line %d column %d', 434 | xml_get_current_line_number($this->parser), 435 | xml_get_current_column_number($this->parser)); 436 | return; 437 | } 438 | } 439 | } else if ($this->type == 'contents') { 440 | // Now we can pass the contents, maybe if you want 441 | // to use CURL, SOCK or other method. 442 | $lines = explode("\n",$this->url); 443 | foreach ($lines as $val) { 444 | $data = $val . "\n"; 445 | if (!xml_parse($this->parser, $data)) { 446 | $this->error = $data."\n".sprintf('XML error at line %d column %d', 447 | xml_get_current_line_number($this->parser), 448 | xml_get_current_column_number($this->parser)); 449 | return; 450 | } 451 | } 452 | } 453 | if( !$this->looks_legit ) 454 | { 455 | $this->error = "Didn't even see a sparql element, is this really an endpoint?"; 456 | } 457 | } 458 | 459 | function startXML($parser, $name, $attr) 460 | { 461 | if( $name == "sparql" ) { $this->looks_legit = true; } 462 | if( $name == "result" ) 463 | { 464 | $this->result = array(); 465 | } 466 | if( $name == "binding" ) 467 | { 468 | $this->part = $attr["name"]; 469 | } 470 | if( $name == "uri" || $name == "bnode" ) 471 | { 472 | $this->part_type = $name; 473 | $this->chars = ""; 474 | } 475 | if( $name == "literal" ) 476 | { 477 | $this->part_type = "literal"; 478 | if( isset( $attr["datatype"] ) ) 479 | { 480 | $this->part_datatype = $attr["datatype"]; 481 | } 482 | if( isset( $attr["xml:lang"] ) ) 483 | { 484 | $this->part_lang = $attr["xml:lang"]; 485 | } 486 | $this->chars = ""; 487 | } 488 | if( $name == "variable" ) 489 | { 490 | $this->fields[] = $attr["name"]; 491 | } 492 | } 493 | 494 | function endXML($parser, $name) { 495 | if( $name == "result" ) 496 | { 497 | $this->rows[] = $this->result; 498 | $this->result = array(); 499 | } 500 | if( $name == "uri" || $name == "bnode" || $name == "literal" ) 501 | { 502 | $this->result[$this->part] = array( "type"=>$name, "value"=>$this->chars ); 503 | if( isset( $this->part_lang ) ) 504 | { 505 | $this->result[$this->part]["lang"] = $this->part_lang; 506 | } 507 | if( isset( $this->part_datatype ) ) 508 | { 509 | $this->result[$this->part]["datatype"] = $this->part_datatype; 510 | } 511 | $this->part_datatype = null; 512 | $this->part_lang = null; 513 | } 514 | } 515 | 516 | function charXML($parser, $data) { 517 | @$this->chars .= $data; 518 | } 519 | 520 | } 521 | 522 | class sparql_results extends ArrayIterator 523 | { 524 | var $fields; 525 | function fields() { return $this->fields; } 526 | 527 | function render_table() 528 | { 529 | $html = ""; 530 | foreach( $this->fields as $i=>$field ) 531 | { 532 | $html .= ""; 533 | } 534 | $html .= ""; 535 | foreach( $this as $row ) 536 | { 537 | $html.=""; 538 | foreach( $row as $cell ) 539 | { 540 | $html .= ""; 541 | } 542 | $html.=""; 543 | } 544 | $html.="
?$field
".htmlspecialchars( $cell )."
545 | 550 | "; 551 | return $html;exit; 552 | } 553 | 554 | } 555 | --------------------------------------------------------------------------------