class W3C::FeedValidator

Implements an interface to the W3C Feed Validation online service, based on its SOAP 1.2 support.

It helps to find errors in RSS or Atom feeds.


Please remember that the W3C Feed Validation service is a shared resource, so do not abuse it: you should make your scripts sleep between requests.

Constants

VERSION

Attributes

errors[R]

Collection of errors founded by the w3c feed validation service. Every error is a hash containing: :type, :line, :column, :text, :element

informations[R]

Collection of informations founded by the w3c feed validation service. Every error is a hash containing: :type, :line, :column, :text, :element

request_type[R]

request_type :manuel for direct input validation :url for url validation

response[R]

The complete response (as Net::HTTPResponse object) sent it by the w3c feed validation service.

valid[R]

True if the w3c feed validation service not found errors in the feed.

valid?[R]

True if the w3c feed validation service not found errors in the feed.

warnings[R]

Collection of warnings founded by the w3c feed validation service. Every error is a hash containing: :type, :line, :column, :text, :element

Public Class Methods

new() click to toggle source

Initialize the feed validator object

# File lib/feed_validator.rb, line 78
def initialize
  clear
end

Public Instance Methods

parse(response) click to toggle source

Parse a response from the w3c feed validation service. Used by assert_valid_feed

# File lib/feed_validator/assertions.rb, line 33
def parse(response)
  clear
  if response.respond_to?(:body)
    parse_response(response.body)
  else
    parse_response(response)
  end
end
to_s() click to toggle source
# File lib/feed_validator.rb, line 123
def to_s
  msg = "Vailidity: #{@valid}\n"
  msg << "Errors count: #{@errors.size}\n"
  @errors.each_with_index{ |item, i| msg << "(#{i+1}) type: #{item[:type]} | line: #{item[:line]} | column: #{item[:column]} | text: #{item[:text]},\n"}
  msg << "Warnings count: #{@warnings.size}\n"
  @warnings.each_with_index{ |item, i| msg << "(#{i+1}) type: #{item[:type]} | line: #{item[:line]} | column: #{item[:column]} | text: #{item[:text]},\n"}
  msg << "Informations count: #{@informations.size}\n"
  @informations.each_with_index{ |item, i| msg << "(#{i+1}) type: #{item[:type]} | line: #{item[:line]} | column: #{item[:column]} | text: #{item[:text]},\n"}
  msg
end
validate_data(rawdata) click to toggle source

Validate the data provided. Returns a true value if the validation succeeded (regardless of whether the feed contains errors).

# File lib/feed_validator.rb, line 85
    def validate_data(rawdata)
      clear
      params = "rawdata=#{CGI.escape(rawdata)}&manual=1&output=soap12"
      @request_type = :manual
      begin
#        headers = VERSION == "1.8.4" ? {'Content-Type'=>'application/x-www-form-urlencoded'} : {}
        headers = {'Content-Type'=>'application/x-www-form-urlencoded'}
        @response = Net::HTTP.start('validator.w3.org',80) {|http|
          http.post('/feed/check.cgi',params,headers)
        }
      rescue Exception => e
        warn "Exception: #{e.class}: #{e.message}\n\t#{e.backtrace.join("\n\t")}" if $VERBOSE
        return false
      end

      parse_response(@response.body)
      return true
    end
validate_url(url) click to toggle source

Validate the url provided. Returns a true value if the validation succeeded (regardless of whether the feed contains errors).

# File lib/feed_validator.rb, line 107
def validate_url(url)
  clear
  params = "url=#{CGI.escape(url)}&output=soap12"
  @request_type = :url
  begin
    @response = Net::HTTP.get_response('validator.w3.org',"/feed/check.cgi?#{params}",80)
  rescue Exception => e
    warn "Exception: #{e.class}: #{e.message}\n\t#{e.backtrace.join("\n\t")}" if $VERBOSE
    return false
  end
  parse_response(@response.body)
  return true
end

Private Instance Methods

clear() click to toggle source
# File lib/feed_validator.rb, line 175
def clear #nodoc
  @response = nil
  @request_type = nil
  @valid = false
  @errors = []
  @warnings = []
  @informations = []
end
parse_response(response) click to toggle source
# File lib/feed_validator.rb, line 136
def parse_response(response) #nodoc
  xml = REXML::Document.new(response)
  @valid = (/true/.match(xml.root.elements["env:Body/m:feedvalidationresponse/m:validity"].get_text.value))? true : false
  unless @valid
    xml.elements.each("env:Envelope/env:Body/m:feedvalidationresponse/m:errors/m:errorlist/error") do |error|
      @errors << {
        :type =>    error.elements["type"].nil? ? "" : error.elements["type"].get_text.value,
        :line =>    error.elements["line"].nil? ? "" : error.elements["line"].get_text.value,
        :column =>  error.elements["column"].nil? ? "" : error.elements["column"].get_text.value,
        :text =>    error.elements["text"].nil? ? "" : error.elements["text"].get_text.value,
        :element => error.elements["element"].nil? ? "" : error.elements["element"].get_text.value
        }
    end
  end
  xml.elements.each("env:Envelope/env:Body/m:feedvalidationresponse/m:warnings/m:warninglist/warning") do |warning|
    next if
      @request_type == :manual &&
      warning.elements["type"].get_text.value == "SelfDoesntMatchLocation" &&
      warning.elements["text"].get_text.value == "Self reference doesn't match document location"

    @warnings << {
      :type =>    warning.elements["type"].nil? ? "" : warning.elements["type"].get_text.value,
      :line =>    warning.elements["line"].nil? ? "" : warning.elements["line"].get_text.value,
      :column =>  warning.elements["column"].nil? ? "" : warning.elements["column"].get_text.value,
      :text =>    warning.elements["text"].nil? ? "" : warning.elements["text"].get_text.value,
      :element => warning.elements["element"].nil? ? "" : warning.elements["element"].get_text.value
      }
  end
  xml.elements.each("env:Envelope/env:Body/m:feedvalidationresponse/m:informations/m:infolist/information") do |info|
    @informations << {
      :type =>    info.elements["type"].nil? ? "" : info.elements["type"].get_text.value,
      :line =>    info.elements["line"].nil? ? "" : info.elements["line"].get_text.value,
      :column =>  info.elements["column"].nil? ? "" : info.elements["column"].get_text.value,
      :text =>    info.elements["text"].nil? ? "" : info.elements["text"].get_text.value,
      :element => info.elements["element"].nil? ? "" : info.elements["element"].get_text.value
      }
  end
end