Module: REXML::Functions

Module | REXML::Functions
In: | rexml/functions.rb

If you add a method, keep in mind two things: (1) the first argument will always be a list of nodes from which to filter. In the case of context methods (such as position), the function should return an array with a value for each child in the array. (2) all method calls from XML will have "-" replaced with "_". Therefore, in XML, "local-name()" is identical (and actually becomes) "local_name()"

### Methods

boolean ceiling compare_language concat contains context= count false floor get_namespace id lang last local_name method_missing name namespace_context namespace_context= namespace_uri normalize_space not number position processing_instruction round starts_with string string_length substring substring_after substring_before sum text translate true variables variables=

### Public Class methods

boolean( object=nil )

UNTESTED

[Source]

    # File rexml/functions.rb, line 255
        def Functions::boolean( object=nil )
          if object.kind_of? String
            if object =~ /\d+/u
              return object.to_f != 0
            else
              return object.size > 0
            end
          elsif object.kind_of? Array
            object = object.find{|x| x and true}
          end
          return object ? true : false
        end

ceiling( number )

[Source]

    # File rexml/functions.rb, line 350
        def Functions::ceiling( number )
          number(number).ceil
        end

compare_language(lang1, lang2)

[Source]

    # File rexml/functions.rb, line 302
        def Functions::compare_language lang1, lang2
          lang2.downcase.index(lang1.downcase) == 0
        end

concat( *objects )

UNTESTED

[Source]

    # File rexml/functions.rb, line 132
        def Functions::concat( *objects )
          objects.join
        end

contains( string, test )

Fixed by Mike Stok

[Source]

    # File rexml/functions.rb, line 142
        def Functions::contains( string, test )
          string(string).include? string(test)
        end

context=(value)

[Source]

    # File rexml/functions.rb, line 19
        def Functions::context=(value); @@context = value; end

count( node_set )

[Source]

    # File rexml/functions.rb, line 39
        def Functions::count( node_set )
          node_set.size
        end

false( )

UNTESTED

[Source]

    # File rexml/functions.rb, line 279
        def Functions::false(  )
          false
        end

floor( number )

[Source]

    # File rexml/functions.rb, line 346
        def Functions::floor( number )
          number(number).floor
        end

get_namespace( node_set = nil ) {|@@context[:node] if defined? @@context[:node].namespace| ...}

Helper method.

[Source]

    # File rexml/functions.rb, line 66
        def Functions::get_namespace( node_set = nil )
          if node_set == nil
            yield @@context[:node] if defined? @@context[:node].namespace
          else
            if node_set.namespace
              yield node_set
            else
              return unless node_set.kind_of? Enumerable
              node_set.each { |node| yield node if defined? node.namespace }
            end
          end
        end

id( object )

Since REXML is non-validating, this method is not implemented as it requires a DTD

[Source]

    # File rexml/functions.rb, line 45
        def Functions::id( object )
        end

lang( language )

UNTESTED

[Source]

    # File rexml/functions.rb, line 284
        def Functions::lang( language )
          lang = false
          node = @@context[:node]
          attr = nil
          until node.nil?
            if node.node_type == :element
              attr = node.attributes["xml:lang"]
              unless attr.nil?
                lang = compare_language(string(language), attr)
                break
              else
              end
            end
            node = node.parent
          end
          lang
        end

last( )

[Source]

    # File rexml/functions.rb, line 31
        def Functions::last( )
          @@context[:size]
        end

local_name( node_set=nil )

UNTESTED

[Source]

    # File rexml/functions.rb, line 49
        def Functions::local_name( node_set=nil )
          get_namespace( node_set ) do |node|
            return node.local_name
          end
        end

method_missing( id )

[Source]

    # File rexml/functions.rb, line 366
        def Functions::method_missing( id )
          puts "METHOD MISSING #{id.id2name}"
          XPath.match( @@context[:node], id.id2name )
        end

name( node_set=nil )

[Source]

    # File rexml/functions.rb, line 59
        def Functions::name( node_set=nil )
          get_namespace( node_set ) do |node|
            node.expanded_name
          end
        end

