8 * Copyright (c) 2009-2013 Nicholas J Humfrey. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
18 * promote products derived from this software without specific prior
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 * @copyright Copyright (c) 2009-2013 Nicholas J Humfrey
35 * @license http://www.opensource.org/licenses/bsd-license.php
39 * Class to parse RDF using Redland (librdf) C library.
42 * @copyright Copyright (c) 2009-2013 Nicholas J Humfrey
43 * @license http://www.opensource.org/licenses/bsd-license.php
45 class EasyRdf_Parser_Redland extends EasyRdf_Parser
47 /** Variable set to the librdf world */
48 private $world = null;
50 /** Parser feature URI string for getting the error count of last parse. */
51 const LIBRDF_PARSER_FEATURE_ERROR_COUNT =
52 'http://feature.librdf.org/parser-error-count';
55 * Types supported by Redland:
58 * turtle: Turtle Terse RDF Triple Language
59 * trig: TriG - Turtle with Named Graphs
60 * rss-tag-soup: RSS Tag Soup
61 * grddl: Gleaning Resource Descriptions from Dialects of Languages
62 * guess: Pick the parser to use using content type and URI
63 * rdfa: RDF/A via librdfa
70 * Convert a librdf node type into a string
73 protected function nodeTypeString($node)
75 switch(librdf_node_get_type($node)) {
92 * Convert the URI for a node into a string
95 protected function nodeUriString($node)
97 $type = EasyRdf_Parser_Redland::nodeTypeString($node);
99 $uri = librdf_node_get_uri($node);
101 throw new EasyRdf_Exception("Failed to get URI of node");
103 $str = librdf_uri_to_string($uri);
105 throw new EasyRdf_Exception(
106 "Failed to convert librdf_uri to string"
110 } elseif ($type == 'bnode') {
111 return $this->remapBnode(
112 librdf_node_get_blank_identifier($node)
115 throw new EasyRdf_Exception("Unsupported type: ".$type);
120 * Convert a node into an associate array
123 protected function nodeToRdfPhp($node)
126 $object['type'] = EasyRdf_Parser_Redland::nodeTypeString($node);
127 if ($object['type'] == 'uri') {
128 $object['value'] = EasyRdf_Parser_Redland::nodeUriString($node);
129 } elseif ($object['type'] == 'bnode') {
130 $object['value'] = '_:'.librdf_node_get_blank_identifier($node);
131 } elseif ($object['type'] == 'literal') {
132 $object['value'] = librdf_node_get_literal_value($node);
133 $lang = librdf_node_get_literal_value_language($node);
135 $object['lang'] = $lang;
137 $datatype = librdf_node_get_literal_value_datatype_uri($node);
139 $object['datatype'] = librdf_uri_to_string($datatype);
142 throw new EasyRdf_Exception("Unsupported type: ".$object['type']);
148 * Return the number of errors during parsing
151 protected function parserErrorCount($parser)
153 $errorUri = librdf_new_uri(
155 self::LIBRDF_PARSER_FEATURE_ERROR_COUNT
157 $errorNode = librdf_parser_get_feature($parser, $errorUri);
158 $errorCount = librdf_node_get_literal_value($errorNode);
159 librdf_free_uri($errorUri);
166 * @return object EasyRdf_Parser_Redland
168 public function __construct()
170 if (extension_loaded('redland')) {
171 $this->world = librdf_php_get_world();
173 throw new EasyRdf_Exception(
174 "Failed to initialise librdf world."
178 throw new EasyRdf_Exception(
179 "Redland PHP extension is not available."
185 * Parse an RDF document into an EasyRdf_Graph
187 * @param object EasyRdf_Graph $graph the graph to load the data into
188 * @param string $data the RDF document data
189 * @param string $format the format of the input data
190 * @param string $baseUri the base URI of the data being parsed
191 * @return integer The number of triples added to the graph
193 public function parse($graph, $data, $format, $baseUri)
195 parent::checkParseParams($graph, $data, $format, $baseUri);
197 $parser = librdf_new_parser($this->world, $format, null, null);
199 throw new EasyRdf_Exception(
200 "Failed to create librdf_parser of type: $format"
204 $rdfUri = librdf_new_uri($this->world, $baseUri);
206 throw new EasyRdf_Exception(
207 "Failed to create librdf_uri from: $baseUri"
211 $stream = librdf_parser_parse_string_as_stream($parser, $data, $rdfUri);
213 throw new EasyRdf_Parser_Exception(
214 "Failed to parse RDF stream"
219 $statement = librdf_stream_get_object($stream);
221 $subject = EasyRdf_Parser_Redland::nodeUriString(
222 librdf_statement_get_subject($statement)
224 $predicate = EasyRdf_Parser_Redland::nodeUriString(
225 librdf_statement_get_predicate($statement)
227 $object = EasyRdf_Parser_Redland::nodeToRdfPhp(
228 librdf_statement_get_object($statement)
231 $this->addTriple($subject, $predicate, $object);
233 } while (!librdf_stream_next($stream));
235 $errorCount = $this->parserErrorCount($parser);
237 throw new EasyRdf_Parser_Exception("$errorCount errors while parsing.");
240 librdf_free_uri($rdfUri);
241 librdf_free_stream($stream);
242 librdf_free_parser($parser);
244 return $this->tripleCount;