class XML::XXPath
Instances of this class hold (in a pre-compiled form) an XPath pattern. You
call instance methods like each
, first
,
all
, create_new
on instances of this class to
apply the pattern to REXML elements.
Public Class Methods
create and compile a new XPath. xpathstr is the string representation (XPath pattern) of the path
# File lib/xml/xxpath.rb, line 21 def initialize(xpathstr) @xpathstr = xpathstr # for error messages # TODO: write a real XPath parser sometime xpathstr='/'+xpathstr if xpathstr[0] != ?/ @creator_procs = [ proc{|node,create_new| node} ] @reader_proc = proc {|nodes| nodes} part=nil; part_expected=true xpathstr.split(/(\/+)/)[1..-1].reverse.each do |x| if part_expected part=x part_expected = false next end part_expected = true axis = case x when '/' :child when '//' :descendant else raise XXPathError, "XPath (#{xpathstr}): unknown axis: #{x}" end axis=:self if axis==:child and (part[0]==?. or part=~/^self::/) # yuck step = Step.compile(axis,part) @creator_procs << step.creator(@creator_procs[-1]) @reader_proc = step.reader(@reader_proc, @creator_procs[-1]) end end
Public Instance Methods
Return an Enumerable with all sub-nodes of node that match this XPath. Returns an empty Enumerable if no match was found.
If :ensure_created=>true is provided, all() ensures that a match exists in node, creating one (and returning it as the sole element of the returned enumerable) if none existed before.
# File lib/xml/xxpath.rb, line 88 def all(node,options={}) raise "options not a hash" unless Hash===options if options[:create_new] return [ @creator_procs[-1].call(node,true) ] else last_nodes,rest_creator = catch(:not_found) do return @reader_proc.call([node]) end if options[:ensure_created] [ rest_creator.call(last_nodes[0],false) ] else [] end end end
create a completely new match of this XPath in base_node. “Completely new” means that a new node will be created for each path element, even if a matching node already existed in base_node.
path.create_new(node)
is equivalent to
path.first(node,:create_new=>true)
.
# File lib/xml/xxpath.rb, line 111 def create_new(base_node) first(base_node,:create_new=>true) end
loop over all sub-nodes of node that match this XPath.
# File lib/xml/xxpath.rb, line 57 def each(node,options={},&block) all(node,options).each(&block) end
the first sub-node of node that matches this XPath. If nothing matches, raise XXPathError unless :allow_nil=>true was provided.
If :ensure_created=>true is provided, first() ensures that a match exists in node, creating one if none existed before.
path.first(node,:create_new=>true)
is equivalent to
path.create_new(node)
.
# File lib/xml/xxpath.rb, line 69 def first(node,options={}) a=all(node,options) if a.empty? if options[:allow_nil] nil else raise XXPathError, "path not found: #{@xpathstr}" end else a[0] end end