Module: Xpath
- Included in:
- Rind::Cdata, Rind::Comment, Rind::Element, Rind::ProcessingInstruction, Rind::Text
- Defined in:
- lib/rind/xpath.rb
Overview
Current Xpath support is fairly basic but covers almost all axes and node tests. Predicates are limited to attribute and position checks. I intend to expand support but that should cover most of the needed functionality.
Instance Method Summary collapse
-
#s(path) ⇒ Object
Xpath search of a node that returns a list of matching nodes.
-
#sf(path) ⇒ Object
Xpath search returning only the first matching node in the list.
Instance Method Details
#s(path) ⇒ Object
Xpath search of a node that returns a list of matching nodes.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 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 |
# File 'lib/rind/xpath.rb', line 6 def s(path) node = self # absolute paths to the top if '/' == path[0,1] while not node.parent.nil? node = node.parent end if '/' != path[1,1] path[0] = 'self::' end end # node check nodes = [node] path.scan(%r{(?:^\/?|\/) (?:([^\/]*?)::)? # axis ([^\/\[]+)? # node test ((?:\[.+?\])*) # predicates }x) do |axis, node_test, predicates| case node_test when nil axis = 'descendant-or-self' node_test = 'node()' when '.' axis = 'self' node_test = 'node()' when '..' axis = 'parent' node_test = 'node()' end axis = 'child' if axis.nil? node_test.gsub!(/^@/, 'attribute::') predicates.gsub!(/^@/, 'attribute::') # find matching nodes nodes = nodes.collect{|node| node.find_matching_nodes(axis, node_test)}.flatten.compact.uniq # check predicates if not predicates.nil? # true() and false() predicates.gsub!(/(true|false)\(\)/, '\1') # == predicates.gsub!(/=/, '==') predicates.scan(/\[(.*?)\]/) do |predicate| predicate = predicate[0] # last() predicate.gsub!(/last\(\)/, nodes.length.to_s) nodes = nodes.find_all do |node| node.validate_predicate(predicate.clone, Rind::Nodes[*nodes].exact_index(node)+1) end break if nodes.empty? end end return Rind::Nodes.new if nodes.empty? end Rind::Nodes.new(nodes) end |
#sf(path) ⇒ Object
Xpath search returning only the first matching node in the list.
72 73 74 |
# File 'lib/rind/xpath.rb', line 72 def sf(path) self.s(path).first end |