Extended maintenance of Ruby versions 1.8.7 and 1.9.2 will end on July 31, 2014. Read more

In Files

  • rexml/quickpath.rb

REXML::QuickPath

Constants

EMPTY_HASH

Public Class Methods

attribute( name ) click to toggle source
 
               # File 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 ) click to toggle source
 
               # File 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) click to toggle source
 
               # File rexml/quickpath.rb, line 15
def QuickPath::each element, path, namespaces=EMPTY_HASH, &block
        path = "*" unless path
        match(element, path, namespaces).each( &block )
end
            
filter(elements, path) click to toggle source

Given an array of nodes it filters the array based on the path. The result is that when this method returns, the array will contain elements which match the path

 
               # File rexml/quickpath.rb, line 48
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
                axe_name = $1
                rest = $'
                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) click to toggle source
 
               # File rexml/quickpath.rb, line 11
def QuickPath::first element, path, namespaces=EMPTY_HASH
        match(element, path, namespaces)[0]
end
            
function( elements, fname, rest ) click to toggle source
 
               # File 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 Fixnum
                        results << element if Functions.pair[0] == res
                end
        end
        return results
end
            
match(element, path, namespaces=EMPTY_HASH) click to toggle source
 
               # File rexml/quickpath.rb, line 20
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
                matches = []
                children = element.to_a
                results = filter(children, path)
        else
                results = filter([element], path)
        end
        return results
end
            
method_missing( id, *args ) click to toggle source
 
               # File 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() click to toggle source
 
               # File rexml/quickpath.rb, line 210
def QuickPath::name()
        return Functions.node.name if Functions.node.kind_of? Element
end
            
parse_args( element, string ) click to toggle source
 
               # File 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 ) click to toggle source

A predicate filters a node-set with respect to an axis to produce a new node-set. For each node in the node-set to be filtered, the PredicateExpr is evaluated with that node as the context node, with the number of nodes in the node-set as the context size, and with the proximity position of the node in the node-set with respect to the axis as the context position; if PredicateExpr evaluates to true for that node, the node is included in the new node-set; otherwise, it is not included.

A PredicateExpr is evaluated by evaluating the Expr and converting the result to a boolean. If the result is a number, the result will be converted to true if the number is equal to the context position and will be converted to false otherwise; if the result is not a number, then the result will be converted as if by a call to the boolean function. Thus a location path para is equivalent to para.

 
               # File rexml/quickpath.rb, line 160
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!( /([^\s(and)(or)<>=]+)\s*([<>=])\s*([^\s(and)(or)<>=]+)\s*([<>=])\s*([^\s(and)(or)<>=]+)/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 Fixnum
                        results << element if Functions.pair[0] == res
                when String
                        results << element
                end
        end
        return filter( results, rest )
end
            

Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.

If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.

If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.

If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.

blog comments powered by Disqus