Class: XmlNodeStream::Selector

Inherits:
Object
  • Object
show all
Defined in:
lib/xml_node_stream/selector.rb

Overview

Partial implementation of XPath selectors. Only abbreviated paths and the text() function are supported. The rest of XPath is unecessary in the context of a Ruby application since XPath is also a programming language. If you really need an XPath function, chances are you can just do it in the Ruby code.

Example selectors:

  • book - find all child book elements

  • book/author - find all author elements that are children of the book child elements

  • ../book - find all sibling book elements

  • */author - find all author elements that are children of any child elements

  • book//author - find all author elements that descendants at any level of book child elements

  • .//author - find all author elements that are descendants of the current element

  • /library/books/book - find all book elements with the full path /library/books/book

  • author/text() - get the text values of all author child elements

Defined Under Namespace

Classes: Matcher

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ Selector

Create a selector. Path should be an abbreviated XPath string.



17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/xml_node_stream/selector.rb', line 17

def initialize (path)
  @parts = []
  path.gsub('//', '/%/').split('/').each do |part_path|
    part_matchers = []
    @parts << part_matchers
    or_paths = part_path.split('|')
    or_paths << "" if or_paths.empty?
    or_paths.each do |matcher_path|
      part_matchers << Matcher.new(matcher_path)
    end
  end
end

Instance Method Details

#find(node) ⇒ Object

Apply the selector to the current node. Note, if your path started with a /, it will be applied to the root node.



32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/xml_node_stream/selector.rb', line 32

def find (node)
  matched = [node]
  @parts.each do |part_matchers|
    context = matched
    matched = []
    part_matchers.each do |matcher|
      matched.concat(matcher.select(context))
    end
    break if matched.empty?
  end
  return matched
end