class REXML::QuickPath
常量
- EMPTY_HASH
一个基础的 Hash 对象,用于初始化默认的空命名空间集。
- OPERAND_
公共类方法
attribute( name ) 点击切换源代码
# File rexml-3.4.0/lib/rexml/quickpath.rb, line 206 def QuickPath::attribute( name ) return Functions.node.attributes[name] if Functions.node.kind_of? Element end
axe( elements, axe_name, rest ) 点击切换源代码
# File rexml-3.4.0/lib/rexml/quickpath.rb, line 106 def QuickPath::axe( elements, axe_name, rest ) matches = [] matches = filter( elements.dup, rest ) if axe_name =~ /-or-self$/u case axe_name when /^descendant/u elements.each do |element| matches |= filter( element.to_a, "descendant-or-self::#{rest}" ) if element.kind_of? Element end when /^ancestor/u elements.each do |element| while element.parent matches << element.parent element = element.parent end end matches = filter( matches, rest ) when "self" matches = filter( elements, rest ) when "child" elements.each do |element| matches |= filter( element.to_a, rest ) if element.kind_of? Element end when "attribute" elements.each do |element| matches << element.attributes[ rest ] if element.kind_of? Element end when "parent" matches = filter(elements.collect{|element| element.parent}.uniq, rest) when "following-sibling" matches = filter(elements.collect{|element| element.next_sibling}.uniq, rest) when "previous-sibling" matches = filter(elements.collect{|element| element.previous_sibling}.uniq, rest ) end return matches.uniq end
each(element, path, namespaces=EMPTY_HASH, &block) 点击切换源代码
# File rexml-3.4.0/lib/rexml/quickpath.rb, line 18 def QuickPath::each element, path, namespaces=EMPTY_HASH, &block path = "*" unless path match(element, path, namespaces).each( &block ) end
filter(elements, path) 点击切换源代码
给定一个节点数组,它会根据路径过滤该数组。结果是,当此方法返回时,该数组将包含与路径匹配的元素
# File rexml-3.4.0/lib/rexml/quickpath.rb, line 50 def QuickPath::filter elements, path return elements if path.nil? or path == '' or elements.size == 0 case path when /^\/\//u # Descendant return axe( elements, "descendant-or-self", $' ) when /^\/?\b(\w[-\w]*)\b::/u # Axe return axe( elements, $1, $' ) when /^\/(?=\b([:!\w][-\.\w]*:)?[-!\*\.\w]*\b([^:(]|$)|\*)/u # Child rest = $' results = [] elements.each do |element| results |= filter( element.to_a, rest ) end return results when /^\/?(\w[-\w]*)\(/u # / Function return function( elements, $1, $' ) when Namespace::NAMESPLIT # Element name name = $2 ns = $1 rest = $' elements.delete_if do |element| !(element.kind_of? Element and (element.expanded_name == name or (element.name == name and element.namespace == Functions.namespace_context[ns]))) end return filter( elements, rest ) when /^\/\[/u matches = [] elements.each do |element| matches |= predicate( element.to_a, path[1..-1] ) if element.kind_of? Element end return matches when /^\[/u # Predicate return predicate( elements, path ) when /^\/?\.\.\./u # Ancestor return axe( elements, "ancestor", $' ) when /^\/?\.\./u # Parent return filter( elements.collect{|e|e.parent}, $' ) when /^\/?\./u # Self return filter( elements, $' ) when /^\*/u # Any results = [] elements.each do |element| results |= filter( [element], $' ) if element.kind_of? Element #if element.kind_of? Element # children = element.to_a # children.delete_if { |child| !child.kind_of?(Element) } # results |= filter( children, $' ) #end end return results end return [] end
first(element, path, namespaces=EMPTY_HASH) 点击切换源代码
# File rexml-3.4.0/lib/rexml/quickpath.rb, line 14 def QuickPath::first element, path, namespaces=EMPTY_HASH match(element, path, namespaces)[0] end
function( elements, fname, rest ) 点击切换源代码
# File rexml-3.4.0/lib/rexml/quickpath.rb, line 222 def QuickPath::function( elements, fname, rest ) args = parse_args( elements, rest ) Functions.pair = [0, elements.size] results = [] elements.each do |element| Functions.pair[0] += 1 Functions.node = element res = Functions.send( fname, *args ) case res when true results << element when Integer results << element if Functions.pair[0] == res end end return results end
match(element, path, namespaces=EMPTY_HASH) 点击切换源代码
# File rexml-3.4.0/lib/rexml/quickpath.rb, line 23 def QuickPath::match element, path, namespaces=EMPTY_HASH raise "nil is not a valid xpath" unless path results = nil Functions::namespace_context = namespaces case path when /^\/([^\/]|$)/u # match on root path = path[1..-1] return [element.root.parent] if path == '' results = filter([element.root], path) when /^[-\w]*::/u results = filter([element], path) when /^\*/u results = filter(element.to_a, path) when /^[\[!\w:]/u # match on child children = element.to_a results = filter(children, path) else results = filter([element], path) end return results end
method_missing( id, *args ) 点击切换源代码
# File rexml-3.4.0/lib/rexml/quickpath.rb, line 214 def QuickPath::method_missing( id, *args ) begin Functions.send( id.id2name, *args ) rescue Exception raise "METHOD: #{id.id2name}(#{args.join ', '})\n#{$!.message}" end end
name() 点击切换源代码
# File rexml-3.4.0/lib/rexml/quickpath.rb, line 210 def QuickPath::name() return Functions.node.name if Functions.node.kind_of? Element end
parse_args( element, string ) 点击切换源代码
# File rexml-3.4.0/lib/rexml/quickpath.rb, line 240 def QuickPath::parse_args( element, string ) # /.*?(?:\)|,)/ arguments = [] buffer = "" while string and string != "" c = string[0] string.sub!(/^./u, "") case c when ?, # if depth = 1, then we start a new argument arguments << evaluate( buffer ) #arguments << evaluate( string[0..count] ) when ?( # start a new method call function( element, buffer, string ) buffer = "" when ?) # close the method call and return arguments return arguments else buffer << c end end "" end
predicate( elements, path ) 点击切换源代码
谓词根据轴过滤一个节点集,以产生一个新的节点集。对于要过滤的节点集中的每个节点,都使用该节点作为上下文节点,节点集中的节点数作为上下文大小,以及节点在轴上的邻近位置作为上下文位置来评估 PredicateExpr;如果 PredicateExpr 对于该节点评估为 true,则该节点包含在新节点集中;否则,它不会被包含。
PredicateExpr 通过评估 Expr 并将结果转换为布尔值来评估。如果结果是一个数字,如果该数字等于上下文位置,则结果将转换为 true,否则将转换为 false;如果结果不是数字,则结果将像调用布尔函数一样进行转换。因此,位置路径 para 等效于 para。
# File rexml-3.4.0/lib/rexml/quickpath.rb, line 161 def QuickPath::predicate( elements, path ) ind = 1 bcount = 1 while bcount > 0 bcount += 1 if path[ind] == ?[ bcount -= 1 if path[ind] == ?] ind += 1 end ind -= 1 predicate = path[1..ind-1] rest = path[ind+1..-1] # have to change 'a [=<>] b [=<>] c' into 'a [=<>] b and b [=<>] c' # predicate.gsub!( /#{OPERAND_}\s*([<>=])\s*#{OPERAND_}\s*([<>=])\s*#{OPERAND_}/u, '\1 \2 \3 and \3 \4 \5' ) # Let's do some Ruby trickery to avoid some work: predicate.gsub!( /&/u, "&&" ) predicate.gsub!( /=/u, "==" ) predicate.gsub!( /@(\w[-\w.]*)/u, 'attribute("\1")' ) predicate.gsub!( /\bmod\b/u, "%" ) predicate.gsub!( /\b(\w[-\w.]*\()/u ) { fname = $1 fname.gsub( /-/u, "_" ) } Functions.pair = [ 0, elements.size ] results = [] elements.each do |element| Functions.pair[0] += 1 Functions.node = element res = eval( predicate ) case res when true results << element when Integer results << element if Functions.pair[0] == res when String results << element end end return filter( results, rest ) end