module XML::Schema
Public Class Methods
validate(xml_doc)
click to toggle source
# File lib/validate_xml_xsi.rb, line 26 def self.validate(xml_doc) xml_doc = XML::parse(xml_doc) unless xml_doc.is_a?(Nokogiri::XML::Document) errors = [] ## Build an all-in-one XSD document that imports all of the separate schema locations xsd_doc = "<?xml version=\"1.0\"?>\n" xsd_doc << "<xsd:schema targetNamespace=\"http://www.w3.orig/XML/1998/namespace\"\n" \ " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" \ " version=\"1.0\">\n" ## Iterate over all the elements and find any xsi:schemaLocation attributes ## and build a hash of all of the namespaces and locations schemata_by_ns = {} xml_doc.search('//*[@xsi:schemaLocation]').each do |elem| elem['xsi:schemaLocation'].scan(/(\S+)\s+(\S+)/).each do |ns_set| if ns_loc = schemata_by_ns[ns_set.first] unless ns_loc.eql?(ns_set.last) error "MISMATCHING XMLNS XSI: #{ns_set.first} -> #{ns_loc} VS #{ns_set.last}" end else schemata_by_ns[ns_set.first] = ns_set.last end end end schemata_by_ns.each do |ns_href, ns_file| xsd_doc << " <xsd:import namespace=\"#{ns_href}\" schemaLocation=\"#{ns_file}\"/>\n" end xsd_doc << "</xsd:schema>\n" xsd = Nokogiri::XML.Schema(xsd_doc) xsd.errors.each do |err| err_msg = (/ERROR: /.match(err.message)) ? $' : err.message errors << XML::Validation::Error.new(:XSD, err.file, err.line, err.column, err_msg, err) end errs = xsd.validate(xml_doc) errs.each do |err| err_msg = (/ERROR: /.match(err.message)) ? $' : err.message fname = (err.file.nil?) ? xml_doc.filename : err.file errors << XML::Validation::Error.new(:XML, fname, err.line, err.column, err_msg, err) end errors end