Class: SvgConform::SaxValidationHandler

Inherits:
Nokogiri::XML::SAX::Document
  • Object
show all
Defined in:
lib/svg_conform/sax_validation_handler.rb

Overview

SAX event handler for streaming SVG validation Processes XML events and dispatches to requirements

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(profile) ⇒ SaxValidationHandler

Returns a new instance of SaxValidationHandler.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/svg_conform/sax_validation_handler.rb', line 15

def initialize(profile)
  @profile = profile
  @element_stack = [] # Track parent-child hierarchy
  @path_stack = [] # Current element path
  @position_counters = [] # Stack of sibling counters per level
  @parse_errors = []
  @result = nil # Will be set in end_document

  # Create validation context (without document reference for SAX)
  @context = create_sax_context

  # Classify requirements into immediate vs deferred
  @immediate_requirements = []
  @deferred_requirements = []
  classify_requirements
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.



13
14
15
# File 'lib/svg_conform/sax_validation_handler.rb', line 13

def context
  @context
end

#resultObject (readonly)

Get result (will be nil until end_document called)



125
126
127
# File 'lib/svg_conform/sax_validation_handler.rb', line 125

def result
  @result
end

Instance Method Details

#add_parse_error(error) ⇒ Object

Handle parse errors



115
116
117
118
119
120
121
122
# File 'lib/svg_conform/sax_validation_handler.rb', line 115

def add_parse_error(error)
  @context.add_error(
    node: nil,
    message: "Parse error: #{error.message}",
    requirement_id: "parse_error",
    severity: :error,
  )
end

#characters(string) ⇒ Object

SAX Event: Text content



87
88
89
90
91
# File 'lib/svg_conform/sax_validation_handler.rb', line 87

def characters(string)
  return if @element_stack.empty?

  @element_stack.last.text_content << string
end

#end_documentObject

SAX Event: Document complete



94
95
96
97
98
99
100
101
102
# File 'lib/svg_conform/sax_validation_handler.rb', line 94

def end_document
  # Run deferred validation
  @deferred_requirements.each do |req|
    req.validate_sax_complete(@context)
  end

  # Create result
  @result = ValidationResult.new(nil, @profile, @context)
end

#end_element(_name) ⇒ Object

SAX Event: Element end tag



80
81
82
83
84
# File 'lib/svg_conform/sax_validation_handler.rb', line 80

def end_element(_name)
  @element_stack.pop
  @path_stack.pop
  @position_counters.pop
end

#error(error_message) ⇒ Object

SAX Event: Parse error



105
106
107
# File 'lib/svg_conform/sax_validation_handler.rb', line 105

def error(error_message)
  @parse_errors << error_message
end

#start_documentObject

SAX Event: Document start



33
34
35
36
37
38
39
# File 'lib/svg_conform/sax_validation_handler.rb', line 33

def start_document
  # Reset state in requirements that maintain state across validations
  reset_stateful_requirements

  # Initialize root level counters
  @position_counters.push({})
end

#start_element(name, attributes = []) ⇒ Object

SAX Event: Element start tag



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
# File 'lib/svg_conform/sax_validation_handler.rb', line 42

def start_element(name, attributes = [])
  attrs = Hash[attributes]

  # Calculate position among siblings at current level
  current_counters = @position_counters.last || {}
  current_counters[name] ||= 0
  current_counters[name] += 1
  position = current_counters[name]

  # Build element proxy
  element = ElementProxy.new(
    name: name,
    attributes: attrs,
    position: position,
    path: @path_stack.dup,
    parent: @element_stack.last,
  )

  # Push to stacks
  @element_stack.push(element)
  @path_stack.push("#{name}[#{position}]")
  @position_counters.push({}) # New level for this element's children

  # Validate with immediate requirements
  @immediate_requirements.each do |req|
    req.validate_sax_element(element, @context)
  end

  # Deferred requirements may need to collect data
  @deferred_requirements.each do |req|
    if req.respond_to?(:collect_sax_data)
      req.collect_sax_data(element,
                           @context)
    end
  end
end

#warning(warning_message) ⇒ Object

SAX Event: Warning



110
111
112
# File 'lib/svg_conform/sax_validation_handler.rb', line 110

def warning(warning_message)
  # Can log warnings if needed
end