class WsdlValidator

Helps to validate xml against schemas contained in a WSDL

Constants

VERSION

Attributes

basic_auth[RW]
doc[RW]
schemas[RW]
Nokogiri::XML::Schema
show_schemas[RW]
String

Schemas found within WSDL

Public Class Methods

new(wsdl_url) click to toggle source

Parse WSDL storing authentication and all schemas from it @param [String] wsdl_url URL to where WSDL is stored or location to where file is stored

# File lib/wsdl_validator/wsdl_validator.rb, line 15
def initialize(wsdl_url)
  self.basic_auth = extract_auth(wsdl_url)
  self.doc = Wasabi.document wsdl_url
  self.show_schemas = parse_wsdl_schemas
  self.schemas = Nokogiri::XML::Schema(show_schemas)
rescue Wasabi::Resolver::HTTPError => resolver
  raise WsdlValidator::Error, "Unauthorized for basic auth #{basic_auth}" if resolver.response.code == 401
  raise resolver
rescue Nokogiri::XML::SyntaxError => syntax_error
  puts "Error for " + show_schemas
  raise syntax_error
end

Public Instance Methods

errors_for(xml) click to toggle source

Returns a list of syntax errors. Empty list indicates valid xml @param [String, Nokogiri::XML::NodeSet] xml @return [Array] List of Nokogiri::XML::SyntaxError objects

# File lib/wsdl_validator/wsdl_validator.rb, line 43
def errors_for(xml)
  raise "Incorrect type #{xml.class}" unless [String, Nokogiri::XML::Document, Nokogiri::XML::NodeSet].include? xml.class
  xml_under_test = Nokogiri::XML(xml.to_s)
  soap_envelope = xml_under_test.children.find { |e| e.name == 'Envelope' }
  xml_under_test = extract_root_from_soap(soap_envelope) if soap_envelope
  schemas.validate(xml_under_test)
end
extract_root_from_soap(envelope) click to toggle source

Gets the namespaces from the SOAP Envelope & Body element, adds them to the root element underneath the body and returns that element. @note This is not the ideal approach. Ideally Nokogiri parser would be able to understand SOAP xsd as well @return [Nokogiri::XML::Document] Retrieve root element from SOAP

# File lib/wsdl_validator/wsdl_validator.rb, line 32
def extract_root_from_soap(envelope)
  body = envelope.children.find { |child| child.name == 'Body' }
  root_element = body.children.reject { |child| child.is_a?(Nokogiri::XML::Text) }.first
  envelope.namespaces.each { |namespace, value| root_element[namespace] = value }
  body.namespaces.each { |namespace, value| root_element[namespace] = value }
  Nokogiri::XML root_element.to_s # Convert to Xml Document
end
valid?(xml) click to toggle source

@param [String, Nokogiri::XML::NodeSet] xml @return [Boolean, Exception] Whether xml is valid according to WSDL of class

# File lib/wsdl_validator/wsdl_validator.rb, line 53
def valid?(xml)
  validator = errors_for xml
  raise WsdlValidator::Error, validator.join unless validator.empty?
  true
end
Also aliased as: validate
validate(xml)
Alias for: valid?

Private Instance Methods

add_global_namespace_to(schema) click to toggle source

Add namespaces from wsdl document to each schema Sometimes schemas are defined there and referenced within the types @return [String] String representing XML with global schemas added

# File lib/wsdl_validator/wsdl_validator.rb, line 96
def add_global_namespace_to(schema)
  doc.parser.document.collect_namespaces.each { |namespace, value| schema[namespace] = value }
  schema.to_s
end
extract_auth(wsdl_location) click to toggle source

Returns an Array with basic auth in it @return [Array] Format is [user_name, password] or []

# File lib/wsdl_validator/wsdl_validator.rb, line 65
def extract_auth(wsdl_location)
  return [] unless wsdl_location.to_s =~ /^http|socks/
  url = wsdl_location.is_a?(URI) ? wsdl_location : URI(wsdl_location)
  if url.user
    [url.user, url.password]
  else
    []
  end
end
extract_schema_for(import) click to toggle source

Makes a GET request returning the xsd from the defined location @return [String] Schema from location defined in 'schemaLocation' attribute

# File lib/wsdl_validator/wsdl_validator.rb, line 103
def extract_schema_for(import)
  raise WsdlValidator::Error, "Could not find import location from #{import}" unless import['schemaLocation']
  xsd_url = URI(import['schemaLocation'])
  xsd_url.user, xsd_url.password = basic_auth unless basic_auth.empty?
  request = HTTPI::Request.new(xsd_url.to_s)
  HTTPI.get(request).body
end
parse_wsdl_schemas() click to toggle source

Join all the schemas within the WSDL, importing schemas if necessary @return [String] Schema XML contained within WSDL

# File lib/wsdl_validator/wsdl_validator.rb, line 77
def parse_wsdl_schemas
  doc.parser.schemas.collect do |schema|
    imports = schema.children.select { |child| child.name == 'import' }
    imported_xsds = imports.collect do |import|
      extract_schema_for(import)
    end.join
    if imported_xsds.empty?
      add_global_namespace_to(schema)
    else
      imported_schemas = Nokogiri::XML(imported_xsds).children
      updated_set = imported_schemas.collect { |imported_schema| add_global_namespace_to(imported_schema) }
      updated_set.join
    end.to_s
  end.join
end