Class: XML_XSI::Schema

Inherits:
Object
  • Object
show all
Defined in:
lib/validate_xml_xsi.rb

Defined Under Namespace

Classes: DocumentError, ValidationError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(xml_doc) ⇒ Schema

Returns a new instance of Schema.

Raises:



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/validate_xml_xsi.rb', line 38

def initialize(xml_doc)
  unless xml_doc.is_a?(Nokogiri::XML::Document)
    raise DocumentError.new("invalid Nokogiri::XML::Document - #{xml_doc.class.name}")
  end
  @document = xml_doc
  ## Determine default/top/root namespace
  target_ns_href = nil
  @document.namespaces.each do |ns_prefix, ns_href|
    target_ns_href = ns_href if ns_prefix.nil? || ns_prefix.empty? || ns_prefix.eql?('xmlns')
  end
  raise DocumentError.new("Unable to determine default (xmlns) namespace!") if target_ns_href.nil? || target_ns_href.empty?
  ## Build an all-in-one XSD document that imports all of the separate schema locations
  @xsd = "<?xml version=\"1.0\"?>\n"
  @xsd << "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" \
             "            targetNamespace=\"#{target_ns_href}\"\n" \
             "            version=\"1.0\">\n"
  ## Include the default xml namespace
  schemata_by_ns = {}
  ## Iterate over all the elements and find any xsi:schemaLocation attributes
  ## and build a hash of all of the namespaces and locations
  @document.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)
          raise DocumentError.new("MISMATCHING namespace: #{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 << (ns_href.eql?(target_ns_href) ?
                "  <xsd:include schemaLocation=\"#{ns_file}\"/>\n" :
                "  <xsd:import namespace=\"#{ns_href}\" schemaLocation=\"#{ns_file}\"/>\n")
  end
  @xsd << "</xsd:schema>\n"

  ## Create the Schema objects
  @schema = Nokogiri::XML::Schema.new(@xsd)
end

Instance Attribute Details

#xsdObject (readonly)

Returns the value of attribute xsd.



37
38
39
# File 'lib/validate_xml_xsi.rb', line 37

def xsd
  @xsd
end

Instance Method Details

#validateObject



80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/validate_xml_xsi.rb', line 80

def validate
  errors = []
  @schema.errors.each do |err|
    errors << ValidationError.new(:XSD, err)
  end
  errs = @schema.validate(@document)
  errs.each do |err|
    fname = (err.file.nil?) ? @document.filename : err.file
    errors << ValidationError.new(:XML, err, fname)
  end
  errors
end