@@ -7,11 +7,14 @@ module REXML
77 # (2) all method calls from XML will have "-" replaced with "_".
88 # Therefore, in XML, "local-name()" is identical (and actually becomes)
99 # "local_name()"
10- module Functions
10+ class FunctionsClass
1111 @@available_functions = { }
12- @@context = nil
13- @@namespace_context = { }
14- @@variables = { }
12+
13+ def initialize
14+ @context = nil
15+ @namespace_context = { }
16+ @variables = { }
17+ end
1518
1619 INTERNAL_METHODS = [
1720 :namespace_context ,
@@ -23,64 +26,64 @@ module Functions
2326 :send ,
2427 ]
2528 class << self
26- def singleton_method_added ( name )
29+ def method_added ( name )
2730 unless INTERNAL_METHODS . include? ( name )
2831 @@available_functions [ name ] = true
2932 end
3033 end
3134 end
3235
33- def Functions :: namespace_context = ( x ) ; @ @namespace_context= x ; end
34- def Functions :: variables = ( x ) ; @ @variables= x ; end
35- def Functions :: namespace_context ; @ @namespace_context ; end
36- def Functions :: variables ; @ @variables ; end
36+ def namespace_context = ( x ) ; @namespace_context = x ; end
37+ def variables = ( x ) ; @variables = x ; end
38+ def namespace_context ; @namespace_context ; end
39+ def variables ; @variables ; end
3740
38- def Functions :: context = ( value ) ; @ @context = value ; end
41+ def context = ( value ) ; @context = value ; end
3942
4043 # Returns the last node of the given list of nodes.
41- def Functions :: last ( )
42- @@ context [ :size ]
44+ def last ( )
45+ @context [ :size ]
4346 end
4447
45- def Functions :: position ( )
46- @@ context [ :position ]
48+ def position ( )
49+ @context [ :position ]
4750 end
4851
4952 # Returns the size of the given list of nodes.
50- def Functions :: count ( node_set )
53+ def count ( node_set )
5154 node_set . size
5255 end
5356
5457 # Since REXML is non-validating, this method is not implemented as it
5558 # requires a DTD
56- def Functions :: id ( object )
59+ def id ( object )
5760 end
5861
59- def Functions :: local_name ( node_set = nil )
62+ def local_name ( node_set = nil )
6063 get_namespace ( node_set ) do |node |
6164 return node . local_name
6265 end
6366 ""
6467 end
6568
66- def Functions :: namespace_uri ( node_set = nil )
69+ def namespace_uri ( node_set = nil )
6770 get_namespace ( node_set ) do |node |
6871 return node . namespace
6972 end
7073 ""
7174 end
7275
73- def Functions :: name ( node_set = nil )
76+ def name ( node_set = nil )
7477 get_namespace ( node_set ) do |node |
7578 return node . expanded_name
7679 end
7780 ""
7881 end
7982
8083 # Helper method.
81- def Functions :: get_namespace ( node_set = nil )
84+ def get_namespace ( node_set = nil )
8285 if node_set == nil
83- yield @@ context [ :node ] if @ @context[ :node ] . respond_to? ( :namespace )
86+ yield @context [ :node ] if @context [ :node ] . respond_to? ( :namespace )
8487 else
8588 if node_set . respond_to? :each
8689 result = [ ]
@@ -129,7 +132,7 @@ def Functions::get_namespace( node_set = nil )
129132 #
130133 # An object of a type other than the four basic types is converted to a
131134 # string in a way that is dependent on that type.
132- def Functions :: string ( object = @ @context[ :node ] )
135+ def string ( object = @context [ :node ] )
133136 if object . respond_to? ( :node_type )
134137 case object . node_type
135138 when :attribute
@@ -169,7 +172,7 @@ def Functions::string( object=@@context[:node] )
169172 # of each of the children of the node in the
170173 # node-set that is first in document order.
171174 # If the node-set is empty, an empty string is returned.
172- def Functions :: string_value ( o )
175+ def string_value ( o )
173176 rv = ""
174177 o . children . each { |e |
175178 if e . node_type == :text
@@ -181,7 +184,7 @@ def Functions::string_value( o )
181184 rv
182185 end
183186
184- def Functions :: concat ( *objects )
187+ def concat ( *objects )
185188 concatenated = ""
186189 objects . each do |object |
187190 concatenated << string ( object )
@@ -190,17 +193,17 @@ def Functions::concat( *objects )
190193 end
191194
192195 # Fixed by Mike Stok
193- def Functions :: starts_with ( string , test )
196+ def starts_with ( string , test )
194197 string ( string ) . index ( string ( test ) ) == 0
195198 end
196199
197200 # Fixed by Mike Stok
198- def Functions :: contains ( string , test )
201+ def contains ( string , test )
199202 string ( string ) . include? ( string ( test ) )
200203 end
201204
202205 # Kouhei fixed this
203- def Functions :: substring_before ( string , test )
206+ def substring_before ( string , test )
204207 ruby_string = string ( string )
205208 ruby_index = ruby_string . index ( string ( test ) )
206209 if ruby_index . nil?
@@ -211,15 +214,15 @@ def Functions::substring_before( string, test )
211214 end
212215
213216 # Kouhei fixed this too
214- def Functions :: substring_after ( string , test )
217+ def substring_after ( string , test )
215218 ruby_string = string ( string )
216219 return $1 if ruby_string =~ /#{ test } (.*)/
217220 ""
218221 end
219222
220223 # Take equal portions of Mike Stok and Sean Russell; mix
221224 # vigorously, and pour into a tall, chilled glass. Serves 10,000.
222- def Functions :: substring ( string , start , length = nil )
225+ def substring ( string , start , length = nil )
223226 ruby_string = string ( string )
224227 ruby_length = if length . nil?
225228 ruby_string . length . to_f
@@ -252,16 +255,16 @@ def Functions::substring( string, start, length=nil )
252255 end
253256
254257 # UNTESTED
255- def Functions :: string_length ( string )
258+ def string_length ( string )
256259 string ( string ) . length
257260 end
258261
259- def Functions :: normalize_space ( object = @ @context[ :node ] )
262+ def normalize_space ( object = @context [ :node ] )
260263 string ( object ) . strip . gsub ( /\s +/um , ' ' )
261264 end
262265
263266 # This is entirely Mike Stok's beast
264- def Functions :: translate ( string , tr1 , tr2 )
267+ def translate ( string , tr1 , tr2 )
265268 from = string ( tr1 )
266269 to = string ( tr2 )
267270
@@ -303,7 +306,7 @@ def Functions::translate( string, tr1, tr2 )
303306 end
304307 end
305308
306- def Functions :: boolean ( object = @ @context[ :node ] )
309+ def boolean ( object = @context [ :node ] )
307310 case object
308311 when true , false
309312 object
@@ -323,24 +326,24 @@ def Functions::boolean(object=@@context[:node])
323326 end
324327
325328 # UNTESTED
326- def Functions :: not ( object )
329+ def not ( object )
327330 not boolean ( object )
328331 end
329332
330333 # UNTESTED
331- def Functions :: true ( )
334+ def true ( )
332335 true
333336 end
334337
335338 # UNTESTED
336- def Functions :: false ( )
339+ def false ( )
337340 false
338341 end
339342
340343 # UNTESTED
341- def Functions :: lang ( language )
344+ def lang ( language )
342345 lang = false
343- node = @@ context [ :node ]
346+ node = @context [ :node ]
344347 attr = nil
345348 until node . nil?
346349 if node . node_type == :element
@@ -356,7 +359,7 @@ def Functions::lang( language )
356359 lang
357360 end
358361
359- def Functions :: compare_language lang1 , lang2
362+ def compare_language lang1 , lang2
360363 lang2 . downcase . index ( lang1 . downcase ) == 0
361364 end
362365
@@ -373,7 +376,7 @@ def Functions::compare_language lang1, lang2
373376 #
374377 # an object of a type other than the four basic types is converted to a
375378 # number in a way that is dependent on that type
376- def Functions :: number ( object = @ @context[ :node ] )
379+ def number ( object = @context [ :node ] )
377380 case object
378381 when true
379382 Float ( 1 )
@@ -394,20 +397,20 @@ def Functions::number(object=@@context[:node])
394397 end
395398 end
396399
397- def Functions :: sum ( nodes )
400+ def sum ( nodes )
398401 nodes = [ nodes ] unless nodes . kind_of? Array
399402 nodes . inject ( 0 ) { |r , n | r + number ( string ( n ) ) }
400403 end
401404
402- def Functions :: floor ( number )
405+ def floor ( number )
403406 number ( number ) . floor
404407 end
405408
406- def Functions :: ceiling ( number )
409+ def ceiling ( number )
407410 number ( number ) . ceil
408411 end
409412
410- def Functions :: round ( number )
413+ def round ( number )
411414 number = number ( number )
412415 begin
413416 neg = number . negative?
@@ -418,14 +421,19 @@ def Functions::round( number )
418421 end
419422 end
420423
421- def Functions :: send ( name , *args )
424+ def send ( name , *args )
422425 if @@available_functions [ name . to_sym ]
423426 super
424427 else
425428 # TODO: Maybe, this is not XPath spec behavior.
426429 # This behavior must be reconsidered.
427- XPath . match ( @@ context [ :node ] , name . to_s )
430+ XPath . match ( @context [ :node ] , name . to_s )
428431 end
429432 end
430433 end
434+
435+ # Using this singleton instance may cause thread-safety issues
436+ # especially when accessing variables, context and namespace_context.
437+ # Consider instantiating your own FunctionsClass object.
438+ Functions = FunctionsClass . new
431439end
0 commit comments