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