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