1 | require 'rexml/validation/validationexception'
|
---|
2 |
|
---|
3 | module 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,v = event[2].find { |k,v|
|
---|
37 | sattr[1] = k
|
---|
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] = v
|
---|
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
|
---|
155 | end
|
---|