Class: XML::XXPath::Step

Inherits:
Object
  • Object
show all
Defined in:
lib/xml/xxpath/steps.rb

Overview

base class for XPath “steps”. Steps contain an “axis” (e.g. “/”, “//”, i.e. the “child” resp. “descendants” axis), and a “node matcher” like “foo” or “@bar” or “foo”, i.e. they match some XML nodes and don’t match others (e.g. “foo” macthes all XML element nodes named “foo” that contain an attribute with name “bar” and value “baz”).

Steps can find out whether they match a given XML node (Step#matches?(node)), and they know how to create a matchingnode on a given base node (Step#create_on(node,create_new)).

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(axis) ⇒ Step

Returns a new instance of Step.



32
33
34
# File 'lib/xml/xxpath/steps.rb', line 32

def initialize axis
  @axis = axis
end

Class Method Details

.compile(axis, string) ⇒ Object

create and return an instance of the right Step subclass for axis axis (:child or :descendant atm.) and node matcher string

Raises:



24
25
26
27
28
29
30
# File 'lib/xml/xxpath/steps.rb', line 24

def self.compile axis, string
  (@subclasses||=[]).each do |sc|
    obj = sc.compile axis, string
    return obj if obj
  end
  raise XXPathError, "can't compile XPath step: #{string}"
end

.inherited(subclass) ⇒ Object

:nodoc:



18
19
20
# File 'lib/xml/xxpath/steps.rb', line 18

def self.inherited(subclass)
  (@subclasses||=[]) << subclass
end

Instance Method Details

#creator(prev_creator) ⇒ Object

return a proc that takes a node, creates a sub-node matching self on it, and then calls prev_creator on that and returns the result.

Needed for compiling whole XPath expressions for writing.

Step itself provides a generic default implementation, subclasses may provide specialized implementations for better performance.



77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/xml/xxpath/steps.rb', line 77

def creator(prev_creator)
	if @axis==:child or @axis==:self
	  proc {|node,create_new|
	    prev_creator.call(self.create_on(node,create_new),
   create_new)
	  }
	else
	  proc {|node,create_new|
	    raise XXPathError, "can't create axis: #{@axis}"
	  }
	end
end

#reader(prev_reader, creator_from_here) ⇒ Object

return a proc that takes a list of nodes, finds all sub-nodes that are reachable from one of those nodes via self’s axis and match (see below) self, and calls prev_reader on them (and returns the result). When the proc doesn’t find any such nodes, it throws :not_found, [nodes,creator_from_here].

Needed for compiling whole XPath expressions for reading.

Step itself provides a generic default implementation which checks whether self matches a given node by calling self.matches?(node). Subclasses must either implement such a matches? method or override reader to provide more specialized implementations for better performance.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/xml/xxpath/steps.rb', line 50

def reader(prev_reader,creator_from_here)
  proc {|nodes|
    next_nodes = []
    nodes.each do |node|
      if node.respond_to? :each_on_axis
        node.each_on_axis(@axis) do |subnode|
          next_nodes << subnode if self.matches?(subnode)
        end
      end
    end
    if (next_nodes.empty?)
      throw :not_found, [nodes,creator_from_here]
    else
      prev_reader.call(next_nodes)
    end
  }
end