1require 'rexml/validation/validationexception' 2 3module REXML 4 module Validation 5 module Validator 6 NILEVENT = [ nil ] 7 def reset 8 @current = @root 9 @root.reset 10 @root.previous = true 11 @attr_stack = [] 12 self 13 end 14 def dump 15 puts @root.inspect 16 end 17 def validate( event ) 18 #puts "Current: #@current" 19 #puts "Event: #{event.inspect}" 20 @attr_stack = [] unless defined? @attr_stack 21 match = @current.next(event) 22 raise ValidationException.new( "Validation error. Expected: "+ 23 @current.expected.join( " or " )+" from #{@current.inspect} "+ 24 " but got #{Event.new( event[0], event[1] ).inspect}" ) unless match 25 @current = match 26 27 # Check for attributes 28 case event[0] 29 when :start_element 30 #puts "Checking attributes" 31 @attr_stack << event[2] 32 begin 33 sattr = [:start_attribute, nil] 34 eattr = [:end_attribute] 35 text = [:text, nil] 36 k, = event[2].find { |key,value| 37 sattr[1] = key 38 #puts "Looking for #{sattr.inspect}" 39 m = @current.next( sattr ) 40 #puts "Got #{m.inspect}" 41 if m 42 # If the state has text children... 43 #puts "Looking for #{eattr.inspect}" 44 #puts "Expect #{m.expected}" 45 if m.matches?( eattr ) 46 #puts "Got end" 47 @current = m 48 else 49 #puts "Didn't get end" 50 text[1] = value 51 #puts "Looking for #{text.inspect}" 52 m = m.next( text ) 53 #puts "Got #{m.inspect}" 54 text[1] = nil 55 return false unless m 56 @current = m if m 57 end 58 m = @current.next( eattr ) 59 if m 60 @current = m 61 true 62 else 63 false 64 end 65 else 66 false 67 end 68 } 69 event[2].delete(k) if k 70 end while k 71 when :end_element 72 attrs = @attr_stack.pop 73 raise ValidationException.new( "Validation error. Illegal "+ 74 " attributes: #{attrs.inspect}") if attrs.length > 0 75 end 76 end 77 end 78 79 class Event 80 def initialize(event_type, event_arg=nil ) 81 @event_type = event_type 82 @event_arg = event_arg 83 end 84 85 attr_reader :event_type 86 attr_accessor :event_arg 87 88 def done? 89 @done 90 end 91 92 def single? 93 return (@event_type != :start_element and @event_type != :start_attribute) 94 end 95 96 def matches?( event ) 97 #puts "#@event_type =? #{event[0]} && #@event_arg =? #{event[1]} " 98 return false unless event[0] == @event_type 99 case event[0] 100 when nil 101 return true 102 when :start_element 103 return true if event[1] == @event_arg 104 when :end_element 105 return true 106 when :start_attribute 107 return true if event[1] == @event_arg 108 when :end_attribute 109 return true 110 when :end_document 111 return true 112 when :text 113 return (@event_arg.nil? or @event_arg == event[1]) 114=begin 115 when :processing_instruction 116 false 117 when :xmldecl 118 false 119 when :start_doctype 120 false 121 when :end_doctype 122 false 123 when :externalentity 124 false 125 when :elementdecl 126 false 127 when :entity 128 false 129 when :attlistdecl 130 false 131 when :notationdecl 132 false 133 when :end_doctype 134 false 135=end 136 else 137 false 138 end 139 end 140 141 def ==( other ) 142 return false unless other.kind_of? Event 143 @event_type == other.event_type and @event_arg == other.event_arg 144 end 145 146 def to_s 147 inspect 148 end 149 150 def inspect 151 "#{@event_type.inspect}( #@event_arg )" 152 end 153 end 154 end 155end 156