namespace_context()

[Source]

    # File rexml/functions.rb, line 16
        def Functions::namespace_context ; @@namespace_context ; end

namespace_context=(x)

[Source]

    # File rexml/functions.rb, line 14
        def Functions::namespace_context=(x) ; @@namespace_context=x ; end

namespace_uri( node_set=nil )

[Source]

    # File rexml/functions.rb, line 55
        def Functions::namespace_uri( node_set=nil )
          get_namespace( node_set ) {|node| node.namespace}
        end

normalize_space( string=nil )

UNTESTED

[Source]

    # File rexml/functions.rb, line 208
        def Functions::normalize_space( string=nil )
          string = string(@@context[:node]) if string.nil?
          if string.kind_of? Array
            string.collect{|x| string.to_s.strip.gsub(/\s+/um, ' ') if string}
          else
            string.to_s.strip.gsub(/\s+/um, ' ')
          end
        end

not( object )

UNTESTED

[Source]

    # File rexml/functions.rb, line 269
        def Functions::not( object )
          not boolean( object )
        end

number( object=nil )

a string that consists of optional whitespace followed by an optional minus sign followed by a Number followed by whitespace is converted to the IEEE 754 number that is nearest (according to the IEEE 754 round-to-nearest rule) to the mathematical value represented by the string; any other string is converted to NaN

boolean true is converted to 1; boolean false is converted to 0

a node-set is first converted to a string as if by a call to the string function and then converted in the same way as a string argument

an object of a type other than the four basic types is converted to a number in a way that is dependent on that type

[Source]

    # File rexml/functions.rb, line 319
        def Functions::number( object=nil )
          object = @@context[:node] unless object
          case object
          when true
            Float(1)
          when false
            Float(0)
          when Array
            number(string( object ))
          when Numeric
            object.to_f
          else
            str = string( object )
            #puts "STRING OF #{object.inspect} = #{str}"
            if str =~ /^\d+/
              object.to_s.to_f
            else
              (0.0 / 0.0)
            end
          end
        end

position( )

[Source]

    # File rexml/functions.rb, line 35
        def Functions::position( )
          @@context[:index]
        end

processing_instruction( node )

[Source]

    # File rexml/functions.rb, line 362
        def Functions::processing_instruction( node )
          node.node_type == :processing_instruction
        end

round( number )

[Source]

    # File rexml/functions.rb, line 354
        def Functions::round( number )
          begin
            number(number).round
          rescue FloatDomainError
            number(number)
          end
        end

starts_with( string, test )

Fixed by Mike Stok

[Source]

    # File rexml/functions.rb, line 137
        def Functions::starts_with( string, test )
          string(string).index(string(test)) == 0
        end

string( object=nil )

A node-set is converted to a string by returning the string-value of the node in the node-set that is first in document order. If the node-set is empty, an empty string is returned.

A number is converted to a string as follows

NaN is converted to the string NaN

positive zero is converted to the string 0

negative zero is converted to the string 0

positive infinity is converted to the string Infinity

negative infinity is converted to the string -Infinity

if the number is an integer, the number is represented in decimal form as a Number with no decimal point and no leading zeros, preceded by a minus sign (-) if the number is negative

otherwise, the number is represented in decimal form as a Number including a decimal point with at least one digit before the decimal point and at least one digit after the decimal point, preceded by a minus sign (-) if the number is negative; there must be no leading zeros before the decimal point apart possibly from the one required digit immediately before the decimal point; beyond the one required digit after the decimal point there must be as many, but only as many, more digits as are needed to uniquely distinguish the number from all other IEEE 754 numeric values.

The boolean false value is converted to the string false. The boolean true value is converted to the string true.

An object of a type other than the four basic types is converted to a string in a way that is dependent on that type.

[Source]

    # File rexml/functions.rb, line 114
        def Functions::string( object=nil )
          #object = @context unless object
          if object.instance_of? Array
            string( object[0] )
          elsif defined? object.node_type
            if object.node_type == :attribute
              object.value
            elsif object.node_type == :element
              object.text
            else
              object.to_s
            end
          else
            object.to_s
          end
        end

