module Redlander # Syntax parsing methods. # "self" is assumed to be an instance of Redlander::Model module Parsing # Core parsing method for non-streams # # @note # If a block is given, the extracted statements will be yielded into # the block and inserted into the model depending on the output # of the block (if true, the statement will be added, # if false, the statement will not be added). # # @param [String, URI] content # - Can be a String, # causing the statements to be extracted # directly from it, or # - URI # causing the content to be first pulled # from the specified URI (or a local file, # if URI schema == "file:") # @param [Hash] options # @option options [String] :format name of the parser to use, # @option options [String] :mime_type MIME type of the syntax, if applicable, # @option options [String, URI] :type_uri URI of syntax, if applicable, # @option options [String, URI] :base_uri base URI, # to be applied to the nodes with relative URIs. # @yieldparam [Statement] # @raise [RedlandError] if it fails to create a parser or stream # @return [Model] def from(content, options = {}) format = options[:format].to_s mime_type = options[:mime_type] && options[:mime_type].to_s type_uri = options[:type_uri] && options[:type_uri].to_s base_uri = options[:base_uri] && options[:base_uri].to_s content = Uri.new(content) if content.is_a?(URI) # FIXME: to be fixed in librdf: # ntriples parser absolutely needs "\n" at the end of the input if format == "ntriples" && !content.is_a?(Uri) && !content.end_with?("\n") content << "\n" end rdf_parser = Redland.librdf_new_parser(Redlander.rdf_world, format, mime_type, type_uri) raise RedlandError, "Failed to create a new '#{format}' parser" if rdf_parser.null? begin if block_given? rdf_stream = if content.is_a?(Uri) Redland.librdf_parser_parse_as_stream(rdf_parser, content.rdf_uri, base_uri) else Redland.librdf_parser_parse_string_as_stream(rdf_parser, content, base_uri) end raise RedlandError, "Failed to create a new stream" if rdf_stream.null? begin while Redland.librdf_stream_end(rdf_stream).zero? statement = Statement.new(Redland.librdf_stream_get_object(rdf_stream)) statements.add(statement) if yield statement Redland.librdf_stream_next(rdf_stream) end ensure Redland.librdf_free_stream(rdf_stream) end else if content.is_a?(Uri) Redland.librdf_parser_parse_into_model(rdf_parser, content.rdf_uri, base_uri, @rdf_model).zero? else Redland.librdf_parser_parse_string_into_model(rdf_parser, content, base_uri, @rdf_model).zero? end end ensure Redland.librdf_free_parser(rdf_parser) end self end # Parse input in RDF/XML format. # Shortcut for {#from}(content, :format => "rdfxml"). # # @param (see #from) # @yieldparam [Statement] # @return [void] def from_rdfxml(content, options = {}, &block) from(content, options.merge(:format => "rdfxml"), &block) end # Parse input in NTriples format. # Shortcut for {#from}(content, :format => "ntriples"). # # @param (see #from) # @yieldparam [Statement] # @return [void] def from_ntriples(content, options = {}, &block) from(content, options.merge(:format => "ntriples"), &block) end # Parse input in Turtls format. # Shortcut for {#from}(content, :format => "turtle"). # # @param (see #from) # @yieldparam [Statement] # @return [void] def from_turtle(content, options = {}, &block) from(content, options.merge(:format => "turtle"), &block) end # Parse input as stream from URI (or File) # # @param [URI, String] uri URI of the endpoint or file path # @param [Hash] options (see {#from}) # @yieldparam [Statement] # @return [void] def from_uri(uri, options = {}, &block) if uri.is_a?(String) uri = URI.parse(uri) uri = URI.parse("file://#{File.expand_path(uri.to_s)}") if uri.scheme.nil? end from(uri, options, &block) end alias_method :from_file, :from_uri end end