class NdrImport::Helpers::File::XmlStreaming::Cursor
Object to track state as the XML is iterated over, and detect when an element of interest is entered.
Constants
- StackItem
wrapper to hold a representation of each element we descent into:
Public Class Methods
new(xpath)
click to toggle source
# File lib/ndr_import/helpers/file/xml_streaming.rb, line 36 def initialize(xpath) @xpath = xpath @stack = [] @match_depth = nil end
Public Instance Methods
enter(node)
click to toggle source
# File lib/ndr_import/helpers/file/xml_streaming.rb, line 47 def enter(node) @stack.push StackItem.new(node.name, node.attributes, node.empty_element?) end
in?(node)
click to toggle source
Has this cursor already passed inside a similar node?
# File lib/ndr_import/helpers/file/xml_streaming.rb, line 43 def in?(node) @stack.detect { |item| item.name == node.name } end
leave(_node)
click to toggle source
# File lib/ndr_import/helpers/file/xml_streaming.rb, line 51 def leave(_node) @stack.pop @match_depth = nil if @match_depth && @stack.length < @match_depth end
matches?()
click to toggle source
Does the element that the cursor is currently on match what is being looked for?
# File lib/ndr_import/helpers/file/xml_streaming.rb, line 58 def matches? # Can't match again if we're inside a match already: return false if @matched_depth match = current_stack_match? # "empty element" matches are yielded immediately, without # tagging the stack as having matched, because there won't # be an equivalent closing tag to end the match with later. if in_empty_element? @stack.pop elsif match @match_depth = @stack.length end match end
Private Instance Methods
add_items_to_dom(dom, items)
click to toggle source
Helper to recursively build XML fragment.
# File lib/ndr_import/helpers/file/xml_streaming.rb, line 104 def add_items_to_dom(dom, items) item = items.shift dom.send(item.name, item.attrs) do add_items_to_dom(dom, items) if items.any? end end
current_stack_match?()
click to toggle source
Does the current state of the stack mean we've met the xpath criteria? Must be an exact match, not just matching a parent element in the DOM.
# File lib/ndr_import/helpers/file/xml_streaming.rb, line 85 def current_stack_match? parent_stack = @stack[0..-2] return false unless dom_stubs[@stack].at_xpath(@xpath) parent_stack.empty? || !dom_stubs[parent_stack].at_xpath(@xpath) end
dom_stubs()
click to toggle source
A cached collection of DOM fragments, to represent the structure necessary to use xpath to descend into the main document's DOM.
# File lib/ndr_import/helpers/file/xml_streaming.rb, line 95 def dom_stubs @dom_stubs ||= Hash.new do |hash, items| hash[items.dup] = Nokogiri::XML::Builder.new do |dom| add_items_to_dom(dom, items.dup) end.doc end end
in_empty_element?()
click to toggle source
# File lib/ndr_import/helpers/file/xml_streaming.rb, line 78 def in_empty_element? @stack.last.empty end