string_length( string )

UNTESTED

[Source]

    # File rexml/functions.rb, line 203
        def Functions::string_length( string )
          string(string).length
        end

substring( string, start, length=nil )

Take equal portions of Mike Stok and Sean Russell; mix vigorously, and pour into a tall, chilled glass. Serves 10,000.

[Source]

    # File rexml/functions.rb, line 170
        def Functions::substring( string, start, length=nil )
          ruby_string = string(string)
          ruby_length = if length.nil?
                          ruby_string.length.to_f
                        else
                          number(length)
                        end
          ruby_start = number(start)

          # Handle the special cases
          return '' if (
            ruby_length.nan? or
            ruby_start.nan? or
            ruby_start.infinite?
          )

          infinite_length = ruby_length.infinite? == 1
          ruby_length = ruby_string.length if infinite_length

          # Now, get the bounds.  The XPath bounds are 1..length; the ruby bounds
          # are 0..length.  Therefore, we have to offset the bounds by one.
          ruby_start = ruby_start.round - 1
          ruby_length = ruby_length.round

          if ruby_start < 0
           ruby_length += ruby_start unless infinite_length
           ruby_start = 0
          end
          return '' if ruby_length <= 0
          ruby_string[ruby_start,ruby_length]
        end

substring_after( string, test )

Kouhei fixed this too

[Source]

    # File rexml/functions.rb, line 158
        def Functions::substring_after( string, test )
          ruby_string = string(string)
          ruby_index = ruby_string.index(string(test))
          if ruby_index.nil?
            ""
          else
            ruby_string[ ruby_index+1..-1 ]
          end
        end

substring_before( string, test )

Kouhei fixed this

[Source]

    # File rexml/functions.rb, line 147
        def Functions::substring_before( string, test )
          ruby_string = string(string)
          ruby_index = ruby_string.index(string(test))
          if ruby_index.nil?
            ""
          else
            ruby_string[ 0...ruby_index ]
          end
        end

sum( nodes )

[Source]

    # File rexml/functions.rb, line 341
        def Functions::sum( nodes )
          nodes = [nodes] unless nodes.kind_of? Array
          nodes.inject(0) { |r,n| r += number(string(n)) }
        end

text( )

[Source]

    # File rexml/functions.rb, line 21
        def Functions::text( )
          if @@context[:node].node_type == :element
            return @@context[:node].find_all{|n| n.node_type == :text}.collect{|n| n.value}
          elsif @@context[:node].node_type == :text
            return @@context[:node].value
          else
            return false
          end
        end

translate( string, tr1, tr2 )

This is entirely Mike Stok’s beast

[Source]

    # File rexml/functions.rb, line 218
        def Functions::translate( string, tr1, tr2 )
          from = string(tr1)
          to = string(tr2)

          # the map is our translation table.
          #
          # if a character occurs more than once in the
          # from string then we ignore the second &
          # subsequent mappings
          #
          # if a charactcer maps to nil then we delete it
          # in the output.  This happens if the from
          # string is longer than the to string
          #
          # there's nothing about - or ^ being special in
          # http://www.w3.org/TR/xpath#function-translate
          # so we don't build ranges or negated classes

          map = Hash.new
          0.upto(from.length - 1) { |pos|
            from_char = from[pos]
            unless map.has_key? from_char
              map[from_char] =
              if pos < to.length
                to[pos]
              else
                nil
              end
            end
          }

          string(string).unpack('U*').collect { |c|
            if map.has_key? c then map[c] else c end
          }.compact.pack('U*')
        end

true( )

UNTESTED

[Source]

    # File rexml/functions.rb, line 274
        def Functions::true( )
          true
        end

variables()

[Source]

    # File rexml/functions.rb, line 17
        def Functions::variables ; @@variables ; end

variables=(x)

[Source]

    # File rexml/functions.rb, line 15
        def Functions::variables=(x) ; @@variables=x ; end

[Validate]