class WsdlValidator
Helps to validate xml against schemas contained in a WSDL
Constants
- VERSION
Attributes
- Nokogiri::XML::Schema
- String
-
Schemas found within WSDL
Public Class Methods
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
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
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
@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
Private Instance Methods
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
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
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
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