Module | REXML::Functions |
In: |
lib/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()"
UNTESTED
# File lib/rexml/functions.rb, line 265 265: def Functions::boolean( object=nil ) 266: if object.kind_of? String 267: if object =~ /\d+/u 268: return object.to_f != 0 269: else 270: return object.size > 0 271: end 272: elsif object.kind_of? Array 273: object = object.find{|x| x and true} 274: end 275: return object ? true : false 276: end
# File lib/rexml/functions.rb, line 361 361: def Functions::ceiling( number ) 362: number(number).ceil 363: end
# File lib/rexml/functions.rb, line 312 312: def Functions::compare_language lang1, lang2 313: lang2.downcase.index(lang1.downcase) == 0 314: end
UNTESTED
# File lib/rexml/functions.rb, line 145 145: def Functions::concat( *objects ) 146: objects.join 147: end
Fixed by Mike Stok
# File lib/rexml/functions.rb, line 155 155: def Functions::contains( string, test ) 156: string(string).include?(string(test)) 157: end
# File lib/rexml/functions.rb, line 39 39: def Functions::count( node_set ) 40: node_set.size 41: end
# File lib/rexml/functions.rb, line 357 357: def Functions::floor( number ) 358: number(number).floor 359: end
Helper method.
# File lib/rexml/functions.rb, line 66 66: def Functions::get_namespace( node_set = nil ) 67: if node_set == nil 68: yield @@context[:node] if defined? @@context[:node].namespace 69: else 70: if node_set.respond_to? :each 71: node_set.each { |node| yield node if defined? node.namespace } 72: elsif node_set.respond_to? :namespace 73: yield node_set 74: end 75: end 76: end
UNTESTED
# File lib/rexml/functions.rb, line 294 294: def Functions::lang( language ) 295: lang = false 296: node = @@context[:node] 297: attr = nil 298: until node.nil? 299: if node.node_type == :element 300: attr = node.attributes["xml:lang"] 301: unless attr.nil? 302: lang = compare_language(string(language), attr) 303: break 304: else 305: end 306: end 307: node = node.parent 308: end 309: lang 310: end
UNTESTED
# File lib/rexml/functions.rb, line 49 49: def Functions::local_name( node_set=nil ) 50: get_namespace( node_set ) do |node| 51: return node.local_name 52: end 53: end
# File lib/rexml/functions.rb, line 377 377: def Functions::method_missing( id ) 378: puts "METHOD MISSING #{id.id2name}" 379: XPath.match( @@context[:node], id.id2name ) 380: end
# File lib/rexml/functions.rb, line 59 59: def Functions::name( node_set=nil ) 60: get_namespace( node_set ) do |node| 61: node.expanded_name 62: end 63: end
# File lib/rexml/functions.rb, line 16 16: def Functions::namespace_context ; @@namespace_context ; end
# File lib/rexml/functions.rb, line 14 14: def Functions::namespace_context=(x) ; @@namespace_context=x ; end
# File lib/rexml/functions.rb, line 55 55: def Functions::namespace_uri( node_set=nil ) 56: get_namespace( node_set ) {|node| node.namespace} 57: end
UNTESTED
# File lib/rexml/functions.rb, line 218 218: def Functions::normalize_space( string=nil ) 219: string = string(@@context[:node]) if string.nil? 220: if string.kind_of? Array 221: string.collect{|x| string.to_s.strip.gsub(/\s+/um, ' ') if string} 222: else 223: string.to_s.strip.gsub(/\s+/um, ' ') 224: end 225: end
UNTESTED
# File lib/rexml/functions.rb, line 279 279: def Functions::not( object ) 280: not boolean( object ) 281: end
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
# File lib/rexml/functions.rb, line 329 329: def Functions::number( object=nil ) 330: object = @@context[:node] unless object 331: case object 332: when true 333: Float(1) 334: when false 335: Float(0) 336: when Array 337: number(string( object )) 338: when Numeric 339: object.to_f 340: else 341: str = string( object ) 342: # If XPath ever gets scientific notation... 343: #if str =~ /^\s*-?(\d*\.?\d+|\d+\.)([Ee]\d*)?\s*$/ 344: if str =~ /^\s*-?(\d*\.?\d+|\d+\.)\s*$/ 345: str.to_f 346: else 347: (0.0 / 0.0) 348: end 349: end 350: end
# File lib/rexml/functions.rb, line 373 373: def Functions::processing_instruction( node ) 374: node.node_type == :processing_instruction 375: end
# File lib/rexml/functions.rb, line 365 365: def Functions::round( number ) 366: begin 367: number(number).round 368: rescue FloatDomainError 369: number(number) 370: end 371: end
Fixed by Mike Stok
# File lib/rexml/functions.rb, line 150 150: def Functions::starts_with( string, test ) 151: string(string).index(string(test)) == 0 152: end
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.
# File lib/rexml/functions.rb, line 113 113: def Functions::string( object=nil ) 114: #object = @context unless object 115: if object.instance_of? Array 116: string( object[0] ) 117: elsif defined? object.node_type 118: if object.node_type == :attribute 119: object.value 120: elsif object.node_type == :element || object.node_type == :document 121: string_value(object) 122: else 123: object.to_s 124: end 125: elsif object.nil? 126: return "" 127: else 128: object.to_s 129: end 130: end
UNTESTED
# File lib/rexml/functions.rb, line 213 213: def Functions::string_length( string ) 214: string(string).length 215: end
# File lib/rexml/functions.rb, line 132 132: def Functions::string_value( o ) 133: rv = "" 134: o.children.each { |e| 135: if e.node_type == :text 136: rv << e.to_s 137: elsif e.node_type == :element 138: rv << string_value( e ) 139: end 140: } 141: rv 142: end
Take equal portions of Mike Stok and Sean Russell; mix vigorously, and pour into a tall, chilled glass. Serves 10,000.
# File lib/rexml/functions.rb, line 180 180: def Functions::substring( string, start, length=nil ) 181: ruby_string = string(string) 182: ruby_length = if length.nil? 183: ruby_string.length.to_f 184: else 185: number(length) 186: end 187: ruby_start = number(start) 188: 189: # Handle the special cases 190: return '' if ( 191: ruby_length.nan? or 192: ruby_start.nan? or 193: ruby_start.infinite? 194: ) 195: 196: infinite_length = ruby_length.infinite? == 1 197: ruby_length = ruby_string.length if infinite_length 198: 199: # Now, get the bounds. The XPath bounds are 1..length; the ruby bounds 200: # are 0..length. Therefore, we have to offset the bounds by one. 201: ruby_start = ruby_start.round - 1 202: ruby_length = ruby_length.round 203: 204: if ruby_start < 0 205: ruby_length += ruby_start unless infinite_length 206: ruby_start = 0 207: end 208: return '' if ruby_length <= 0 209: ruby_string[ruby_start,ruby_length] 210: end
Kouhei fixed this too
# File lib/rexml/functions.rb, line 171 171: def Functions::substring_after( string, test ) 172: ruby_string = string(string) 173: test_string = string(test) 174: return $1 if ruby_string =~ /#{test}(.*)/ 175: "" 176: end
Kouhei fixed this
# File lib/rexml/functions.rb, line 160 160: def Functions::substring_before( string, test ) 161: ruby_string = string(string) 162: ruby_index = ruby_string.index(string(test)) 163: if ruby_index.nil? 164: "" 165: else 166: ruby_string[ 0...ruby_index ] 167: end 168: end
# File lib/rexml/functions.rb, line 352 352: def Functions::sum( nodes ) 353: nodes = [nodes] unless nodes.kind_of? Array 354: nodes.inject(0) { |r,n| r += number(string(n)) } 355: end
# File lib/rexml/functions.rb, line 21 21: def Functions::text( ) 22: if @@context[:node].node_type == :element 23: return @@context[:node].find_all{|n| n.node_type == :text}.collect{|n| n.value} 24: elsif @@context[:node].node_type == :text 25: return @@context[:node].value 26: else 27: return false 28: end 29: end
This is entirely Mike Stok‘s beast
# File lib/rexml/functions.rb, line 228 228: def Functions::translate( string, tr1, tr2 ) 229: from = string(tr1) 230: to = string(tr2) 231: 232: # the map is our translation table. 233: # 234: # if a character occurs more than once in the 235: # from string then we ignore the second & 236: # subsequent mappings 237: # 238: # if a character maps to nil then we delete it 239: # in the output. This happens if the from 240: # string is longer than the to string 241: # 242: # there's nothing about - or ^ being special in 243: # http://www.w3.org/TR/xpath#function-translate 244: # so we don't build ranges or negated classes 245: 246: map = Hash.new 247: 0.upto(from.length - 1) { |pos| 248: from_char = from[pos] 249: unless map.has_key? from_char 250: map[from_char] = 251: if pos < to.length 252: to[pos] 253: else 254: nil 255: end 256: end 257: } 258: 259: string(string).unpack('U*').collect { |c| 260: if map.has_key? c then map[c] else c end 261: }.compact.pack('U*') 262: end