require "forwardable" require "open-uri" require "rss/rss" module RSS class NotWellFormedError < Error attr_reader :line, :element # Create a new NotWellFormedError for an error at +line+ # in +element+. If a block is given the return value of # the block ends up in the error message. def initialize(line=nil, element=nil) message = "This is not well formed XML" if element or line message << "\nerror occurred" message << " in #{element}" if element message << " at about #{line} line" if line end message << "\n#{yield}" if block_given? super(message) end end class XMLParserNotFound < Error def initialize super("available XML parser was not found in " << "#{AVAILABLE_PARSER_LIBRARIES.inspect}.") end end class NotValidXMLParser < Error def initialize(parser) super("#{parser} is not an available XML parser. " << "Available XML parser"<< (AVAILABLE_PARSERS.size > 1 ? "s are ": " is ") << "#{AVAILABLE_PARSERS.inspect}.") end end class NSError < InvalidRSSError attr_reader :tag, :prefix, :uri def initialize(tag, prefix, require_uri) @tag, @prefix, @uri = tag, prefix, require_uri super("prefix <#{prefix}> doesn't associate uri " << "<#{require_uri}> in tag <#{tag}>") end end class Parser extend Forwardable class << self @@default_parser = nil def default_parser @@default_parser || AVAILABLE_PARSERS.first end # Set @@default_parser to new_value if it is one of the # available parsers. Else raise NotValidXMLParser error. def default_parser=(new_value) if AVAILABLE_PARSERS.include?(new_value) @@default_parser = new_value else raise NotValidXMLParser.new(new_value) end end def parse(rss, do_validate=true, ignore_unknown_element=true, parser_class=default_parser) parser = new(rss, parser_class) parser.do_validate = do_validate parser.ignore_unknown_element = ignore_unknown_element parser.parse end end def_delegators(:@parser, :parse, :rss, :ignore_unknown_element, :ignore_unknown_element=, :do_validate, :do_validate=) def initialize(rss, parser_class=self.class.default_parser) @parser = parser_class.new(normalize_rss(rss)) end private # Try to get the XML associated with +rss+. # Return +rss+ if it already looks like XML, or treat it as a URI, # or a file to get the XML, def normalize_rss(rss) return rss if maybe_xml?(rss) uri = to_uri(rss) if uri.respond_to?(:read) uri.read elsif !rss.tainted? and File.readable?(rss) File.open(rss) {|f| f.read} else rss end end # maybe_xml? tests if source is a string that looks like XML. def maybe_xml?(source) source.is_a?(String) and /