rexml 3.1.7.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rexml might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +10 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +60 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/rexml/attlistdecl.rb +63 -0
- data/lib/rexml/attribute.rb +192 -0
- data/lib/rexml/cdata.rb +68 -0
- data/lib/rexml/child.rb +97 -0
- data/lib/rexml/comment.rb +80 -0
- data/lib/rexml/doctype.rb +270 -0
- data/lib/rexml/document.rb +291 -0
- data/lib/rexml/dtd/attlistdecl.rb +11 -0
- data/lib/rexml/dtd/dtd.rb +47 -0
- data/lib/rexml/dtd/elementdecl.rb +18 -0
- data/lib/rexml/dtd/entitydecl.rb +57 -0
- data/lib/rexml/dtd/notationdecl.rb +40 -0
- data/lib/rexml/element.rb +1267 -0
- data/lib/rexml/encoding.rb +51 -0
- data/lib/rexml/entity.rb +171 -0
- data/lib/rexml/formatters/default.rb +112 -0
- data/lib/rexml/formatters/pretty.rb +142 -0
- data/lib/rexml/formatters/transitive.rb +58 -0
- data/lib/rexml/functions.rb +447 -0
- data/lib/rexml/instruction.rb +71 -0
- data/lib/rexml/light/node.rb +196 -0
- data/lib/rexml/namespace.rb +48 -0
- data/lib/rexml/node.rb +76 -0
- data/lib/rexml/output.rb +30 -0
- data/lib/rexml/parent.rb +166 -0
- data/lib/rexml/parseexception.rb +52 -0
- data/lib/rexml/parsers/baseparser.rb +586 -0
- data/lib/rexml/parsers/lightparser.rb +59 -0
- data/lib/rexml/parsers/pullparser.rb +197 -0
- data/lib/rexml/parsers/sax2parser.rb +273 -0
- data/lib/rexml/parsers/streamparser.rb +61 -0
- data/lib/rexml/parsers/treeparser.rb +101 -0
- data/lib/rexml/parsers/ultralightparser.rb +57 -0
- data/lib/rexml/parsers/xpathparser.rb +675 -0
- data/lib/rexml/quickpath.rb +266 -0
- data/lib/rexml/rexml.rb +32 -0
- data/lib/rexml/sax2listener.rb +98 -0
- data/lib/rexml/security.rb +28 -0
- data/lib/rexml/source.rb +298 -0
- data/lib/rexml/streamlistener.rb +93 -0
- data/lib/rexml/syncenumerator.rb +33 -0
- data/lib/rexml/text.rb +424 -0
- data/lib/rexml/undefinednamespaceexception.rb +9 -0
- data/lib/rexml/validation/relaxng.rb +539 -0
- data/lib/rexml/validation/validation.rb +144 -0
- data/lib/rexml/validation/validationexception.rb +10 -0
- data/lib/rexml/xmldecl.rb +116 -0
- data/lib/rexml/xmltokens.rb +85 -0
- data/lib/rexml/xpath.rb +81 -0
- data/lib/rexml/xpath_parser.rb +934 -0
- data/rexml.gemspec +42 -0
- metadata +131 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
require_relative 'streamparser'
|
3
|
+
require_relative 'baseparser'
|
4
|
+
require_relative '../light/node'
|
5
|
+
|
6
|
+
module REXML
|
7
|
+
module Parsers
|
8
|
+
class LightParser
|
9
|
+
def initialize stream
|
10
|
+
@stream = stream
|
11
|
+
@parser = REXML::Parsers::BaseParser.new( stream )
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_listener( listener )
|
15
|
+
@parser.add_listener( listener )
|
16
|
+
end
|
17
|
+
|
18
|
+
def rewind
|
19
|
+
@stream.rewind
|
20
|
+
@parser.stream = @stream
|
21
|
+
end
|
22
|
+
|
23
|
+
def parse
|
24
|
+
root = context = [ :document ]
|
25
|
+
while true
|
26
|
+
event = @parser.pull
|
27
|
+
case event[0]
|
28
|
+
when :end_document
|
29
|
+
break
|
30
|
+
when :start_element, :start_doctype
|
31
|
+
new_node = event
|
32
|
+
context << new_node
|
33
|
+
new_node[1,0] = [context]
|
34
|
+
context = new_node
|
35
|
+
when :end_element, :end_doctype
|
36
|
+
context = context[1]
|
37
|
+
else
|
38
|
+
new_node = event
|
39
|
+
context << new_node
|
40
|
+
new_node[1,0] = [context]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
root
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# An element is an array. The array contains:
|
48
|
+
# 0 The parent element
|
49
|
+
# 1 The tag name
|
50
|
+
# 2 A hash of attributes
|
51
|
+
# 3..-1 The child elements
|
52
|
+
# An element is an array of size > 3
|
53
|
+
# Text is a String
|
54
|
+
# PIs are [ :processing_instruction, target, data ]
|
55
|
+
# Comments are [ :comment, data ]
|
56
|
+
# DocTypes are DocType structs
|
57
|
+
# The root is an array with XMLDecls, Text, DocType, Array, Text
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
require_relative '../parseexception'
|
5
|
+
require_relative 'baseparser'
|
6
|
+
require_relative '../xmltokens'
|
7
|
+
|
8
|
+
module REXML
|
9
|
+
module Parsers
|
10
|
+
# = Using the Pull Parser
|
11
|
+
# <em>This API is experimental, and subject to change.</em>
|
12
|
+
# parser = PullParser.new( "<a>text<b att='val'/>txet</a>" )
|
13
|
+
# while parser.has_next?
|
14
|
+
# res = parser.next
|
15
|
+
# puts res[1]['att'] if res.start_tag? and res[0] == 'b'
|
16
|
+
# end
|
17
|
+
# See the PullEvent class for information on the content of the results.
|
18
|
+
# The data is identical to the arguments passed for the various events to
|
19
|
+
# the StreamListener API.
|
20
|
+
#
|
21
|
+
# Notice that:
|
22
|
+
# parser = PullParser.new( "<a>BAD DOCUMENT" )
|
23
|
+
# while parser.has_next?
|
24
|
+
# res = parser.next
|
25
|
+
# raise res[1] if res.error?
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# Nat Price gave me some good ideas for the API.
|
29
|
+
class PullParser
|
30
|
+
include XMLTokens
|
31
|
+
extend Forwardable
|
32
|
+
|
33
|
+
def_delegators( :@parser, :has_next? )
|
34
|
+
def_delegators( :@parser, :entity )
|
35
|
+
def_delegators( :@parser, :empty? )
|
36
|
+
def_delegators( :@parser, :source )
|
37
|
+
|
38
|
+
def initialize stream
|
39
|
+
@entities = {}
|
40
|
+
@listeners = nil
|
41
|
+
@parser = BaseParser.new( stream )
|
42
|
+
@my_stack = []
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_listener( listener )
|
46
|
+
@listeners = [] unless @listeners
|
47
|
+
@listeners << listener
|
48
|
+
end
|
49
|
+
|
50
|
+
def each
|
51
|
+
while has_next?
|
52
|
+
yield self.pull
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def peek depth=0
|
57
|
+
if @my_stack.length <= depth
|
58
|
+
(depth - @my_stack.length + 1).times {
|
59
|
+
e = PullEvent.new(@parser.pull)
|
60
|
+
@my_stack.push(e)
|
61
|
+
}
|
62
|
+
end
|
63
|
+
@my_stack[depth]
|
64
|
+
end
|
65
|
+
|
66
|
+
def pull
|
67
|
+
return @my_stack.shift if @my_stack.length > 0
|
68
|
+
|
69
|
+
event = @parser.pull
|
70
|
+
case event[0]
|
71
|
+
when :entitydecl
|
72
|
+
@entities[ event[1] ] =
|
73
|
+
event[2] unless event[2] =~ /PUBLIC|SYSTEM/
|
74
|
+
when :text
|
75
|
+
unnormalized = @parser.unnormalize( event[1], @entities )
|
76
|
+
event << unnormalized
|
77
|
+
end
|
78
|
+
PullEvent.new( event )
|
79
|
+
end
|
80
|
+
|
81
|
+
def unshift token
|
82
|
+
@my_stack.unshift token
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# A parsing event. The contents of the event are accessed as an +Array?,
|
87
|
+
# and the type is given either by the ...? methods, or by accessing the
|
88
|
+
# +type+ accessor. The contents of this object vary from event to event,
|
89
|
+
# but are identical to the arguments passed to +StreamListener+s for each
|
90
|
+
# event.
|
91
|
+
class PullEvent
|
92
|
+
# The type of this event. Will be one of :tag_start, :tag_end, :text,
|
93
|
+
# :processing_instruction, :comment, :doctype, :attlistdecl, :entitydecl,
|
94
|
+
# :notationdecl, :entity, :cdata, :xmldecl, or :error.
|
95
|
+
def initialize(arg)
|
96
|
+
@contents = arg
|
97
|
+
end
|
98
|
+
|
99
|
+
def []( start, endd=nil)
|
100
|
+
if start.kind_of? Range
|
101
|
+
@contents.slice( start.begin+1 .. start.end )
|
102
|
+
elsif start.kind_of? Numeric
|
103
|
+
if endd.nil?
|
104
|
+
@contents.slice( start+1 )
|
105
|
+
else
|
106
|
+
@contents.slice( start+1, endd )
|
107
|
+
end
|
108
|
+
else
|
109
|
+
raise "Illegal argument #{start.inspect} (#{start.class})"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def event_type
|
114
|
+
@contents[0]
|
115
|
+
end
|
116
|
+
|
117
|
+
# Content: [ String tag_name, Hash attributes ]
|
118
|
+
def start_element?
|
119
|
+
@contents[0] == :start_element
|
120
|
+
end
|
121
|
+
|
122
|
+
# Content: [ String tag_name ]
|
123
|
+
def end_element?
|
124
|
+
@contents[0] == :end_element
|
125
|
+
end
|
126
|
+
|
127
|
+
# Content: [ String raw_text, String unnormalized_text ]
|
128
|
+
def text?
|
129
|
+
@contents[0] == :text
|
130
|
+
end
|
131
|
+
|
132
|
+
# Content: [ String text ]
|
133
|
+
def instruction?
|
134
|
+
@contents[0] == :processing_instruction
|
135
|
+
end
|
136
|
+
|
137
|
+
# Content: [ String text ]
|
138
|
+
def comment?
|
139
|
+
@contents[0] == :comment
|
140
|
+
end
|
141
|
+
|
142
|
+
# Content: [ String name, String pub_sys, String long_name, String uri ]
|
143
|
+
def doctype?
|
144
|
+
@contents[0] == :start_doctype
|
145
|
+
end
|
146
|
+
|
147
|
+
# Content: [ String text ]
|
148
|
+
def attlistdecl?
|
149
|
+
@contents[0] == :attlistdecl
|
150
|
+
end
|
151
|
+
|
152
|
+
# Content: [ String text ]
|
153
|
+
def elementdecl?
|
154
|
+
@contents[0] == :elementdecl
|
155
|
+
end
|
156
|
+
|
157
|
+
# Due to the wonders of DTDs, an entity declaration can be just about
|
158
|
+
# anything. There's no way to normalize it; you'll have to interpret the
|
159
|
+
# content yourself. However, the following is true:
|
160
|
+
#
|
161
|
+
# * If the entity declaration is an internal entity:
|
162
|
+
# [ String name, String value ]
|
163
|
+
# Content: [ String text ]
|
164
|
+
def entitydecl?
|
165
|
+
@contents[0] == :entitydecl
|
166
|
+
end
|
167
|
+
|
168
|
+
# Content: [ String text ]
|
169
|
+
def notationdecl?
|
170
|
+
@contents[0] == :notationdecl
|
171
|
+
end
|
172
|
+
|
173
|
+
# Content: [ String text ]
|
174
|
+
def entity?
|
175
|
+
@contents[0] == :entity
|
176
|
+
end
|
177
|
+
|
178
|
+
# Content: [ String text ]
|
179
|
+
def cdata?
|
180
|
+
@contents[0] == :cdata
|
181
|
+
end
|
182
|
+
|
183
|
+
# Content: [ String version, String encoding, String standalone ]
|
184
|
+
def xmldecl?
|
185
|
+
@contents[0] == :xmldecl
|
186
|
+
end
|
187
|
+
|
188
|
+
def error?
|
189
|
+
@contents[0] == :error
|
190
|
+
end
|
191
|
+
|
192
|
+
def inspect
|
193
|
+
@contents[0].to_s + ": " + @contents[1..-1].inspect
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,273 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
require_relative 'baseparser'
|
3
|
+
require_relative '../parseexception'
|
4
|
+
require_relative '../namespace'
|
5
|
+
require_relative '../text'
|
6
|
+
|
7
|
+
module REXML
|
8
|
+
module Parsers
|
9
|
+
# SAX2Parser
|
10
|
+
class SAX2Parser
|
11
|
+
def initialize source
|
12
|
+
@parser = BaseParser.new(source)
|
13
|
+
@listeners = []
|
14
|
+
@procs = []
|
15
|
+
@namespace_stack = []
|
16
|
+
@has_listeners = false
|
17
|
+
@tag_stack = []
|
18
|
+
@entities = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def source
|
22
|
+
@parser.source
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_listener( listener )
|
26
|
+
@parser.add_listener( listener )
|
27
|
+
end
|
28
|
+
|
29
|
+
# Listen arguments:
|
30
|
+
#
|
31
|
+
# Symbol, Array, Block
|
32
|
+
# Listen to Symbol events on Array elements
|
33
|
+
# Symbol, Block
|
34
|
+
# Listen to Symbol events
|
35
|
+
# Array, Listener
|
36
|
+
# Listen to all events on Array elements
|
37
|
+
# Array, Block
|
38
|
+
# Listen to :start_element events on Array elements
|
39
|
+
# Listener
|
40
|
+
# Listen to All events
|
41
|
+
#
|
42
|
+
# Symbol can be one of: :start_element, :end_element,
|
43
|
+
# :start_prefix_mapping, :end_prefix_mapping, :characters,
|
44
|
+
# :processing_instruction, :doctype, :attlistdecl, :elementdecl,
|
45
|
+
# :entitydecl, :notationdecl, :cdata, :xmldecl, :comment
|
46
|
+
#
|
47
|
+
# There is an additional symbol that can be listened for: :progress.
|
48
|
+
# This will be called for every event generated, passing in the current
|
49
|
+
# stream position.
|
50
|
+
#
|
51
|
+
# Array contains regular expressions or strings which will be matched
|
52
|
+
# against fully qualified element names.
|
53
|
+
#
|
54
|
+
# Listener must implement the methods in SAX2Listener
|
55
|
+
#
|
56
|
+
# Block will be passed the same arguments as a SAX2Listener method would
|
57
|
+
# be, where the method name is the same as the matched Symbol.
|
58
|
+
# See the SAX2Listener for more information.
|
59
|
+
def listen( *args, &blok )
|
60
|
+
if args[0].kind_of? Symbol
|
61
|
+
if args.size == 2
|
62
|
+
args[1].each { |match| @procs << [args[0], match, blok] }
|
63
|
+
else
|
64
|
+
add( [args[0], nil, blok] )
|
65
|
+
end
|
66
|
+
elsif args[0].kind_of? Array
|
67
|
+
if args.size == 2
|
68
|
+
args[0].each { |match| add( [nil, match, args[1]] ) }
|
69
|
+
else
|
70
|
+
args[0].each { |match| add( [ :start_element, match, blok ] ) }
|
71
|
+
end
|
72
|
+
else
|
73
|
+
add([nil, nil, args[0]])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def deafen( listener=nil, &blok )
|
78
|
+
if listener
|
79
|
+
@listeners.delete_if {|item| item[-1] == listener }
|
80
|
+
@has_listeners = false if @listeners.size == 0
|
81
|
+
else
|
82
|
+
@procs.delete_if {|item| item[-1] == blok }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse
|
87
|
+
@procs.each { |sym,match,block| block.call if sym == :start_document }
|
88
|
+
@listeners.each { |sym,match,block|
|
89
|
+
block.start_document if sym == :start_document or sym.nil?
|
90
|
+
}
|
91
|
+
context = []
|
92
|
+
while true
|
93
|
+
event = @parser.pull
|
94
|
+
case event[0]
|
95
|
+
when :end_document
|
96
|
+
handle( :end_document )
|
97
|
+
break
|
98
|
+
when :start_doctype
|
99
|
+
handle( :doctype, *event[1..-1])
|
100
|
+
when :end_doctype
|
101
|
+
context = context[1]
|
102
|
+
when :start_element
|
103
|
+
@tag_stack.push(event[1])
|
104
|
+
# find the observers for namespaces
|
105
|
+
procs = get_procs( :start_prefix_mapping, event[1] )
|
106
|
+
listeners = get_listeners( :start_prefix_mapping, event[1] )
|
107
|
+
if procs or listeners
|
108
|
+
# break out the namespace declarations
|
109
|
+
# The attributes live in event[2]
|
110
|
+
event[2].each {|n, v| event[2][n] = @parser.normalize(v)}
|
111
|
+
nsdecl = event[2].find_all { |n, value| n =~ /^xmlns(:|$)/ }
|
112
|
+
nsdecl.collect! { |n, value| [ n[6..-1], value ] }
|
113
|
+
@namespace_stack.push({})
|
114
|
+
nsdecl.each do |n,v|
|
115
|
+
@namespace_stack[-1][n] = v
|
116
|
+
# notify observers of namespaces
|
117
|
+
procs.each { |ob| ob.call( n, v ) } if procs
|
118
|
+
listeners.each { |ob| ob.start_prefix_mapping(n, v) } if listeners
|
119
|
+
end
|
120
|
+
end
|
121
|
+
event[1] =~ Namespace::NAMESPLIT
|
122
|
+
prefix = $1
|
123
|
+
local = $2
|
124
|
+
uri = get_namespace(prefix)
|
125
|
+
# find the observers for start_element
|
126
|
+
procs = get_procs( :start_element, event[1] )
|
127
|
+
listeners = get_listeners( :start_element, event[1] )
|
128
|
+
# notify observers
|
129
|
+
procs.each { |ob| ob.call( uri, local, event[1], event[2] ) } if procs
|
130
|
+
listeners.each { |ob|
|
131
|
+
ob.start_element( uri, local, event[1], event[2] )
|
132
|
+
} if listeners
|
133
|
+
when :end_element
|
134
|
+
@tag_stack.pop
|
135
|
+
event[1] =~ Namespace::NAMESPLIT
|
136
|
+
prefix = $1
|
137
|
+
local = $2
|
138
|
+
uri = get_namespace(prefix)
|
139
|
+
# find the observers for start_element
|
140
|
+
procs = get_procs( :end_element, event[1] )
|
141
|
+
listeners = get_listeners( :end_element, event[1] )
|
142
|
+
# notify observers
|
143
|
+
procs.each { |ob| ob.call( uri, local, event[1] ) } if procs
|
144
|
+
listeners.each { |ob|
|
145
|
+
ob.end_element( uri, local, event[1] )
|
146
|
+
} if listeners
|
147
|
+
|
148
|
+
namespace_mapping = @namespace_stack.pop
|
149
|
+
# find the observers for namespaces
|
150
|
+
procs = get_procs( :end_prefix_mapping, event[1] )
|
151
|
+
listeners = get_listeners( :end_prefix_mapping, event[1] )
|
152
|
+
if procs or listeners
|
153
|
+
namespace_mapping.each do |ns_prefix, ns_uri|
|
154
|
+
# notify observers of namespaces
|
155
|
+
procs.each { |ob| ob.call( ns_prefix ) } if procs
|
156
|
+
listeners.each { |ob| ob.end_prefix_mapping(ns_prefix) } if listeners
|
157
|
+
end
|
158
|
+
end
|
159
|
+
when :text
|
160
|
+
#normalized = @parser.normalize( event[1] )
|
161
|
+
#handle( :characters, normalized )
|
162
|
+
copy = event[1].clone
|
163
|
+
|
164
|
+
esub = proc { |match|
|
165
|
+
if @entities.has_key?($1)
|
166
|
+
@entities[$1].gsub(Text::REFERENCE, &esub)
|
167
|
+
else
|
168
|
+
match
|
169
|
+
end
|
170
|
+
}
|
171
|
+
|
172
|
+
copy.gsub!( Text::REFERENCE, &esub )
|
173
|
+
copy.gsub!( Text::NUMERICENTITY ) {|m|
|
174
|
+
m=$1
|
175
|
+
m = "0#{m}" if m[0] == ?x
|
176
|
+
[Integer(m)].pack('U*')
|
177
|
+
}
|
178
|
+
handle( :characters, copy )
|
179
|
+
when :entitydecl
|
180
|
+
handle_entitydecl( event )
|
181
|
+
when :processing_instruction, :comment, :attlistdecl,
|
182
|
+
:elementdecl, :cdata, :notationdecl, :xmldecl
|
183
|
+
handle( *event )
|
184
|
+
end
|
185
|
+
handle( :progress, @parser.position )
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
private
|
190
|
+
def handle( symbol, *arguments )
|
191
|
+
tag = @tag_stack[-1]
|
192
|
+
procs = get_procs( symbol, tag )
|
193
|
+
listeners = get_listeners( symbol, tag )
|
194
|
+
# notify observers
|
195
|
+
procs.each { |ob| ob.call( *arguments ) } if procs
|
196
|
+
listeners.each { |l|
|
197
|
+
l.send( symbol.to_s, *arguments )
|
198
|
+
} if listeners
|
199
|
+
end
|
200
|
+
|
201
|
+
def handle_entitydecl( event )
|
202
|
+
@entities[ event[1] ] = event[2] if event.size == 3
|
203
|
+
parameter_reference_p = false
|
204
|
+
case event[2]
|
205
|
+
when "SYSTEM"
|
206
|
+
if event.size == 5
|
207
|
+
if event.last == "%"
|
208
|
+
parameter_reference_p = true
|
209
|
+
else
|
210
|
+
event[4, 0] = "NDATA"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
when "PUBLIC"
|
214
|
+
if event.size == 6
|
215
|
+
if event.last == "%"
|
216
|
+
parameter_reference_p = true
|
217
|
+
else
|
218
|
+
event[5, 0] = "NDATA"
|
219
|
+
end
|
220
|
+
end
|
221
|
+
else
|
222
|
+
parameter_reference_p = (event.size == 4)
|
223
|
+
end
|
224
|
+
event[1, 0] = event.pop if parameter_reference_p
|
225
|
+
handle( event[0], event[1..-1] )
|
226
|
+
end
|
227
|
+
|
228
|
+
# The following methods are duplicates, but it is faster than using
|
229
|
+
# a helper
|
230
|
+
def get_procs( symbol, name )
|
231
|
+
return nil if @procs.size == 0
|
232
|
+
@procs.find_all do |sym, match, block|
|
233
|
+
(
|
234
|
+
(sym.nil? or symbol == sym) and
|
235
|
+
((name.nil? and match.nil?) or match.nil? or (
|
236
|
+
(name == match) or
|
237
|
+
(match.kind_of? Regexp and name =~ match)
|
238
|
+
)
|
239
|
+
)
|
240
|
+
)
|
241
|
+
end.collect{|x| x[-1]}
|
242
|
+
end
|
243
|
+
def get_listeners( symbol, name )
|
244
|
+
return nil if @listeners.size == 0
|
245
|
+
@listeners.find_all do |sym, match, block|
|
246
|
+
(
|
247
|
+
(sym.nil? or symbol == sym) and
|
248
|
+
((name.nil? and match.nil?) or match.nil? or (
|
249
|
+
(name == match) or
|
250
|
+
(match.kind_of? Regexp and name =~ match)
|
251
|
+
)
|
252
|
+
)
|
253
|
+
)
|
254
|
+
end.collect{|x| x[-1]}
|
255
|
+
end
|
256
|
+
|
257
|
+
def add( pair )
|
258
|
+
if pair[-1].respond_to? :call
|
259
|
+
@procs << pair unless @procs.include? pair
|
260
|
+
else
|
261
|
+
@listeners << pair unless @listeners.include? pair
|
262
|
+
@has_listeners = true
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def get_namespace( prefix )
|
267
|
+
uris = (@namespace_stack.find_all { |ns| not ns[prefix].nil? }) ||
|
268
|
+
(@namespace_stack.find { |ns| not ns[nil].nil? })
|
269
|
+
uris[-1][prefix] unless uris.nil? or 0 == uris.size
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|